From 703a5415ac68e620a421190739742321ff191dd9 Mon Sep 17 00:00:00 2001 From: Maximilian Hubert <64627729+gap-editor@users.noreply.github.com> Date: Sun, 1 Mar 2026 04:22:24 +0100 Subject: [PATCH 001/129] fix: typo in README.md (#1390) Corrected the spelling of 'convenience' in the README. --- examples/typescript/legacy/mcp-embedded-wallet/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/typescript/legacy/mcp-embedded-wallet/README.md b/examples/typescript/legacy/mcp-embedded-wallet/README.md index 0c65830ea8..1c669ec86c 100644 --- a/examples/typescript/legacy/mcp-embedded-wallet/README.md +++ b/examples/typescript/legacy/mcp-embedded-wallet/README.md @@ -110,7 +110,7 @@ We now have everything we need on the renderer side. 3. Set up call from electron -Call from electron live in `operations` in `electron.ts` just for convinience. +Call from electron live in `operations` in `electron.ts` just for convenience. You might add something like this ```typescript From b341973062dfd66931d458b7b038d5511107e4ec Mon Sep 17 00:00:00 2001 From: "Ryan R. Fox" Date: Sat, 28 Feb 2026 22:46:24 -0500 Subject: [PATCH 002/129] fix(ts): remove duplicate server ResourceInfo; use wire-format type directly (#1158) --- .../.changeset/remove-duplicate-resource-info.md | 5 +++++ typescript/packages/core/src/server/index.ts | 2 +- .../core/src/server/x402ResourceServer.ts | 16 ++++++---------- 3 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 typescript/.changeset/remove-duplicate-resource-info.md diff --git a/typescript/.changeset/remove-duplicate-resource-info.md b/typescript/.changeset/remove-duplicate-resource-info.md new file mode 100644 index 0000000000..f00a71cf65 --- /dev/null +++ b/typescript/.changeset/remove-duplicate-resource-info.md @@ -0,0 +1,5 @@ +--- +"@x402/core": patch +--- + +Remove duplicate server-local `ResourceInfo` interface; use the wire-format `ResourceInfo` from `types/payments.ts` directly throughout the server module. diff --git a/typescript/packages/core/src/server/index.ts b/typescript/packages/core/src/server/index.ts index 11f96623a2..bf7f61eb84 100644 --- a/typescript/packages/core/src/server/index.ts +++ b/typescript/packages/core/src/server/index.ts @@ -1,5 +1,5 @@ export { x402ResourceServer } from "./x402ResourceServer"; -export type { ResourceConfig, ResourceInfo, SettleResultContext } from "./x402ResourceServer"; +export type { ResourceConfig, SettleResultContext } from "./x402ResourceServer"; export { HTTPFacilitatorClient } from "../http/httpFacilitatorClient"; export type { FacilitatorClient, FacilitatorConfig } from "../http/httpFacilitatorClient"; diff --git a/typescript/packages/core/src/server/x402ResourceServer.ts b/typescript/packages/core/src/server/x402ResourceServer.ts index a5eb4769b2..e1459fd65c 100644 --- a/typescript/packages/core/src/server/x402ResourceServer.ts +++ b/typescript/packages/core/src/server/x402ResourceServer.ts @@ -5,7 +5,12 @@ import { SupportedResponse, SupportedKind, } from "../types/facilitator"; -import { PaymentPayload, PaymentRequirements, PaymentRequired } from "../types/payments"; +import { + PaymentPayload, + PaymentRequirements, + PaymentRequired, + ResourceInfo, +} from "../types/payments"; import { SchemeNetworkServer } from "../types/mechanisms"; import { Price, Network, ResourceServerExtension, VerifyError } from "../types"; import { deepEqual, findByNetworkAndScheme } from "../utils"; @@ -25,15 +30,6 @@ export interface ResourceConfig { extra?: Record; // Scheme-specific additional data } -/** - * Resource information for PaymentRequired response - */ -export interface ResourceInfo { - url: string; - description: string; - mimeType: string; -} - /** * Lifecycle Hook Context Interfaces */ From 8888d6cb8b1e80500ff5c7f993ada68fdfe5c8d8 Mon Sep 17 00:00:00 2001 From: Jia Jian Goi Date: Mon, 2 Mar 2026 15:43:59 +0800 Subject: [PATCH 003/129] chore: update AgentlyHQ's new url (#1411) * feat: add agently to x402 ecosystem * chore: update agently url --- .../site/app/ecosystem/partners-data/agently/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/typescript/site/app/ecosystem/partners-data/agently/metadata.json b/typescript/site/app/ecosystem/partners-data/agently/metadata.json index d876096aad..4140bad5e0 100644 --- a/typescript/site/app/ecosystem/partners-data/agently/metadata.json +++ b/typescript/site/app/ecosystem/partners-data/agently/metadata.json @@ -1,7 +1,7 @@ { "name": "Agently", - "description": "Agently is the routing and settlement layer for agentic commerce. It enables AI agents to discover, orchestrate, and pay other AI agents, tools, and data providers on a per-call basis, at scale through agentic protocols.", + "description": "The way AI coordinates and transacts. Agently is the routing and settlement layer for your agent economy.", "logoUrl": "/logos/agently.png", - "websiteUrl": "https://agently.to", + "websiteUrl": "https://use-agently.com", "category": "Infrastructure & Tooling" } From 205257b6345b772036d51dddf90ada8119a518ed Mon Sep 17 00:00:00 2001 From: phdargen Date: Tue, 3 Mar 2026 10:09:27 +0900 Subject: [PATCH 004/129] Cleanup dependencies and fix example builds (#1355) * clean up dep * fix examples --- .../typescript/facilitator/advanced/README.md | 6 +- .../facilitator/advanced/all_networks.ts | 23 +- .../typescript/facilitator/advanced/bazaar.ts | 38 +- .../facilitator/advanced/package.json | 2 +- .../typescript/facilitator/basic/index.ts | 10 +- .../typescript/fullstack/miniapp/app/page.tsx | 51 +- examples/typescript/pnpm-lock.yaml | 893 +++++++++++++----- examples/typescript/pnpm-workspace.yaml | 2 +- .../typescript/servers/express/package.json | 1 - typescript/.changeset/clear-tables-teach.md | 6 + typescript/packages/http/express/package.json | 2 - typescript/packages/http/next/package.json | 1 - typescript/pnpm-lock.yaml | 35 +- 13 files changed, 769 insertions(+), 301 deletions(-) create mode 100644 typescript/.changeset/clear-tables-teach.md diff --git a/examples/typescript/facilitator/advanced/README.md b/examples/typescript/facilitator/advanced/README.md index d357b0d478..e0fbb94a6a 100644 --- a/examples/typescript/facilitator/advanced/README.md +++ b/examples/typescript/facilitator/advanced/README.md @@ -42,10 +42,10 @@ pnpm dev:bazaar # Bazaar discovery extension Each example demonstrates a specific advanced pattern: -| Example | Command | Description | -| --- | --- | --- | +| Example | Command | Description | +| -------------- | ----------------------- | -------------------------------------------------------- | | `all-networks` | `pnpm dev:all-networks` | All supported networks with optional chain configuration | -| `bazaar` | `pnpm dev:bazaar` | Bazaar discovery extension for cataloging x402 resources | +| `bazaar` | `pnpm dev:bazaar` | Bazaar discovery extension for cataloging x402 resources | ## API Endpoints diff --git a/examples/typescript/facilitator/advanced/all_networks.ts b/examples/typescript/facilitator/advanced/all_networks.ts index 3692fd9b17..c56b07523b 100644 --- a/examples/typescript/facilitator/advanced/all_networks.ts +++ b/examples/typescript/facilitator/advanced/all_networks.ts @@ -50,22 +50,22 @@ const SVM_NETWORK = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"; // Solana Devnet // Initialize the x402 Facilitator const facilitator = new x402Facilitator() - .onBeforeVerify(async context => { + .onBeforeVerify(async (context) => { console.log("Before verify", context); }) - .onAfterVerify(async context => { + .onAfterVerify(async (context) => { console.log("After verify", context); }) - .onVerifyFailure(async context => { + .onVerifyFailure(async (context) => { console.log("Verify failure", context); }) - .onBeforeSettle(async context => { + .onBeforeSettle(async (context) => { console.log("Before settle", context); }) - .onAfterSettle(async context => { + .onAfterSettle(async (context) => { console.log("After settle", context); }) - .onSettleFailure(async context => { + .onSettleFailure(async (context) => { console.log("Settle failure", context); }); @@ -239,7 +239,14 @@ app.get("/health", (req, res) => { // Start the server app.listen(parseInt(PORT), () => { - console.log(`πŸš€ All Networks Facilitator listening on http://localhost:${PORT}`); - console.log(` Supported networks: ${facilitator.getSupported().kinds.map(k => k.network).join(", ")}`); + console.log( + `πŸš€ All Networks Facilitator listening on http://localhost:${PORT}`, + ); + console.log( + ` Supported networks: ${facilitator + .getSupported() + .kinds.map((k) => k.network) + .join(", ")}`, + ); console.log(); }); diff --git a/examples/typescript/facilitator/advanced/bazaar.ts b/examples/typescript/facilitator/advanced/bazaar.ts index d0637f4148..d1a701b560 100644 --- a/examples/typescript/facilitator/advanced/bazaar.ts +++ b/examples/typescript/facilitator/advanced/bazaar.ts @@ -59,13 +59,26 @@ interface DiscoveredResource { } // BazaarCatalog stores discovered resources +/** + * Catalog of discovered resources from bazaar discovery extension. + */ class BazaarCatalog { private resources: Map = new Map(); + /** + * Adds a discovered resource to the catalog. + * + * @param res - The discovered resource to add + */ add(res: DiscoveredResource): void { this.resources.set(res.resource, res); } + /** + * Returns all discovered resources in the catalog. + * + * @returns Array of all discovered resources + */ getAll(): DiscoveredResource[] { return Array.from(this.resources.values()); } @@ -75,10 +88,10 @@ const bazaarCatalog = new BazaarCatalog(); // Initialize the x402 Facilitator with discovery hooks const facilitator = new x402Facilitator() - .onBeforeVerify(async context => { + .onBeforeVerify(async (context) => { console.log("Before verify", context); }) - .onAfterVerify(async context => { + .onAfterVerify(async (context) => { console.log("βœ… Payment verified"); // Extract discovered resource from payment for bazaar catalog @@ -93,7 +106,11 @@ const facilitator = new x402Facilitator() console.log(` πŸ“ Discovered resource: ${discovered.resourceUrl}`); console.log(` πŸ“ Description: ${discovered.description}`); console.log(` πŸ“ MimeType: ${discovered.mimeType}`); - console.log(` πŸ“ Method: ${discovered.method}`); + if ("method" in discovered && discovered.method !== undefined) { + console.log(` πŸ“ Method: ${discovered.method}`); + } else if ("toolName" in discovered) { + console.log(` πŸ“ Tool: ${discovered.toolName}`); + } console.log(` πŸ“ X402Version: ${discovered.x402Version}`); bazaarCatalog.add({ @@ -112,16 +129,16 @@ const facilitator = new x402Facilitator() console.log(` ⚠️ Failed to extract discovery info: ${err}`); } }) - .onVerifyFailure(async context => { + .onVerifyFailure(async (context) => { console.log("Verify failure", context); }) - .onBeforeSettle(async context => { + .onBeforeSettle(async (context) => { console.log("Before settle", context); }) - .onAfterSettle(async context => { + .onAfterSettle(async (context) => { console.log(`πŸŽ‰ Payment settled: ${context.result.transaction}`); }) - .onSettleFailure(async context => { + .onSettleFailure(async (context) => { console.log("Settle failure", context); }); @@ -325,7 +342,12 @@ app.get("/health", (req, res) => { // Start the server app.listen(parseInt(PORT), () => { console.log(`πŸš€ Discovery Facilitator listening on http://localhost:${PORT}`); - console.log(` Supported networks: ${facilitator.getSupported().kinds.map(k => k.network).join(", ")}`); + console.log( + ` Supported networks: ${facilitator + .getSupported() + .kinds.map((k) => k.network) + .join(", ")}`, + ); console.log(` Discovery endpoint: GET /discovery/resources`); console.log(); }); diff --git a/examples/typescript/facilitator/advanced/package.json b/examples/typescript/facilitator/advanced/package.json index 4f8c88d05a..05f03aa129 100644 --- a/examples/typescript/facilitator/advanced/package.json +++ b/examples/typescript/facilitator/advanced/package.json @@ -38,4 +38,4 @@ "tsx": "^4.19.2", "typescript": "^5.7.2" } -} \ No newline at end of file +} diff --git a/examples/typescript/facilitator/basic/index.ts b/examples/typescript/facilitator/basic/index.ts index b9cff1eec3..baf957bea8 100644 --- a/examples/typescript/facilitator/basic/index.ts +++ b/examples/typescript/facilitator/basic/index.ts @@ -116,8 +116,14 @@ const facilitator = new x402Facilitator() }); // Register EVM and SVM schemes -facilitator.register("eip155:84532", new ExactEvmScheme(evmSigner, { deployERC4337WithEIP6492: true })); // Base Sepolia -facilitator.register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme(svmSigner)); // Devnet +facilitator.register( + "eip155:84532", + new ExactEvmScheme(evmSigner, { deployERC4337WithEIP6492: true }), +); // Base Sepolia +facilitator.register( + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + new ExactSvmScheme(svmSigner), +); // Devnet // Initialize Express app const app = express(); diff --git a/examples/typescript/fullstack/miniapp/app/page.tsx b/examples/typescript/fullstack/miniapp/app/page.tsx index 75ef8a3a7c..5aca262219 100644 --- a/examples/typescript/fullstack/miniapp/app/page.tsx +++ b/examples/typescript/fullstack/miniapp/app/page.tsx @@ -15,35 +15,53 @@ import { WalletDropdownDisconnect, } from "@coinbase/onchainkit/wallet"; import { useEffect, useMemo, useState, useCallback } from "react"; -import { useAccount, useWalletClient, useSwitchChain } from "wagmi"; +import { useAccount, useWalletClient, useSwitchChain, usePublicClient } from "wagmi"; import { baseSepolia } from "wagmi/chains"; import { sdk } from "@farcaster/miniapp-sdk"; import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { toClientEvmSigner } from "@x402/evm"; import type { ClientEvmSigner } from "@x402/evm"; import type { WalletClient, Account } from "viem"; /** * Converts a wagmi/viem WalletClient to a ClientEvmSigner for x402Client */ -function wagmiToClientSigner(walletClient: WalletClient): ClientEvmSigner { +function wagmiToClientSigner( + walletClient: WalletClient, + publicClient: { readContract: (args: unknown) => Promise } +): ClientEvmSigner { if (!walletClient.account) { throw new Error("Wallet client must have an account"); } - return { - address: walletClient.account.address, - signTypedData: async (message) => { - const signature = await walletClient.signTypedData({ - account: walletClient.account as Account, - domain: message.domain, - types: message.types, - primaryType: message.primaryType, - message: message.message, - }); - return signature; + const readContractAdapter = { + readContract(args: { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args?: readonly unknown[]; + }): Promise { + return publicClient.readContract(args); }, }; + + return toClientEvmSigner( + { + address: walletClient.account.address, + signTypedData: async (message) => { + const signature = await walletClient.signTypedData({ + account: walletClient.account as Account, + domain: message.domain, + types: message.types, + primaryType: message.primaryType, + message: message.message, + }); + return signature; + }, + }, + readContractAdapter + ); } export default function App() { @@ -54,6 +72,7 @@ export default function App() { const [message, setMessage] = useState(""); const { address, isConnected, chainId } = useAccount(); const { data: walletClient } = useWalletClient(); + const publicClient = usePublicClient(); const { switchChainAsync } = useSwitchChain(); sdk.actions.ready(); @@ -96,7 +115,7 @@ export default function App() { }, [addFrame]); const handleProtectedAction = useCallback(async () => { - if (!isConnected || !walletClient) { + if (!isConnected || !walletClient || !publicClient) { setMessage("Please connect your wallet first"); return; } @@ -112,7 +131,7 @@ export default function App() { // Create x402 client and register EVM scheme with wagmi signer const client = new x402Client(); - const signer = wagmiToClientSigner(walletClient); + const signer = wagmiToClientSigner(walletClient, publicClient); client.register("eip155:*", new ExactEvmScheme(signer)); // Wrap fetch with payment handling @@ -137,7 +156,7 @@ export default function App() { } finally { setIsLoading(false); } - }, [isConnected, walletClient, chainId, switchChainAsync]); + }, [isConnected, walletClient, publicClient, chainId, switchChainAsync]); const saveFrameButton = useMemo(() => { if (context && !context.client.added) { diff --git a/examples/typescript/pnpm-lock.yaml b/examples/typescript/pnpm-lock.yaml index c3c6d73c07..024cf50dd3 100644 --- a/examples/typescript/pnpm-lock.yaml +++ b/examples/typescript/pnpm-lock.yaml @@ -200,12 +200,6 @@ importers: ../../typescript/packages/http/express: dependencies: - '@coinbase/cdp-sdk': - specifier: ^1.22.0 - version: 1.36.0(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@solana/kit': - specifier: ^6.1.0 - version: 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@x402/core': specifier: workspace:~ version: link:../../core @@ -398,9 +392,6 @@ importers: ../../typescript/packages/http/next: dependencies: - '@coinbase/cdp-sdk': - specifier: ^1.22.0 - version: 1.36.0(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@x402/core': specifier: workspace:~ version: link:../../core @@ -1578,7 +1569,7 @@ importers: version: 16.6.1 openai: specifier: ^4.77.3 - version: 4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + version: 4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) viem: specifier: ^2.39.0 version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -1727,11 +1718,145 @@ importers: specifier: ^5.3.0 version: 5.9.2 + facilitator/advanced: + dependencies: + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana/kit': + specifier: ^6.1.0 + version: 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(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.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.33.0 + '@types/express': + specifier: ^4.17.21 + version: 4.17.25 + '@types/node': + specifier: ^22.10.1 + version: 22.17.2 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.15.0 + version: 9.33.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.6.2) + prettier: + specifier: ^3.3.3 + version: 3.6.2 + tsx: + specifier: ^4.19.2 + version: 4.20.4 + typescript: + specifier: ^5.7.2 + version: 5.9.2 + + facilitator/basic: + dependencies: + '@scure/base': + specifier: ^1.2.6 + version: 1.2.6 + '@solana/kit': + specifier: ^6.1.0 + version: 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(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.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.33.0 + '@types/express': + specifier: ^4.17.21 + version: 4.17.25 + '@types/node': + specifier: ^22.10.1 + version: 22.17.2 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.15.0 + version: 9.33.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.6.2) + prettier: + specifier: ^3.3.3 + version: 3.6.2 + tsx: + specifier: ^4.19.2 + version: 4.20.4 + typescript: + specifier: ^5.7.2 + version: 5.9.2 + fullstack/miniapp: dependencies: '@coinbase/onchainkit': specifier: 1.1.2 - version: 1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13) + version: 1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(zod@4.1.13) '@farcaster/miniapp-sdk': specifier: 0.2.1 version: 0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) @@ -1764,7 +1889,7 @@ importers: version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) wagmi: specifier: ^2.14.11 - version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) devDependencies: '@eslint/js': specifier: ^9.24.0 @@ -2345,7 +2470,7 @@ importers: dependencies: '@coinbase/onchainkit': specifier: ^0.38.14 - version: 0.38.19(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + version: 0.38.19(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) '@farcaster/frame-sdk': specifier: ^0.0.60 version: 0.0.60(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) @@ -2375,7 +2500,7 @@ importers: version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) wagmi: specifier: ^2.14.11 - version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) x402-fetch: specifier: workspace:* version: link:../../../../../typescript/packages/legacy/x402-fetch @@ -2497,7 +2622,7 @@ importers: dependencies: '@coinbase/onchainkit': specifier: 0.38.14 - version: 0.38.14(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + version: 0.38.14(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) '@tanstack/react-query': specifier: ^5 version: 5.90.11(react@19.2.3) @@ -2515,7 +2640,7 @@ importers: version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) wagmi: specifier: ^2.15.6 - version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) x402: specifier: workspace:* version: link:../../../../../typescript/packages/legacy/x402 @@ -2921,9 +3046,6 @@ importers: servers/express: dependencies: - '@coinbase/x402': - specifier: ^2.1.0 - version: 2.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@x402/core': specifier: workspace:* version: link:../../../../typescript/packages/core @@ -3166,6 +3288,70 @@ importers: specifier: ^5.3.0 version: 5.9.2 + servers/receipt-attestation: + 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.4.7 + version: 16.6.1 + express: + specifier: ^4.18.2 + version: 4.21.2 + viem: + specifier: ^2.39.0 + version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.33.0 + '@types/express': + specifier: ^5.0.1 + version: 5.0.3 + '@types/node': + specifier: ^20.0.0 + version: 20.19.11 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.24.0 + version: 9.33.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.4 + typescript: + specifier: ^5.3.0 + version: 5.9.2 + servers/sign-in-with-x: dependencies: '@x402/core': @@ -3929,9 +4115,6 @@ packages: '@coinbase/wallet-sdk@4.3.6': resolution: {integrity: sha512-4q8BNG1ViL4mSAAvPAtpwlOs1gpC+67eQtgIwNvT3xyeyFFd+guwkc8bcX5rTmQhXpqnhzC4f0obACbP9CqMSA==} - '@coinbase/x402@2.1.0': - resolution: {integrity: sha512-aKeM+cz//+FjzPVu/zgz7830x0KLtKarwCyxoeC71QgCn+Xcf0NhFpn3Qyw0H496y5YOuR/IQ67gP8DZ/hXFqQ==} - '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} @@ -7639,9 +7822,15 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/express-serve-static-core@4.19.8': + resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} + '@types/express-serve-static-core@5.0.7': resolution: {integrity: sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==} + '@types/express@4.17.25': + resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + '@types/express@5.0.3': resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==} @@ -8166,9 +8355,6 @@ packages: '@walletconnect/window-metadata@1.0.1': resolution: {integrity: sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==} - '@x402/core@2.3.1': - resolution: {integrity: sha512-CWvsf09tslISoVOzQ2TIoBLBP+bUycPsYmmRVe3EV5X2FtD7eXXpiPsiXLEVtWP7zhqLNP/5OIATsA2hSVLSfw==} - '@xmldom/xmldom@0.8.11': resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} engines: {node: '>=10.0.0'} @@ -14138,9 +14324,9 @@ snapshots: - ws - zod - '@base-org/account@2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13)': + '@base-org/account@2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': dependencies: - '@coinbase/cdp-sdk': 1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@coinbase/cdp-sdk': 1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@noble/hashes': 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 @@ -14163,9 +14349,9 @@ snapshots: - ws - zod - '@base-org/account@2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13)': + '@base-org/account@2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': dependencies: - '@coinbase/cdp-sdk': 1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@coinbase/cdp-sdk': 1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@noble/hashes': 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 @@ -14336,29 +14522,6 @@ snapshots: - utf-8-validate - ws - '@coinbase/cdp-sdk@1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)': - dependencies: - '@solana-program/system': 0.8.1(@solana/kit@3.0.3(typescript@5.9.2)) - '@solana-program/token': 0.6.0(@solana/kit@3.0.3(typescript@5.9.2)) - '@solana/kit': 3.0.3(typescript@5.9.2) - '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10) - abitype: 1.0.6(typescript@5.9.2)(zod@3.25.76) - axios: 1.13.2 - axios-retry: 4.5.0(axios@1.13.2) - jose: 6.0.12 - md5: 2.3.0 - uncrypto: 0.1.3 - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - zod: 3.25.76 - transitivePeerDependencies: - - bufferutil - - debug - - encoding - - fastestsmallesttextencoderdecoder - - typescript - - utf-8-validate - - ws - '@coinbase/coinbase-sdk@0.20.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@scure/bip32': 1.7.0 @@ -14382,7 +14545,7 @@ snapshots: - utf-8-validate - zod - '@coinbase/onchainkit@0.38.14(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + '@coinbase/onchainkit@0.38.14(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': dependencies: '@farcaster/frame-sdk': 0.0.60(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@farcaster/frame-wagmi-connector': 0.0.42(@farcaster/frame-sdk@0.0.60(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) @@ -14396,7 +14559,7 @@ snapshots: react-dom: 19.2.3(react@19.2.3) tailwind-merge: 2.6.0 viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -14487,7 +14650,7 @@ snapshots: - ws - zod - '@coinbase/onchainkit@0.38.19(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13)': + '@coinbase/onchainkit@0.38.19(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': dependencies: '@farcaster/frame-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@farcaster/miniapp-wagmi-connector': 1.0.0(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) @@ -14501,7 +14664,7 @@ snapshots: react-dom: 19.2.3(react@19.2.3) tailwind-merge: 2.6.0 viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -14540,7 +14703,7 @@ snapshots: - ws - zod - '@coinbase/onchainkit@1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13)': + '@coinbase/onchainkit@1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(zod@4.1.13)': dependencies: '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@farcaster/miniapp-wagmi-connector': 1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) @@ -14561,7 +14724,7 @@ snapshots: tailwind-merge: 3.4.0 usehooks-ts: 3.1.1(react@19.2.3) viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@tanstack/query-core' - '@types/react' @@ -14708,21 +14871,6 @@ snapshots: - utf-8-validate - zod - '@coinbase/x402@2.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@coinbase/cdp-sdk': 1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@x402/core': 2.3.1 - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - zod: 3.25.76 - transitivePeerDependencies: - - bufferutil - - debug - - encoding - - fastestsmallesttextencoderdecoder - - typescript - - utf-8-validate - - ws - '@colors/colors@1.6.0': {} '@craftamap/esbuild-plugin-html@0.9.0(bufferutil@4.0.9)(esbuild@0.25.9)(utf-8-validate@5.0.10)': @@ -17364,7 +17512,7 @@ snapshots: dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -17398,7 +17546,7 @@ snapshots: dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -18075,7 +18223,7 @@ snapshots: '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -18112,7 +18260,7 @@ snapshots: '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -18290,7 +18438,7 @@ snapshots: '@reown/appkit-utils': 1.7.8(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.10)(react@19.2.3))(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) @@ -18332,7 +18480,7 @@ snapshots: '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) @@ -18555,10 +18703,6 @@ snapshots: dependencies: '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/system@0.8.1(@solana/kit@3.0.3(typescript@5.9.2))': - dependencies: - '@solana/kit': 3.0.3(typescript@5.9.2) - '@solana-program/token-2022@0.4.2(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2))': dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) @@ -18586,10 +18730,6 @@ snapshots: dependencies: '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/token@0.6.0(@solana/kit@3.0.3(typescript@5.9.2))': - dependencies: - '@solana/kit': 3.0.3(typescript@5.9.2) - '@solana-program/token@0.9.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -19225,33 +19365,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/kit@3.0.3(typescript@5.9.2)': - dependencies: - '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/codecs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/errors': 3.0.3(typescript@5.9.2) - '@solana/functional': 3.0.3(typescript@5.9.2) - '@solana/instruction-plans': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/instructions': 3.0.3(typescript@5.9.2) - '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/programs': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/rpc-parsed-types': 3.0.3(typescript@5.9.2) - '@solana/rpc-spec-types': 3.0.3(typescript@5.9.2) - '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/signers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/sysvars': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/transaction-confirmation': 3.0.3(typescript@5.9.2) - '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - typescript: 5.9.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - - '@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) @@ -20404,23 +20518,6 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@3.0.3(typescript@5.9.2)': - dependencies: - '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/errors': 3.0.3(typescript@5.9.2) - '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/promises': 3.0.3(typescript@5.9.2) - '@solana/rpc': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - typescript: 5.9.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - '@solana/transaction-confirmation@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) @@ -20940,6 +21037,13 @@ snapshots: '@types/estree@1.0.8': {} + '@types/express-serve-static-core@4.19.8': + dependencies: + '@types/node': 22.17.2 + '@types/qs': 6.14.0 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.5 + '@types/express-serve-static-core@5.0.7': dependencies: '@types/node': 22.17.2 @@ -20947,6 +21051,13 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 0.17.5 + '@types/express@4.17.25': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 4.19.8 + '@types/qs': 6.14.0 + '@types/serve-static': 1.15.8 + '@types/express@5.0.3': dependencies: '@types/body-parser': 1.19.6 @@ -21536,19 +21647,19 @@ snapshots: - utf-8-validate - zod - '@wagmi/connectors@6.2.0(7c0fb5ad6e91c192e500875cd884eb4c)': + '@wagmi/connectors@6.2.0(1aee367860625464d156864b651beb8c)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(utf-8-validate@5.0.10)(zod@3.25.76) - '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@base-org/account': 2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.1.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.1.1))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.1.1))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.1.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -21589,19 +21700,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(826cb7847d3729c23c5bbd1840c9486a)': + '@wagmi/connectors@6.2.0(26b6de6e2b894d3d8ec3de3fd9d7a34e)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) - '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -21642,19 +21753,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13)': + '@wagmi/connectors@6.2.0(7c0fb5ad6e91c192e500875cd884eb4c)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.1.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.1.1))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.1.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.1.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.1.1))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.1.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -21695,19 +21806,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13)': + '@wagmi/connectors@6.2.0(826cb7847d3729c23c5bbd1840c9486a)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@gemini-wallet/core': 0.3.2(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -21748,19 +21859,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13)': + '@wagmi/connectors@6.2.0(87f53a8d2b85f9075dbb2195dfb00723)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@gemini-wallet/core': 0.3.2(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -21801,19 +21912,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13)': + '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@gemini-wallet/core': 0.3.2(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -21854,19 +21965,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13)': + '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@gemini-wallet/core': 0.3.2(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -22221,6 +22332,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/core@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/window-getters': 1.0.1 + es-toolkit: 1.33.0 + events: 3.3.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/core@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/heartbeat': 1.2.2 @@ -22307,6 +22461,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/core@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/window-getters': 1.0.1 + es-toolkit: 1.33.0 + events: 3.3.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/environment@1.0.1': dependencies: tslib: 1.14.1 @@ -22439,10 +22636,10 @@ snapshots: '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/utils': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -22479,10 +22676,10 @@ snapshots: '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/utils': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -22673,6 +22870,41 @@ snapshots: - utf-8-validate - zod + '@walletconnect/sign-client@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/core': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/sign-client@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/core': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -22743,6 +22975,41 @@ snapshots: - utf-8-validate - zod + '@walletconnect/sign-client@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/core': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/time@1.0.2': dependencies: tslib: 1.14.1 @@ -22881,6 +23148,45 @@ snapshots: - utf-8-validate - zod + '@walletconnect/universal-provider@2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/sign-client': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + es-toolkit: 1.33.0 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/universal-provider@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/events': 1.0.1 @@ -22959,6 +23265,45 @@ snapshots: - utf-8-validate - zod + '@walletconnect/universal-provider@2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + es-toolkit: 1.33.0 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/utils@2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 @@ -23045,6 +23390,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/utils@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@noble/ciphers': 1.2.1 + '@noble/curves': 1.8.1 + '@noble/hashes': 1.7.1 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + bs58: 6.0.0 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 + viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + 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/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/utils@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 @@ -23131,6 +23519,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/utils@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@noble/ciphers': 1.2.1 + '@noble/curves': 1.8.1 + '@noble/hashes': 1.7.1 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + bs58: 6.0.0 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 + viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + 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/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/window-getters@1.0.1': dependencies: tslib: 1.14.1 @@ -23140,10 +23571,6 @@ snapshots: '@walletconnect/window-getters': 1.0.1 tslib: 1.14.1 - '@x402/core@2.3.1': - dependencies: - zod: 3.25.76 - '@xmldom/xmldom@0.8.11': {} abbrev@1.1.1: {} @@ -24885,6 +25312,15 @@ snapshots: optionalDependencies: eslint-config-prettier: 10.1.8(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.6.2): + dependencies: + eslint: 9.33.0(jiti@2.6.1) + prettier: 3.6.2 + prettier-linter-helpers: 1.0.0 + synckit: 0.11.11 + optionalDependencies: + eslint-config-prettier: 10.1.8(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-react-hooks@5.2.0(eslint@8.57.1): dependencies: eslint: 8.57.1 @@ -26690,21 +27126,6 @@ snapshots: dependencies: mimic-fn: 2.1.0 - openai@4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): - dependencies: - '@types/node': 18.19.123 - '@types/node-fetch': 2.6.13 - abort-controller: 3.0.0 - agentkeepalive: 4.6.0 - form-data-encoder: 1.7.2 - formdata-node: 4.4.1 - node-fetch: 2.7.0(encoding@0.1.13) - optionalDependencies: - ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) - zod: 3.25.76 - transitivePeerDependencies: - - encoding - openai@4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): dependencies: '@types/node': 18.19.123 @@ -27175,7 +27596,7 @@ snapshots: - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)): dependencies: '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) hono: 4.10.7 @@ -27189,13 +27610,13 @@ snapshots: '@tanstack/react-query': 5.90.11(react@19.2.3) react: 19.2.3 typescript: 5.9.2 - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@types/react' - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)): dependencies: '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) hono: 4.10.7 @@ -27209,13 +27630,13 @@ snapshots: '@tanstack/react-query': 5.90.11(react@19.2.3) react: 19.2.3 typescript: 5.9.2 - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@types/react' - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)): dependencies: '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) hono: 4.10.7 @@ -27229,13 +27650,13 @@ snapshots: '@tanstack/react-query': 5.90.11(react@19.2.3) react: 19.2.3 typescript: 5.9.2 - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@types/react' - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)): dependencies: '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) hono: 4.10.7 @@ -27249,13 +27670,13 @@ snapshots: '@tanstack/react-query': 5.90.11(react@19.2.3) react: 19.2.3 typescript: 5.9.2 - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@types/react' - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)): dependencies: '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) hono: 4.10.7 @@ -27269,7 +27690,7 @@ snapshots: '@tanstack/react-query': 5.90.11(react@19.2.3) react: 19.2.3 typescript: 5.9.2 - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@types/react' - immer @@ -29292,10 +29713,10 @@ snapshots: - ws - zod - wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13): dependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13) + '@wagmi/connectors': 6.2.0(26b6de6e2b894d3d8ec3de3fd9d7a34e) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) @@ -29337,10 +29758,10 @@ snapshots: - ws - zod - wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13): dependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13) + '@wagmi/connectors': 6.2.0(87f53a8d2b85f9075dbb2195dfb00723) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) @@ -29382,10 +29803,10 @@ snapshots: - ws - zod - wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13): dependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13) + '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) @@ -29427,10 +29848,10 @@ snapshots: - ws - zod - wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13): dependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13) + '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) @@ -29472,10 +29893,10 @@ snapshots: - ws - zod - wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13): dependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(zod@4.1.13))(zod@4.1.13) + '@wagmi/connectors': 6.2.0(1aee367860625464d156864b651beb8c) '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) diff --git a/examples/typescript/pnpm-workspace.yaml b/examples/typescript/pnpm-workspace.yaml index ef34f7b6d5..c98a039f40 100644 --- a/examples/typescript/pnpm-workspace.yaml +++ b/examples/typescript/pnpm-workspace.yaml @@ -2,7 +2,7 @@ packages: - "clients/*" - "servers/*" - "fullstack/*" - - "facilitator" + - "facilitator/*" - "legacy/facilitator" - "legacy/servers/*" - "legacy/clients/*" diff --git a/examples/typescript/servers/express/package.json b/examples/typescript/servers/express/package.json index 690dd8ae8f..adcbe1f6a8 100644 --- a/examples/typescript/servers/express/package.json +++ b/examples/typescript/servers/express/package.json @@ -10,7 +10,6 @@ "lint:check": "eslint . --ext .ts" }, "dependencies": { - "@coinbase/x402": "^2.1.0", "@x402/core": "workspace:*", "@x402/evm": "workspace:*", "@x402/express": "workspace:*", diff --git a/typescript/.changeset/clear-tables-teach.md b/typescript/.changeset/clear-tables-teach.md new file mode 100644 index 0000000000..ae20548dd7 --- /dev/null +++ b/typescript/.changeset/clear-tables-teach.md @@ -0,0 +1,6 @@ +--- +'@x402/express': patch +'@x402/next': patch +--- + +Cleaned up dependencies diff --git a/typescript/packages/http/express/package.json b/typescript/packages/http/express/package.json index 4dd076bde3..60fb267ca6 100644 --- a/typescript/packages/http/express/package.json +++ b/typescript/packages/http/express/package.json @@ -40,8 +40,6 @@ "vitest": "^3.0.5" }, "dependencies": { - "@coinbase/cdp-sdk": "^1.22.0", - "@solana/kit": "^6.1.0", "@x402/core": "workspace:~", "@x402/extensions": "workspace:~", "viem": "^2.39.3", diff --git a/typescript/packages/http/next/package.json b/typescript/packages/http/next/package.json index 3c50e7f62f..0b4254327e 100644 --- a/typescript/packages/http/next/package.json +++ b/typescript/packages/http/next/package.json @@ -38,7 +38,6 @@ "vitest": "^3.0.5" }, "dependencies": { - "@coinbase/cdp-sdk": "^1.22.0", "@x402/core": "workspace:~", "@x402/extensions": "workspace:~", "zod": "^3.24.2" diff --git a/typescript/pnpm-lock.yaml b/typescript/pnpm-lock.yaml index 0666c69bc8..57092af693 100644 --- a/typescript/pnpm-lock.yaml +++ b/typescript/pnpm-lock.yaml @@ -209,12 +209,6 @@ importers: packages/http/express: dependencies: - '@coinbase/cdp-sdk': - specifier: ^1.22.0 - version: 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/kit': - specifier: ^6.1.0 - version: 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) '@x402/core': specifier: workspace:~ version: link:../../core @@ -407,9 +401,6 @@ importers: packages/http/next: dependencies: - '@coinbase/cdp-sdk': - specifier: ^1.22.0 - version: 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) '@x402/core': specifier: workspace:~ version: link:../../core @@ -491,7 +482,7 @@ importers: version: 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/transaction-confirmation': specifier: ^2.1.1 - version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) '@solana/wallet-standard-features': specifier: ^1.3.0 version: 1.3.0 @@ -609,7 +600,7 @@ importers: version: 0.11.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) '@solana-program/token': specifier: ^0.9.0 - version: 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) '@solana-program/token-2022': specifier: ^0.6.1 version: 0.6.1(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) @@ -1230,7 +1221,7 @@ importers: version: 0.11.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) '@solana-program/token': specifier: ^0.9.0 - version: 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) '@solana-program/token-2022': specifier: ^0.6.1 version: 0.6.1(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) @@ -9393,8 +9384,8 @@ snapshots: '@coinbase/cdp-sdk@1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: - '@solana-program/system': 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@solana-program/token': 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@solana-program/system': 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) + '@solana-program/token': 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) abitype: 1.0.6(typescript@5.9.3)(zod@3.25.76) @@ -10977,7 +10968,7 @@ snapshots: dependencies: '@solana/kit': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana-program/system@0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@solana-program/system@0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -10995,7 +10986,7 @@ snapshots: dependencies: '@solana/kit': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana-program/token@0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@solana-program/token@0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))': dependencies: '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -11652,14 +11643,14 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.9.3)(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.3.0(typescript@5.9.3) '@solana/functional': 2.3.0(typescript@5.9.3) '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.3) '@solana/subscribable': 2.3.0(typescript@5.9.3) typescript: 5.9.3 - ws: 8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) '@solana/rpc-subscriptions-channel-websocket@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': dependencies: @@ -11713,7 +11704,7 @@ snapshots: optionalDependencies: typescript: 5.9.3 - '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.3.0(typescript@5.9.3) '@solana/fast-stable-stringify': 2.3.0(typescript@5.9.3) @@ -11721,7 +11712,7 @@ snapshots: '@solana/promises': 2.3.0(typescript@5.9.3) '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.9.3)(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.3) '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) @@ -11988,7 +11979,7 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) @@ -11996,7 +11987,7 @@ snapshots: '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/promises': 2.3.0(typescript@5.9.3) '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) From e8680beb52108664543be50cd8d08db8b60587ae Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 17:09:54 -0800 Subject: [PATCH 005/129] Add Go SDK support to payment-identifier docs (#1253) * Update docs/sdk-features.md Generated-By: mintlify-agent * Update docs/extensions/payment-identifier.mdx Generated-By: mintlify-agent * Update docs/extensions/payment-identifier.mdx Generated-By: mintlify-agent * Update docs/extensions/payment-identifier.mdx Generated-By: mintlify-agent * Update docs/extensions/payment-identifier.mdx Generated-By: mintlify-agent * fix conflicts --------- Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> Co-authored-by: Philippe d'Argent --- docs/extensions/payment-identifier.mdx | 535 +++++++++++++++++++------ docs/sdk-features.md | 2 +- 2 files changed, 419 insertions(+), 118 deletions(-) diff --git a/docs/extensions/payment-identifier.mdx b/docs/extensions/payment-identifier.mdx index 3d72890086..e5ea85f00e 100644 --- a/docs/extensions/payment-identifier.mdx +++ b/docs/extensions/payment-identifier.mdx @@ -33,6 +33,10 @@ import { generatePaymentId } from "@x402/extensions/payment-identifier"; const paymentId = generatePaymentId(); // Example: "pay_7d5d747be160e280504c099d984bcfe0" + +// Custom prefix +const orderId = generatePaymentId("order_"); +// Example: "order_7d5d747be160e280504c099d984bcfe0" ``` ### Step 2: Add Payment ID to Extensions @@ -41,7 +45,10 @@ Hook into the payment flow to add the payment ID before payload creation: ```typescript import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; -import { appendPaymentIdentifierToExtensions } from "@x402/extensions/payment-identifier"; +import { + appendPaymentIdentifierToExtensions, + generatePaymentId, +} from "@x402/extensions/payment-identifier"; const client = new x402Client(); // ... register schemes ... @@ -51,10 +58,10 @@ const paymentId = generatePaymentId(); // Hook into payment flow to add the payment ID client.onBeforePaymentCreation(async ({ paymentRequired }) => { - if (!paymentRequired.extensions) { - paymentRequired.extensions = {}; + if (paymentRequired.extensions) { + // Only appends if server declared the extension + appendPaymentIdentifierToExtensions(paymentRequired.extensions, paymentId); } - appendPaymentIdentifierToExtensions(paymentRequired.extensions, paymentId); }); const fetchWithPayment = wrapFetchWithPayment(fetch, client); @@ -78,6 +85,10 @@ from x402.extensions.payment_identifier import generate_payment_id payment_id = generate_payment_id() # Example: "pay_7d5d747be160e280504c099d984bcfe0" + +# Custom prefix +order_id = generate_payment_id("order_") +# Example: "order_7d5d747be160e280504c099d984bcfe0" ``` ### Step 2: Add Payment ID to Extensions @@ -86,8 +97,12 @@ Hook into the payment flow to add the payment ID before payload creation: ```python from x402 import x402Client -from x402.extensions.payment_identifier import append_payment_identifier_to_extensions +from x402.extensions.payment_identifier import ( + append_payment_identifier_to_extensions, + generate_payment_id, +) from x402.http.clients import x402HttpxClient +from x402.schemas import PaymentCreationContext client = x402Client() # ... register schemes ... @@ -96,9 +111,10 @@ client = x402Client() payment_id = generate_payment_id() # Hook into payment flow to add the payment ID -async def before_payment_creation(context): +async def before_payment_creation(context: PaymentCreationContext) -> None: extensions = context.payment_required.extensions if extensions is not None: + # Only appends if server declared the extension append_payment_identifier_to_extensions(extensions, payment_id) client.on_before_payment_creation(before_payment_creation) @@ -106,19 +122,81 @@ client.on_before_payment_creation(before_payment_creation) async with x402HttpxClient(client) as http: # First request - payment is processed response1 = await http.get(url) - + # Retry with same payment ID - cached response returned (no payment) response2 = await http.get(url) ``` + + + +### Step 1: Generate a Payment ID + +Use the `GeneratePaymentID()` utility to create a unique identifier: + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +// Generate with default prefix "pay_" +paymentID := paymentidentifier.GeneratePaymentID("") +// Example: "pay_7d5d747be160e280504c099d984bcfe0" + +// Generate with custom prefix +paymentID = paymentidentifier.GeneratePaymentID("order_") +// Example: "order_7d5d747be160e280504c099d984bcfe0" +``` + +### Step 2: Add Payment ID to Extensions + +Hook into the payment flow to add the payment ID before payload creation: + +```go +import ( + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/extensions/paymentidentifier" +) + +client := x402.Newx402Client() +// ... register schemes ... + +// Generate a unique payment ID for this logical request +paymentID := paymentidentifier.GeneratePaymentID("") + +// Hook into payment flow to add the payment ID +client.OnBeforePaymentCreation(func(ctx x402.PaymentCreationContext) (*x402.BeforePaymentCreationHookResult, error) { + if ctx.Extensions == nil { + return nil, nil + } + + // Only add if server declared the extension + if ctx.Extensions[paymentidentifier.PAYMENT_IDENTIFIER] == nil { + return nil, nil + } + + err := paymentidentifier.AppendPaymentIdentifierToExtensions(ctx.Extensions, paymentID) + if err != nil { + return nil, err + } + + return nil, nil +}) + +// First request - payment is processed +response1, err := client.MakeRequest(url) + +// Retry with same payment ID - cached response returned (no payment) +response2, err := client.MakeRequest(url) +``` + + ### Best Practices 1. **Generate payment IDs at the logical request level**, not per retry 2. **Persist payment IDs** for long-running operations so they survive restarts -3. **Use descriptive prefixes** (e.g., `order_`, `sub_`) to identify payment types +3. **Use descriptive prefixes** (e.g., `generatePaymentId("order_")`) to identify payment types 4. **Don't reuse payment IDs** across different logical requests ## Quickstart for Sellers (Servers) @@ -131,17 +209,26 @@ async with x402HttpxClient(client) as http: Declare the payment-identifier extension in your route configuration: ```typescript -import { paymentMiddlewareFromHTTPServer, x402ResourceServer, x402HTTPResourceServer } from "@x402/express"; -import { declarePaymentIdentifierExtension, PAYMENT_IDENTIFIER } from "@x402/extensions/payment-identifier"; +import { + paymentMiddlewareFromHTTPServer, + x402ResourceServer, + x402HTTPResourceServer, +} from "@x402/express"; +import { + declarePaymentIdentifierExtension, + PAYMENT_IDENTIFIER, +} from "@x402/extensions/payment-identifier"; const routes = { "GET /weather": { - accepts: { - scheme: "exact", - price: "$0.001", - network: "eip155:84532", - payTo: address - }, + accepts: [ + { + scheme: "exact", + price: "$0.001", + network: "eip155:84532", + payTo: address, + }, + ], extensions: { [PAYMENT_IDENTIFIER]: declarePaymentIdentifierExtension(false), // optional }, @@ -159,9 +246,9 @@ declarePaymentIdentifierExtension(false) declarePaymentIdentifierExtension(true) ``` -### Step 2: Implement Idempotency Cache +### Step 2: Cache Responses After Settlement -Use the `extractPaymentIdentifier()` utility to check for cached responses: +Store responses after successful payment settlement: ```typescript import { extractPaymentIdentifier } from "@x402/extensions/payment-identifier"; @@ -170,35 +257,42 @@ import { extractPaymentIdentifier } from "@x402/extensions/payment-identifier"; const idempotencyCache = new Map(); const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour -const httpServer = new x402HTTPResourceServer(resourceServer, routes) - .onProtectedRequest(async (context) => { - // Check if payment ID is in cache - const paymentPayload = JSON.parse(Buffer.from(context.paymentHeader, "base64").toString()); +const resourceServer = new x402ResourceServer(facilitatorClient) + .register("eip155:84532", new ExactEvmScheme()) + .onAfterSettle(async ({ paymentPayload }) => { const paymentId = extractPaymentIdentifier(paymentPayload); - if (paymentId) { - const cached = idempotencyCache.get(paymentId); - if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) { - return { grantAccess: true }; // Skip payment, grant access - } + idempotencyCache.set(paymentId, { + timestamp: Date.now(), + response: { /* your response data */ }, + }); } }); ``` -### Step 3: Cache Responses After Settlement +### Step 3: Check Cache Before Payment -Store responses after successful payment settlement: +Use the `onProtectedRequest` hook to return cached responses and skip payment processing: ```typescript -const resourceServer = new x402ResourceServer(facilitatorClient) - .register("eip155:84532", new ExactEvmScheme()) - .onAfterSettle(async ({ paymentPayload }) => { - const paymentId = extractPaymentIdentifier(paymentPayload); - if (paymentId) { - idempotencyCache.set(paymentId, { - timestamp: Date.now(), - response: { /* your response data */ } - }); +const httpServer = new x402HTTPResourceServer(resourceServer, routes) + .onProtectedRequest(async (context) => { + if (!context.paymentHeader) return; + + try { + const paymentPayload = JSON.parse( + Buffer.from(context.paymentHeader, "base64").toString("utf-8"), + ); + const paymentId = extractPaymentIdentifier(paymentPayload); + + if (paymentId) { + const cached = idempotencyCache.get(paymentId); + if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) { + return { grantAccess: true }; // Skip payment, serve from cache + } + } + } catch { + // Invalid payment header, continue to normal payment flow } }); ``` @@ -211,24 +305,30 @@ const resourceServer = new x402ResourceServer(facilitatorClient) Declare the payment-identifier extension in your route configuration: ```python -from x402.http.servers.fastapi import x402FastAPIResourceServer +from x402.server import x402ResourceServer +from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption +from x402.http.middleware.fastapi import PaymentMiddlewareASGI +from x402.http.types import RouteConfig +from x402.mechanisms.evm.exact import ExactEvmServerScheme from x402.extensions.payment_identifier import ( declare_payment_identifier_extension, PAYMENT_IDENTIFIER, ) routes = { - "GET /weather": { - "accepts": { - "scheme": "exact", - "price": "$0.001", - "network": "eip155:84532", - "payTo": address, + "GET /weather": RouteConfig( + accepts=[ + PaymentOption( + scheme="exact", + price="$0.001", + network="eip155:84532", + pay_to=address, + ), + ], + extensions={ + PAYMENT_IDENTIFIER: declare_payment_identifier_extension(required=False), # optional }, - "extensions": { - PAYMENT_IDENTIFIER: declare_payment_identifier_extension(False), # optional - }, - }, + ), } ``` @@ -236,62 +336,148 @@ routes = { ```python # Payment ID is optional (clients can omit it) -declare_payment_identifier_extension(False) +declare_payment_identifier_extension(required=False) # Payment ID is required (clients must provide it or receive 400 Bad Request) -declare_payment_identifier_extension(True) +declare_payment_identifier_extension(required=True) ``` -### Step 2: Implement Idempotency Cache +### Step 2: Cache Responses After Settlement -Use the `extract_payment_identifier()` utility to check for cached responses: +Store responses after successful payment settlement: ```python -from x402.extensions.payment_identifier import extract_payment_identifier import time +from x402.schemas import SettleContext +from x402.extensions.payment_identifier import extract_payment_identifier # In-memory cache (use Redis in production) -idempotency_cache = {} -CACHE_TTL_MS = 60 * 60 * 1000 # 1 hour - -async def on_protected_request(context): - # Check if payment ID is in cache - payment_payload = context.payment_payload - payment_id = extract_payment_identifier(payment_payload) - +idempotency_cache: dict = {} +CACHE_TTL_SECONDS = 60 * 60 # 1 hour + +async def after_settle(ctx: SettleContext) -> None: + payment_id = extract_payment_identifier(ctx.payment_payload) if payment_id: - cached = idempotency_cache.get(payment_id) - if cached and (time.time() * 1000 - cached["timestamp"]) < CACHE_TTL_MS: - return {"grant_access": True} # Skip payment, grant access + idempotency_cache[payment_id] = { + "timestamp": time.time(), + "response": {}, # your response data + } -http_server = x402FastAPIResourceServer(resource_server, routes) -http_server.on_protected_request(on_protected_request) +server = x402ResourceServer(facilitator) +server.register("eip155:84532", ExactEvmServerScheme()) +server.on_after_settle(after_settle) ``` -### Step 3: Cache Responses After Settlement +### Step 3: Check Cache Before Payment -Store responses after successful payment settlement: +Use FastAPI middleware to check the cache before the payment middleware processes the request: ```python -from x402 import x402ResourceServer -from x402.mechanisms.evm import ExactEvmScheme +import base64 +import json +from fastapi import Request, Response +from x402.schemas import PaymentPayload + +@app.middleware("http") +async def idempotency_middleware(request: Request, call_next): + payment_header = request.headers.get("X-Payment") + if payment_header: + try: + payment_data = json.loads(base64.b64decode(payment_header)) + payment_payload = PaymentPayload.model_validate(payment_data) + payment_id = extract_payment_identifier(payment_payload) + + if payment_id: + cached = idempotency_cache.get(payment_id) + if cached and time.time() - cached["timestamp"] < CACHE_TTL_SECONDS: + return Response( + content=json.dumps(cached["response"]), + media_type="application/json", + ) + except Exception: + pass # Invalid payment header, continue to normal flow + + return await call_next(request) + +# Add payment middleware AFTER idempotency middleware +app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server) +``` -async def after_settle(context): - payment_id = extract_payment_identifier(context.payment_payload) - if payment_id: - idempotency_cache[payment_id] = { - "timestamp": time.time() * 1000, - "response": {} # your response data - } + + + +### Step 1: Advertise Extension Support + +Declare the payment-identifier extension in your route configuration: -resource_server = x402ResourceServer(facilitator_client) -resource_server.register("eip155:84532", ExactEvmScheme()) -resource_server.on_after_settle(after_settle) +```go +import ( + x402http "github.com/coinbase/x402/go/http" + "github.com/coinbase/x402/go/extensions/paymentidentifier" +) + +// Optional or required payment identifier (pick one) +paymentIdExtension := paymentidentifier.DeclarePaymentIdentifierExtension(false) // optional +// paymentIdExtension = paymentidentifier.DeclarePaymentIdentifierExtension(true) // required + +routes := x402http.RoutesConfig{ + "GET /weather": { + Accepts: []x402http.PaymentOption{ + { + Scheme: "exact", + Price: "$0.001", + Network: "eip155:84532", + PayTo: address, + }, + }, + Extensions: map[string]interface{}{ + paymentidentifier.PAYMENT_IDENTIFIER: paymentIdExtension, + }, + }, +} +``` + +### Step 2: Extract Payment ID + +Use the `ExtractPaymentIdentifier()` utility to get the payment ID from the payload: + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +// In your handler +payload := c.MustGet("x402_payload").(x402.PaymentPayload) + +paymentID, err := paymentidentifier.ExtractPaymentIdentifier(payload, true) +if err != nil { + // Handle invalid payment ID + c.JSON(400, gin.H{"error": err.Error()}) + return +} + +// Check for duplicate +if existingResponse, found := processedPayments[paymentID]; found { + // Return cached response + c.JSON(200, existingResponse) + return +} +``` + +### Step 3: Cache Responses + +Store responses after successful payment processing: + +```go +// In-memory cache (use Redis in production) +var processedPayments = make(map[string]interface{}) + +// After processing payment +processedPayments[paymentID] = responseData ``` + ### Idempotency Behavior | Scenario | Server Response | @@ -305,7 +491,7 @@ resource_server.on_after_settle(after_settle) #### Cache TTL -Adjust `CACHE_TTL_MS` based on your use case: +Adjust `CACHE_TTL_MS` (TypeScript/Go) or `CACHE_TTL_SECONDS` (Python) based on your use case: - Short TTL (5-15 min): For time-sensitive resources - Long TTL (1-24 hours): For static or infrequently changing resources @@ -323,7 +509,7 @@ Adjust `CACHE_TTL_MS` based on your use case: ### Client Functions -#### `generatePaymentId()` +#### `generatePaymentId(prefix?)` Generates a cryptographically secure unique payment identifier. @@ -332,18 +518,21 @@ import { generatePaymentId } from "@x402/extensions/payment-identifier"; const paymentId = generatePaymentId(); // Returns: "pay_<32-character-hex-string>" + +const orderId = generatePaymentId("order_"); +// Returns: "order_<32-character-hex-string>" ``` -#### `appendPaymentIdentifierToExtensions(extensions, paymentId?)` +#### `appendPaymentIdentifierToExtensions(extensions, id?)` -Adds a payment identifier to the extensions object. If no payment ID is provided, one is generated automatically. +Adds a payment identifier to the extensions object. Only modifies extensions if the server declared support for the extension. If no payment ID is provided, one is generated automatically. ```typescript import { appendPaymentIdentifierToExtensions } from "@x402/extensions/payment-identifier"; -const extensions = {}; -appendPaymentIdentifierToExtensions(extensions, "pay_custom_id"); -// extensions now contains the payment-identifier extension +const extensions = paymentRequired.extensions ?? {}; +appendPaymentIdentifierToExtensions(extensions, "pay_custom_id_1234567890abcdef"); +// extensions now contains the payment-identifier extension (only if server declared it) ``` #### `isValidPaymentId(id)` @@ -353,21 +542,21 @@ Validates a payment identifier format. ```typescript import { isValidPaymentId } from "@x402/extensions/payment-identifier"; -isValidPaymentId("pay_7d5d747be160e280"); // true -isValidPaymentId("invalid"); // false +isValidPaymentId("pay_7d5d747be160e280504c099d984bcfe0"); // true +isValidPaymentId("invalid"); // false (too short) ``` ### Server Functions -#### `declarePaymentIdentifierExtension(required)` +#### `declarePaymentIdentifierExtension(required?)` Creates a payment-identifier extension declaration for resource servers. ```typescript import { declarePaymentIdentifierExtension } from "@x402/extensions/payment-identifier"; -// Optional payment ID -const extension = declarePaymentIdentifierExtension(false); +// Optional payment ID (default) +const extension = declarePaymentIdentifierExtension(); // Required payment ID const extensionRequired = declarePaymentIdentifierExtension(true); @@ -386,16 +575,17 @@ if (paymentId) { } ``` -#### `validatePaymentIdentifier(paymentPayload)` +#### `validatePaymentIdentifier(extension)` -Validates the payment identifier in a payment payload. +Validates the payment identifier extension object structure and ID format. ```typescript import { validatePaymentIdentifier } from "@x402/extensions/payment-identifier"; -const result = validatePaymentIdentifier(paymentPayload); +const extension = paymentPayload.extensions?.["payment-identifier"]; +const result = validatePaymentIdentifier(extension); if (!result.valid) { - console.error(result.error); + console.error(result.errors); } ``` @@ -415,7 +605,7 @@ import { ### Client Functions -#### `generate_payment_id()` +#### `generate_payment_id(prefix="pay_")` Generates a cryptographically secure unique payment identifier. @@ -424,18 +614,21 @@ from x402.extensions.payment_identifier import generate_payment_id payment_id = generate_payment_id() # Returns: "pay_<32-character-hex-string>" + +order_id = generate_payment_id("order_") +# Returns: "order_<32-character-hex-string>" ``` #### `append_payment_identifier_to_extensions(extensions, id=None)` -Adds a payment identifier to the extensions object. If no payment ID is provided, one is generated automatically. +Adds a payment identifier to the extensions object. Only modifies extensions if the server declared support for the extension. If no payment ID is provided, one is generated automatically. ```python from x402.extensions.payment_identifier import append_payment_identifier_to_extensions -extensions = {} -append_payment_identifier_to_extensions(extensions, "pay_custom_id") -# extensions now contains the payment-identifier extension +extensions = payment_required.extensions or {} +append_payment_identifier_to_extensions(extensions, "pay_custom_id_1234567890abcdef") +# extensions now contains the payment-identifier extension (only if server declared it) ``` #### `is_valid_payment_id(id)` @@ -445,8 +638,8 @@ Validates a payment identifier format. ```python from x402.extensions.payment_identifier import is_valid_payment_id -is_valid_payment_id("pay_7d5d747be160e280") # True -is_valid_payment_id("invalid") # False +is_valid_payment_id("pay_7d5d747be160e280504c099d984bcfe0") # True +is_valid_payment_id("invalid") # False (too short) ``` ### Server Functions @@ -458,11 +651,11 @@ Creates a payment-identifier extension declaration for resource servers. ```python from x402.extensions.payment_identifier import declare_payment_identifier_extension -# Optional payment ID -extension = declare_payment_identifier_extension(False) +# Optional payment ID (default) +extension = declare_payment_identifier_extension() # Required payment ID -extension_required = declare_payment_identifier_extension(True) +extension_required = declare_payment_identifier_extension(required=True) ``` #### `extract_payment_identifier(payment_payload)` @@ -478,16 +671,17 @@ if payment_id: pass ``` -#### `validate_payment_identifier(payment_payload)` +#### `validate_payment_identifier(extension)` -Validates the payment identifier in a payment payload. +Validates the payment identifier extension object structure and ID format. ```python from x402.extensions.payment_identifier import validate_payment_identifier -result = validate_payment_identifier(payment_payload) +extension = payment_payload.extensions.get("payment-identifier") +result = validate_payment_identifier(extension) if not result.valid: - print(result.error) + print(result.errors) ``` ### Constants @@ -497,8 +691,113 @@ from x402.extensions.payment_identifier import ( PAYMENT_IDENTIFIER, # "payment-identifier" PAYMENT_ID_MIN_LENGTH, # 16 PAYMENT_ID_MAX_LENGTH, # 128 - PAYMENT_ID_PATTERN, # r"^[a-zA-Z0-9_-]+$" + PAYMENT_ID_PATTERN, # re.compile(r"^[a-zA-Z0-9_-]+$") +) +``` + + + + +### Client Functions + +#### `GeneratePaymentID(prefix string)` + +Generates a cryptographically secure unique payment identifier. + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +// Generate with default prefix "pay_" +paymentID := paymentidentifier.GeneratePaymentID("") +// Returns: "pay_<32-character-hex-string>" + +// Generate with custom prefix +paymentID = paymentidentifier.GeneratePaymentID("order_") +// Returns: "order_<32-character-hex-string>" +``` + +#### `AppendPaymentIdentifierToExtensions(extensions map[string]interface{}, id string) error` + +Adds a payment identifier to the extensions object. Only modifies extensions if the server declared support for the extension. Pass an empty string to auto-generate an ID. + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +extensions := make(map[string]interface{}) +err := paymentidentifier.AppendPaymentIdentifierToExtensions(extensions, "pay_custom_id_1234567890abcdef") +// extensions now contains the payment-identifier extension (only if server declared it) +``` + +#### `IsValidPaymentID(id string) bool` + +Validates a payment identifier format. + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +valid := paymentidentifier.IsValidPaymentID("pay_7d5d747be160e280504c099d984bcfe0") // true +valid = paymentidentifier.IsValidPaymentID("invalid") // false (too short) +``` + +### Server Functions + +#### `DeclarePaymentIdentifierExtension(required bool) PaymentIdentifierExtension` + +Creates a payment-identifier extension declaration for resource servers. + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +// Optional payment ID +extension := paymentidentifier.DeclarePaymentIdentifierExtension(false) + +// Required payment ID +extensionRequired := paymentidentifier.DeclarePaymentIdentifierExtension(true) +``` + +#### `ExtractPaymentIdentifier(payload PaymentPayload, validate bool) (string, error)` + +Extracts the payment identifier from a payment payload. + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +paymentID, err := paymentidentifier.ExtractPaymentIdentifier(payload, true) +if err != nil { + // Handle error +} +if paymentID != "" { + // Check cache, implement idempotency logic +} +``` + +#### `ValidatePaymentIdentifier(extension interface{}) ValidationResult` + +Validates the payment identifier extension object structure and ID format. + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +extension := payload.Extensions[paymentidentifier.PAYMENT_IDENTIFIER] +result := paymentidentifier.ValidatePaymentIdentifier(extension) +if !result.Valid { + // Handle validation errors + fmt.Println(result.Errors) +} +``` + +### Constants + +```go +import "github.com/coinbase/x402/go/extensions/paymentidentifier" + +const ( + PAYMENT_IDENTIFIER = "payment-identifier" + PAYMENT_ID_MIN_LENGTH = 16 + PAYMENT_ID_MAX_LENGTH = 128 ) + +var PAYMENT_ID_PATTERN = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`) ``` @@ -508,15 +807,17 @@ from x402.extensions.payment_identifier import ( Full working examples are available in the x402 repository: +**TypeScript:** - [TypeScript Client Example](https://github.com/coinbase/x402/tree/main/examples/typescript/clients/payment-identifier) - [TypeScript Server Example](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/payment-identifier) + +**Python:** - [Python Client Example](https://github.com/coinbase/x402/tree/main/examples/python/clients/payment-identifier) - [Python Server Example](https://github.com/coinbase/x402/tree/main/examples/python/servers/payment-identifier) -## Support - -- **GitHub**: [github.com/coinbase/x402](https://github.com/coinbase/x402) -- **Discord**: [Join #x402 channel](https://discord.com/invite/cdp) +**Go:** +- [Go Client Example](https://github.com/coinbase/x402/tree/main/examples/go/clients/payment-identifier) +- [Go Server Example](https://github.com/coinbase/x402/tree/main/examples/go/servers/payment-identifier) ## FAQ @@ -530,4 +831,4 @@ A: This is configurable by the server. Typical TTLs range from 5 minutes to 24 h A: Payment IDs must be 16-128 characters, alphanumeric with hyphens and underscores allowed. Use `isValidPaymentId()` to validate custom IDs. **Q: What if the server doesn't support payment-identifier?** -A: The extension is optional. If the server doesn't advertise support, clients can still make payments normally without idempotency. \ No newline at end of file +A: The extension is optional. If the server doesn't advertise support, clients can still make payments normally without idempotency. diff --git a/docs/sdk-features.md b/docs/sdk-features.md index b63ede970e..40a797201a 100644 --- a/docs/sdk-features.md +++ b/docs/sdk-features.md @@ -44,7 +44,7 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt |-----------|------------|-----|--------| | bazaar | βœ… | βœ… | βœ… | | sign-in-with-x | βœ… | ❌ | ❌ | -| payment-identifier | βœ… | ❌ | βœ… | +| payment-identifier | βœ… | βœ… | βœ… | ## Client Hooks From 1c554e907aa50c9731e9436f2693862ba59ae02f Mon Sep 17 00:00:00 2001 From: wonjoon <39115630+wnjoon@users.noreply.github.com> Date: Tue, 3 Mar 2026 11:40:31 +0900 Subject: [PATCH 006/129] feat(go/http): add pluggable PaywallProvider for custom paywall HTML generation (#1370) --- .../unreleased/changed-20260227-153504.yaml | 3 + go/http/paywall.go | 126 +++++++ go/http/paywall_test.go | 325 ++++++++++++++++++ go/http/server.go | 74 +++- 4 files changed, 526 insertions(+), 2 deletions(-) create mode 100644 go/.changes/unreleased/changed-20260227-153504.yaml create mode 100644 go/http/paywall.go create mode 100644 go/http/paywall_test.go diff --git a/go/.changes/unreleased/changed-20260227-153504.yaml b/go/.changes/unreleased/changed-20260227-153504.yaml new file mode 100644 index 0000000000..1802f6202b --- /dev/null +++ b/go/.changes/unreleased/changed-20260227-153504.yaml @@ -0,0 +1,3 @@ +kind: changed +body: Add pluggable PaywallProvider interface for custom paywall HTML generation with PaywallBuilder pattern +time: 2026-02-27T15:35:04.609332+09:00 diff --git a/go/http/paywall.go b/go/http/paywall.go new file mode 100644 index 0000000000..a6191f7f4c --- /dev/null +++ b/go/http/paywall.go @@ -0,0 +1,126 @@ +package http + +import ( + "strings" + + "github.com/coinbase/x402/go/types" +) + +// ============================================================================ +// Paywall Provider Interfaces +// ============================================================================ + +// PaywallProvider generates HTML for browser-facing 402 responses. +// Register a custom implementation via RegisterPaywallProvider to override +// the built-in EVM/SVM templates. +type PaywallProvider interface { + GenerateHTML(paymentRequired types.PaymentRequired, config *PaywallConfig) string +} + +// PaywallNetworkHandler handles paywall HTML generation for a specific network family. +// Used with PaywallBuilder to compose network-specific handlers into a single PaywallProvider. +type PaywallNetworkHandler interface { + // Supports returns true if this handler can generate HTML for the given payment requirement. + Supports(requirement types.PaymentRequirements) bool + + // GenerateHTML generates the paywall HTML for the given requirement. + GenerateHTML(requirement types.PaymentRequirements, paymentRequired types.PaymentRequired, config *PaywallConfig) string +} + +// ============================================================================ +// Built-in Network Handlers +// ============================================================================ + +// EVMPaywallHandler generates paywall HTML for EVM-compatible networks (eip155:*). +type EVMPaywallHandler struct{} + +// Supports returns true for EVM networks (eip155:* CAIP-2 identifiers). +func (h *EVMPaywallHandler) Supports(requirement types.PaymentRequirements) bool { + return strings.HasPrefix(requirement.Network, "eip155:") +} + +// GenerateHTML generates paywall HTML using the built-in EVM template. +func (h *EVMPaywallHandler) GenerateHTML(_ types.PaymentRequirements, paymentRequired types.PaymentRequired, config *PaywallConfig) string { + return injectPaywallConfig(EVMPaywallTemplate, paymentRequired, config) +} + +// SVMPaywallHandler generates paywall HTML for Solana networks (solana:*). +type SVMPaywallHandler struct{} + +// Supports returns true for Solana networks (solana:* CAIP-2 identifiers). +func (h *SVMPaywallHandler) Supports(requirement types.PaymentRequirements) bool { + return strings.HasPrefix(requirement.Network, "solana:") +} + +// GenerateHTML generates paywall HTML using the built-in SVM template. +func (h *SVMPaywallHandler) GenerateHTML(_ types.PaymentRequirements, paymentRequired types.PaymentRequired, config *PaywallConfig) string { + return injectPaywallConfig(SVMPaywallTemplate, paymentRequired, config) +} + +// ============================================================================ +// Paywall Builder +// ============================================================================ + +// PaywallBuilder composes multiple PaywallNetworkHandlers into a single PaywallProvider. +// Use NewPaywallBuilder to create a builder, add network handlers, and call Build. +type PaywallBuilder struct { + handlers []PaywallNetworkHandler + config *PaywallConfig +} + +// NewPaywallBuilder creates a new PaywallBuilder. +func NewPaywallBuilder() *PaywallBuilder { + return &PaywallBuilder{} +} + +// WithNetwork adds a network handler to the builder. +func (b *PaywallBuilder) WithNetwork(handler PaywallNetworkHandler) *PaywallBuilder { + b.handlers = append(b.handlers, handler) + return b +} + +// WithConfig sets default paywall configuration for the builder. +func (b *PaywallBuilder) WithConfig(config *PaywallConfig) *PaywallBuilder { + b.config = config + return b +} + +// Build creates a PaywallProvider that dispatches to the first matching network handler. +func (b *PaywallBuilder) Build() PaywallProvider { + return &compositePaywallProvider{ + handlers: b.handlers, + config: b.config, + } +} + +// compositePaywallProvider dispatches to the first handler that supports the payment requirement. +type compositePaywallProvider struct { + handlers []PaywallNetworkHandler + config *PaywallConfig +} + +func (p *compositePaywallProvider) GenerateHTML(paymentRequired types.PaymentRequired, config *PaywallConfig) string { + // Use builder config as fallback if no per-call config provided + effectiveConfig := config + if effectiveConfig == nil { + effectiveConfig = p.config + } + + for _, req := range paymentRequired.Accepts { + for _, handler := range p.handlers { + if handler.Supports(req) { + return handler.GenerateHTML(req, paymentRequired, effectiveConfig) + } + } + } + + return "" +} + +// DefaultPaywallProvider creates a PaywallProvider with built-in EVM and SVM handlers. +func DefaultPaywallProvider() PaywallProvider { + return NewPaywallBuilder(). + WithNetwork(&EVMPaywallHandler{}). + WithNetwork(&SVMPaywallHandler{}). + Build() +} diff --git a/go/http/paywall_test.go b/go/http/paywall_test.go new file mode 100644 index 0000000000..96ea50891d --- /dev/null +++ b/go/http/paywall_test.go @@ -0,0 +1,325 @@ +package http + +import ( + "strings" + "testing" + + "github.com/coinbase/x402/go/types" +) + +// mockPaywallProvider is a test PaywallProvider that returns configurable HTML. +type mockPaywallProvider struct { + html string +} + +func (m *mockPaywallProvider) GenerateHTML(_ types.PaymentRequired, _ *PaywallConfig) string { + return m.html +} + +// mockNetworkHandler is a test PaywallNetworkHandler for a configurable network prefix. +type mockNetworkHandler struct { + prefix string + html string +} + +func (m *mockNetworkHandler) Supports(req types.PaymentRequirements) bool { + return strings.HasPrefix(req.Network, m.prefix) +} + +func (m *mockNetworkHandler) GenerateHTML(_ types.PaymentRequirements, _ types.PaymentRequired, _ *PaywallConfig) string { + return m.html +} + +func makePaymentRequired(network string) types.PaymentRequired { + return types.PaymentRequired{ + X402Version: 2, + Accepts: []types.PaymentRequirements{ + { + Scheme: "exact", + Network: network, + Asset: "USDC", + Amount: "1000000", + PayTo: "0xtest", + }, + }, + Resource: &types.ResourceInfo{ + URL: "/api/test", + Description: "Test API", + }, + } +} + +// --- EVMPaywallHandler tests --- + +func TestEVMPaywallHandler_Supports(t *testing.T) { + handler := &EVMPaywallHandler{} + + tests := []struct { + network string + want bool + }{ + {"eip155:1", true}, + {"eip155:8453", true}, + {"eip155:84532", true}, + {"solana:mainnet", false}, + {"solana:devnet", false}, + {"aptos:mainnet", false}, + {"", false}, + } + + for _, tt := range tests { + t.Run(tt.network, func(t *testing.T) { + req := types.PaymentRequirements{Network: tt.network} + got := handler.Supports(req) + if got != tt.want { + t.Errorf("EVMPaywallHandler.Supports(%q) = %v, want %v", tt.network, got, tt.want) + } + }) + } +} + +// --- SVMPaywallHandler tests --- + +func TestSVMPaywallHandler_Supports(t *testing.T) { + handler := &SVMPaywallHandler{} + + tests := []struct { + network string + want bool + }{ + {"solana:mainnet", true}, + {"solana:devnet", true}, + {"eip155:1", false}, + {"eip155:8453", false}, + {"aptos:mainnet", false}, + {"", false}, + } + + for _, tt := range tests { + t.Run(tt.network, func(t *testing.T) { + req := types.PaymentRequirements{Network: tt.network} + got := handler.Supports(req) + if got != tt.want { + t.Errorf("SVMPaywallHandler.Supports(%q) = %v, want %v", tt.network, got, tt.want) + } + }) + } +} + +// --- PaywallBuilder tests --- + +func TestPaywallBuilder_Build(t *testing.T) { + provider := NewPaywallBuilder(). + WithNetwork(&mockNetworkHandler{prefix: "eip155:", html: ""}). + WithNetwork(&mockNetworkHandler{prefix: "solana:", html: ""}). + Build() + + t.Run("matches EVM network", func(t *testing.T) { + got := provider.GenerateHTML(makePaymentRequired("eip155:8453"), nil) + if got != "" { + t.Errorf("expected , got %q", got) + } + }) + + t.Run("matches Solana network", func(t *testing.T) { + got := provider.GenerateHTML(makePaymentRequired("solana:mainnet"), nil) + if got != "" { + t.Errorf("expected , got %q", got) + } + }) + + t.Run("no match returns empty string", func(t *testing.T) { + got := provider.GenerateHTML(makePaymentRequired("aptos:mainnet"), nil) + if got != "" { + t.Errorf("expected empty string for unsupported network, got %q", got) + } + }) +} + +func TestPaywallBuilder_WithConfig(t *testing.T) { + var capturedConfig *PaywallConfig + + handler := &configCapturingHandler{ + prefix: "eip155:", + onGenerate: func(config *PaywallConfig) { + capturedConfig = config + }, + } + + builderConfig := &PaywallConfig{AppName: "TestApp", Testnet: true} + provider := NewPaywallBuilder(). + WithNetwork(handler). + WithConfig(builderConfig). + Build() + + t.Run("uses builder config when no per-call config", func(t *testing.T) { + provider.GenerateHTML(makePaymentRequired("eip155:1"), nil) + if capturedConfig == nil || capturedConfig.AppName != "TestApp" { + t.Errorf("expected builder config to be used, got %+v", capturedConfig) + } + }) + + t.Run("per-call config overrides builder config", func(t *testing.T) { + callConfig := &PaywallConfig{AppName: "CallApp"} + provider.GenerateHTML(makePaymentRequired("eip155:1"), callConfig) + if capturedConfig == nil || capturedConfig.AppName != "CallApp" { + t.Errorf("expected per-call config to override, got %+v", capturedConfig) + } + }) +} + +type configCapturingHandler struct { + prefix string + onGenerate func(config *PaywallConfig) +} + +func (h *configCapturingHandler) Supports(req types.PaymentRequirements) bool { + return strings.HasPrefix(req.Network, h.prefix) +} + +func (h *configCapturingHandler) GenerateHTML(_ types.PaymentRequirements, _ types.PaymentRequired, config *PaywallConfig) string { + if h.onGenerate != nil { + h.onGenerate(config) + } + return "" +} + +// --- DefaultPaywallProvider tests --- + +func TestDefaultPaywallProvider(t *testing.T) { + provider := DefaultPaywallProvider() + + t.Run("EVM network returns non-empty HTML", func(t *testing.T) { + got := provider.GenerateHTML(makePaymentRequired("eip155:8453"), nil) + if got == "" { + t.Error("expected non-empty HTML for EVM network") + } + if !strings.Contains(got, "window.x402") { + t.Error("expected window.x402 config injection in HTML") + } + }) + + t.Run("Solana network returns non-empty HTML", func(t *testing.T) { + got := provider.GenerateHTML(makePaymentRequired("solana:mainnet"), nil) + if got == "" { + t.Error("expected non-empty HTML for Solana network") + } + if !strings.Contains(got, "window.x402") { + t.Error("expected window.x402 config injection in HTML") + } + }) + + t.Run("unsupported network returns empty", func(t *testing.T) { + got := provider.GenerateHTML(makePaymentRequired("aptos:mainnet"), nil) + if got != "" { + t.Errorf("expected empty string for unsupported network, got length %d", len(got)) + } + }) +} + +// --- RegisterPaywallProvider integration tests --- + +func TestRegisterPaywallProvider(t *testing.T) { + routes := RoutesConfig{ + "GET /api/test": { + Accepts: PaymentOptions{ + { + Scheme: "exact", + PayTo: "0xtest", + Price: "$1.00", + Network: "eip155:8453", + }, + }, + }, + } + + t.Run("returns server for chaining", func(t *testing.T) { + server := Newx402HTTPResourceServer(routes) + result := server.RegisterPaywallProvider(&mockPaywallProvider{html: ""}) + if result != server { + t.Error("expected RegisterPaywallProvider to return the same server instance") + } + }) + + t.Run("registered provider is used in generatePaywallHTMLV2", func(t *testing.T) { + server := Newx402HTTPResourceServer(routes) + server.RegisterPaywallProvider(&mockPaywallProvider{html: ""}) + + got := server.generatePaywallHTMLV2(makePaymentRequired("eip155:8453"), nil, "") + if got != "" { + t.Errorf("expected , got %q", got) + } + }) + + t.Run("CustomPaywallHTML takes priority over provider", func(t *testing.T) { + server := Newx402HTTPResourceServer(routes) + server.RegisterPaywallProvider(&mockPaywallProvider{html: ""}) + + got := server.generatePaywallHTMLV2(makePaymentRequired("eip155:8453"), nil, "") + if got != "" { + t.Errorf("expected , got %q", got) + } + }) + + t.Run("no provider falls back to built-in template", func(t *testing.T) { + server := Newx402HTTPResourceServer(routes) + + got := server.generatePaywallHTMLV2(makePaymentRequired("eip155:8453"), nil, "") + if got == "" { + t.Error("expected non-empty HTML from built-in template") + } + if !strings.Contains(got, "window.x402") { + t.Error("expected built-in template with window.x402 injection") + } + }) +} + +// --- injectPaywallConfig tests --- + +func TestInjectPaywallConfig(t *testing.T) { + template := "" + paymentReq := makePaymentRequired("eip155:8453") + + t.Run("injects window.x402 config", func(t *testing.T) { + got := injectPaywallConfig(template, paymentReq, nil) + if !strings.Contains(got, "window.x402") { + t.Error("expected window.x402 in output") + } + if !strings.Contains(got, "") { + t.Error("expected to remain in output") + } + }) + + t.Run("includes PaywallConfig values", func(t *testing.T) { + config := &PaywallConfig{ + AppName: "TestApp", + AppLogo: "https://example.com/logo.png", + Testnet: true, + } + got := injectPaywallConfig(template, paymentReq, config) + if !strings.Contains(got, "TestApp") { + t.Error("expected appName in output") + } + if !strings.Contains(got, "https://example.com/logo.png") { + t.Error("expected appLogo in output") + } + if !strings.Contains(got, "testnet: true") { + t.Error("expected testnet: true in output") + } + }) + + t.Run("escapes HTML in config values", func(t *testing.T) { + config := &PaywallConfig{AppName: ``} + got := injectPaywallConfig(template, paymentReq, config) + if strings.Contains(got, ``) { + t.Error("expected HTML-escaped appName, got raw script tag") + } + }) + + t.Run("uses resource URL as currentUrl fallback", func(t *testing.T) { + got := injectPaywallConfig(template, paymentReq, nil) + if !strings.Contains(got, "/api/test") { + t.Error("expected resource URL as currentUrl fallback") + } + }) +} diff --git a/go/http/server.go b/go/http/server.go index 15455d4663..13ce8e3438 100644 --- a/go/http/server.go +++ b/go/http/server.go @@ -213,7 +213,8 @@ func (e *RouteConfigurationError) Error() string { // x402HTTPResourceServer provides HTTP-specific payment handling type x402HTTPResourceServer struct { *x402.X402ResourceServer - compiledRoutes []CompiledRoute + compiledRoutes []CompiledRoute + paywallProvider PaywallProvider } // Newx402HTTPResourceServer creates a new HTTP resource server @@ -247,6 +248,14 @@ func Wrappedx402HTTPResourceServer(routes RoutesConfig, resourceServer *x402.X40 return server } +// RegisterPaywallProvider registers a custom PaywallProvider for generating paywall HTML. +// The provider takes precedence over the built-in EVM/SVM templates but is overridden +// by per-route CustomPaywallHTML. Returns the server for method chaining. +func (s *x402HTTPResourceServer) RegisterPaywallProvider(provider PaywallProvider) *x402HTTPResourceServer { + s.paywallProvider = provider + return s +} + // Initialize initializes the server by populating facilitator data and validating route configuration. // It calls the parent server's Initialize to fetch facilitator support, then validates that all // configured routes have matching scheme registrations and facilitator support. @@ -741,12 +750,20 @@ func (s *x402HTTPResourceServer) createSettlementHeaders(response *x402.SettleRe }, nil } -// generatePaywallHTMLV2 generates HTML paywall for V2 PaymentRequired +// generatePaywallHTMLV2 generates HTML paywall for V2 PaymentRequired. +// Fallback chain: 1) customHTML, 2) registered PaywallProvider, 3) built-in templates. func (s *x402HTTPResourceServer) generatePaywallHTMLV2(paymentRequired types.PaymentRequired, config *PaywallConfig, customHTML string) string { + // Tier 1: Per-route custom HTML (highest priority) if customHTML != "" { return customHTML } + // Tier 2: Registered PaywallProvider + if s.paywallProvider != nil { + return s.paywallProvider.GenerateHTML(paymentRequired, config) + } + + // Tier 3: Built-in EVM/SVM templates (default fallback) // Convert V2 to generic format to reuse existing HTML generation genericRequired := x402.PaymentRequired{ X402Version: paymentRequired.X402Version, @@ -859,6 +876,59 @@ func (s *x402HTTPResourceServer) getDisplayAmount(paymentRequired x402.PaymentRe return 0.0 } +// injectPaywallConfig injects a window.x402 configuration script into a paywall HTML template. +// Used by built-in PaywallNetworkHandler implementations to hydrate templates with payment data. +func injectPaywallConfig(template string, paymentRequired types.PaymentRequired, config *PaywallConfig) string { + // Calculate display amount (assuming USDC with 6 decimals) + var displayAmount float64 + if len(paymentRequired.Accepts) > 0 { + amount, err := strconv.ParseFloat(paymentRequired.Accepts[0].Amount, 64) + if err == nil { + displayAmount = amount / 1000000 + } + } + + appName := "" + appLogo := "" + testnet := false + currentURL := "" + + if config != nil { + appName = config.AppName + appLogo = config.AppLogo + testnet = config.Testnet + currentURL = config.CurrentURL + } + + if currentURL == "" && paymentRequired.Resource != nil { + currentURL = paymentRequired.Resource.URL + } + + requirementsJSON, _ := json.Marshal(paymentRequired) + + configScript := fmt.Sprintf(``, + string(requirementsJSON), + html.EscapeString(appName), + html.EscapeString(appLogo), + displayAmount, + testnet, + displayAmount, + html.EscapeString(currentURL), + ) + + return strings.Replace(template, "", configScript+"", 1) +} + // ============================================================================ // Utility Functions // ============================================================================ From cb040d815b8561967ace6ed934d94d709598bfab Mon Sep 17 00:00:00 2001 From: wonjoon <39115630+wnjoon@users.noreply.github.com> Date: Tue, 3 Mar 2026 11:52:17 +0900 Subject: [PATCH 007/129] feat(go): add WithBazaar facilitator client for discovery resource queries (#1407) --- .../unreleased/added-20260302-103254.yaml | 3 + go/extensions/bazaar/facilitator_client.go | 181 +++++++ .../bazaar/facilitator_client_test.go | 491 ++++++++++++++++++ go/http/facilitator_client.go | 16 + 4 files changed, 691 insertions(+) create mode 100644 go/.changes/unreleased/added-20260302-103254.yaml create mode 100644 go/extensions/bazaar/facilitator_client.go create mode 100644 go/extensions/bazaar/facilitator_client_test.go diff --git a/go/.changes/unreleased/added-20260302-103254.yaml b/go/.changes/unreleased/added-20260302-103254.yaml new file mode 100644 index 0000000000..166c2e3bbe --- /dev/null +++ b/go/.changes/unreleased/added-20260302-103254.yaml @@ -0,0 +1,3 @@ +kind: added +body: Add WithBazaar facilitator client decorator for querying /discovery/resources endpoint from bazaar in go +time: 2026-03-02T10:32:54.304235+09:00 diff --git a/go/extensions/bazaar/facilitator_client.go b/go/extensions/bazaar/facilitator_client.go new file mode 100644 index 0000000000..90be3b9ab6 --- /dev/null +++ b/go/extensions/bazaar/facilitator_client.go @@ -0,0 +1,181 @@ +package bazaar + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + + x402http "github.com/coinbase/x402/go/http" +) + +// ListDiscoveryResourcesParams contains optional filtering and pagination parameters +// for listing discovery resources from a facilitator's bazaar. +type ListDiscoveryResourcesParams struct { + // Type filters by protocol type (e.g., "http", "mcp"). + Type string + + // Limit is the number of discovered x402 resources to return per page. + Limit int + + // Offset is the offset of the first discovered x402 resource to return. + Offset int +} + +// DiscoveryResource represents a discovered x402 resource from the bazaar. +type DiscoveryResource struct { + // Resource is the URL or identifier of the discovered resource. + Resource string `json:"resource"` + + // Type is the protocol type of the resource (e.g., "http"). + Type string `json:"type"` + + // X402Version is the x402 protocol version supported by this resource. + X402Version int `json:"x402Version"` + + // Accepts is an array of accepted payment methods for this resource. + Accepts []json.RawMessage `json:"accepts"` + + // LastUpdated is an ISO 8601 timestamp of when the resource was last updated. + LastUpdated string `json:"lastUpdated"` + + // Metadata contains additional metadata about the resource. + Metadata map[string]any `json:"metadata,omitempty"` +} + +// Pagination contains pagination information for a discovery resources response. +type Pagination struct { + // Limit is the maximum number of results returned. + Limit int `json:"limit"` + + // Offset is the number of results skipped. + Offset int `json:"offset"` + + // Total is the total count of resources matching the query. + Total int `json:"total"` +} + +// DiscoveryResourcesResponse is the response from listing discovery resources. +type DiscoveryResourcesResponse struct { + // X402Version is the x402 protocol version of this response. + X402Version int `json:"x402Version"` + + // Items is the list of discovered resources. + Items []DiscoveryResource `json:"items"` + + // Pagination contains pagination information for the response. + Pagination Pagination `json:"pagination"` +} + +// BazaarFacilitatorClient wraps an HTTPFacilitatorClient with bazaar discovery +// query functionality. It preserves all original facilitator client capabilities +// (Verify, Settle, GetSupported) and adds the ability to list discovered x402 +// resources from the facilitator's bazaar. +type BazaarFacilitatorClient struct { + *x402http.HTTPFacilitatorClient +} + +// WithBazaar extends a facilitator client with bazaar discovery query functionality. +// +// Example: +// +// client := bazaar.WithBazaar(http.NewHTTPFacilitatorClient(nil)) +// resources, err := client.ListDiscoveryResources(ctx, &bazaar.ListDiscoveryResourcesParams{ +// Type: "http", +// Limit: 20, +// }) +func WithBazaar(client *x402http.HTTPFacilitatorClient) *BazaarFacilitatorClient { + return &BazaarFacilitatorClient{HTTPFacilitatorClient: client} +} + +// ListDiscoveryResources queries the facilitator's /discovery/resources endpoint +// to list x402 discovery resources from the bazaar. +// +// Params may be nil to list all resources without filtering. +func (c *BazaarFacilitatorClient) ListDiscoveryResources( + ctx context.Context, + params *ListDiscoveryResourcesParams, +) (*DiscoveryResourcesResponse, error) { + // Build URL with query parameters + endpoint, err := c.buildDiscoveryURL(params) + if err != nil { + return nil, fmt.Errorf("failed to build discovery URL: %w", err) + } + + // Create request + req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil) + if err != nil { + return nil, fmt.Errorf("failed to create discovery request: %w", err) + } + + req.Header.Set("Content-Type", "application/json") + + // Add auth headers if available + authProvider := c.GetAuthProvider() + if authProvider != nil { + authHeaders, err := authProvider.GetAuthHeaders(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get auth headers: %w", err) + } + for k, v := range authHeaders.Discovery { + req.Header.Set(k, v) + } + } + + // Make request + resp, err := c.HTTPClient().Do(req) + if err != nil { + return nil, fmt.Errorf("discovery request failed: %w", err) + } + defer resp.Body.Close() + + // Read response body + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response body: %w", err) + } + + // Check for error response + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("facilitator listDiscoveryResources failed (%d): %s", resp.StatusCode, string(body)) + } + + // Parse response + var result DiscoveryResourcesResponse + if err := json.Unmarshal(body, &result); err != nil { + return nil, fmt.Errorf("failed to decode discovery response: %w", err) + } + + return &result, nil +} + +// buildDiscoveryURL constructs the full /discovery/resources URL with query parameters. +func (c *BazaarFacilitatorClient) buildDiscoveryURL(params *ListDiscoveryResourcesParams) (string, error) { + base := c.URL() + "/discovery/resources" + + if params == nil { + return base, nil + } + + u, err := url.Parse(base) + if err != nil { + return "", err + } + + q := u.Query() + if params.Type != "" { + q.Set("type", params.Type) + } + if params.Limit > 0 { + q.Set("limit", strconv.Itoa(params.Limit)) + } + if params.Offset > 0 { + q.Set("offset", strconv.Itoa(params.Offset)) + } + + u.RawQuery = q.Encode() + return u.String(), nil +} diff --git a/go/extensions/bazaar/facilitator_client_test.go b/go/extensions/bazaar/facilitator_client_test.go new file mode 100644 index 0000000000..c23ec4308b --- /dev/null +++ b/go/extensions/bazaar/facilitator_client_test.go @@ -0,0 +1,491 @@ +package bazaar + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + x402http "github.com/coinbase/x402/go/http" +) + +// testAuthProvider is a test helper that returns fixed auth headers. +type testAuthProvider struct { + headers x402http.AuthHeaders + err error +} + +func (p *testAuthProvider) GetAuthHeaders(_ context.Context) (x402http.AuthHeaders, error) { + return p.headers, p.err +} + +func TestWithBazaar(t *testing.T) { + client := x402http.NewHTTPFacilitatorClient(nil) + bazaarClient := WithBazaar(client) + + if bazaarClient == nil { + t.Fatal("Expected non-nil bazaar client") + } + if bazaarClient.HTTPFacilitatorClient != client { + t.Error("Expected embedded client to match original") + } +} + +func TestWithBazaar_PreservesOriginalMethods(t *testing.T) { + client := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: "https://example.com/facilitator", + }) + bazaarClient := WithBazaar(client) + + // Verify the wrapped client preserves the URL + if bazaarClient.URL() != "https://example.com/facilitator" { + t.Errorf("Expected URL https://example.com/facilitator, got %s", bazaarClient.URL()) + } +} + +func TestListDiscoveryResources_Success(t *testing.T) { + ctx := context.Background() + + expectedResponse := DiscoveryResourcesResponse{ + X402Version: 2, + Items: []DiscoveryResource{ + { + Resource: "https://api.example.com/data", + Type: "http", + X402Version: 2, + Accepts: []json.RawMessage{json.RawMessage(`{"scheme":"exact","network":"eip155:1"}`)}, + LastUpdated: "2026-03-01T00:00:00Z", + Metadata: map[string]any{"category": "data"}, + }, + }, + Pagination: Pagination{ + Limit: 20, + Offset: 0, + Total: 1, + }, + } + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/discovery/resources" { + t.Errorf("Expected path /discovery/resources, got %s", r.URL.Path) + } + if r.Method != "GET" { + t.Errorf("Expected GET method, got %s", r.Method) + } + if r.Header.Get("Content-Type") != "application/json" { + t.Errorf("Expected Content-Type application/json, got %s", r.Header.Get("Content-Type")) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(expectedResponse) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + result, err := client.ListDiscoveryResources(ctx, nil) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + if result.X402Version != 2 { + t.Errorf("Expected x402Version 2, got %d", result.X402Version) + } + if len(result.Items) != 1 { + t.Fatalf("Expected 1 item, got %d", len(result.Items)) + } + if result.Items[0].Resource != "https://api.example.com/data" { + t.Errorf("Expected resource URL https://api.example.com/data, got %s", result.Items[0].Resource) + } + if result.Items[0].Type != "http" { + t.Errorf("Expected type http, got %s", result.Items[0].Type) + } + if result.Items[0].X402Version != 2 { + t.Errorf("Expected item x402Version 2, got %d", result.Items[0].X402Version) + } + if result.Items[0].LastUpdated != "2026-03-01T00:00:00Z" { + t.Errorf("Expected lastUpdated 2026-03-01T00:00:00Z, got %s", result.Items[0].LastUpdated) + } + if result.Items[0].Metadata["category"] != "data" { + t.Errorf("Expected metadata category=data, got %v", result.Items[0].Metadata["category"]) + } + if result.Pagination.Limit != 20 { + t.Errorf("Expected pagination limit 20, got %d", result.Pagination.Limit) + } + if result.Pagination.Total != 1 { + t.Errorf("Expected pagination total 1, got %d", result.Pagination.Total) + } +} + +func TestListDiscoveryResources_WithParams(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + + if query.Get("type") != "http" { + t.Errorf("Expected type=http, got %s", query.Get("type")) + } + if query.Get("limit") != "10" { + t.Errorf("Expected limit=10, got %s", query.Get("limit")) + } + if query.Get("offset") != "5" { + t.Errorf("Expected offset=5, got %s", query.Get("offset")) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(DiscoveryResourcesResponse{ + X402Version: 2, + Items: []DiscoveryResource{}, + Pagination: Pagination{Limit: 10, Offset: 5, Total: 0}, + }) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + result, err := client.ListDiscoveryResources(ctx, &ListDiscoveryResourcesParams{ + Type: "http", + Limit: 10, + Offset: 5, + }) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + if result.Pagination.Limit != 10 { + t.Errorf("Expected pagination limit 10, got %d", result.Pagination.Limit) + } + if result.Pagination.Offset != 5 { + t.Errorf("Expected pagination offset 5, got %d", result.Pagination.Offset) + } +} + +func TestListDiscoveryResources_NoParams(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.RawQuery != "" { + t.Errorf("Expected no query params, got %s", r.URL.RawQuery) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(DiscoveryResourcesResponse{ + X402Version: 2, + Items: []DiscoveryResource{}, + Pagination: Pagination{Limit: 20, Offset: 0, Total: 0}, + }) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } +} + +func TestListDiscoveryResources_PartialParams(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + + if query.Get("type") != "mcp" { + t.Errorf("Expected type=mcp, got %s", query.Get("type")) + } + // limit and offset should not be set when zero + if query.Has("limit") { + t.Errorf("Expected no limit param, got %s", query.Get("limit")) + } + if query.Has("offset") { + t.Errorf("Expected no offset param, got %s", query.Get("offset")) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(DiscoveryResourcesResponse{ + X402Version: 2, + Items: []DiscoveryResource{}, + Pagination: Pagination{Limit: 20, Offset: 0, Total: 0}, + }) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + _, err := client.ListDiscoveryResources(ctx, &ListDiscoveryResourcesParams{ + Type: "mcp", + }) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } +} + +func TestListDiscoveryResources_ErrorResponse(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte("internal server error")) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err == nil { + t.Fatal("Expected error for 500 response") + } + + expected := "facilitator listDiscoveryResources failed (500): internal server error" + if err.Error() != expected { + t.Errorf("Expected error message %q, got %q", expected, err.Error()) + } +} + +func TestListDiscoveryResources_NotFound(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte("not found")) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err == nil { + t.Fatal("Expected error for 404 response") + } + + expected := "facilitator listDiscoveryResources failed (404): not found" + if err.Error() != expected { + t.Errorf("Expected error message %q, got %q", expected, err.Error()) + } +} + +func TestListDiscoveryResources_InvalidJSON(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"x402Version":`)) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err == nil { + t.Fatal("Expected error for invalid JSON response") + } +} + +func TestListDiscoveryResources_WithAuthHeaders(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + auth := r.Header.Get("Authorization") + if auth != "Bearer test-token" { + t.Errorf("Expected Authorization header 'Bearer test-token', got %q", auth) + } + + apiKey := r.Header.Get("X-Api-Key") + if apiKey != "my-key" { + t.Errorf("Expected X-Api-Key header 'my-key', got %q", apiKey) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(DiscoveryResourcesResponse{ + X402Version: 2, + Items: []DiscoveryResource{}, + Pagination: Pagination{Limit: 20, Offset: 0, Total: 0}, + }) + })) + defer server.Close() + + authProvider := &testAuthProvider{ + headers: x402http.AuthHeaders{ + Discovery: map[string]string{ + "Authorization": "Bearer test-token", + "X-Api-Key": "my-key", + }, + }, + } + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + AuthProvider: authProvider, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } +} + +func TestListDiscoveryResources_NoAuthProvider(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Should not have Authorization header when no auth provider + if r.Header.Get("Authorization") != "" { + t.Errorf("Expected no Authorization header, got %q", r.Header.Get("Authorization")) + } + + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(DiscoveryResourcesResponse{ + X402Version: 2, + Items: []DiscoveryResource{}, + Pagination: Pagination{Limit: 20, Offset: 0, Total: 0}, + }) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } +} + +func TestListDiscoveryResources_AuthProviderError(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + t.Error("Request should not have been made when auth provider fails") + w.WriteHeader(http.StatusOK) + })) + defer server.Close() + + authProvider := &testAuthProvider{ + err: http.ErrAbortHandler, + } + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + AuthProvider: authProvider, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err == nil { + t.Fatal("Expected error when auth provider fails") + } +} + +func TestListDiscoveryResources_MultipleItems(t *testing.T) { + ctx := context.Background() + + expectedResponse := DiscoveryResourcesResponse{ + X402Version: 2, + Items: []DiscoveryResource{ + { + Resource: "https://api.example.com/endpoint1", + Type: "http", + X402Version: 2, + Accepts: []json.RawMessage{json.RawMessage(`{"scheme":"exact"}`)}, + LastUpdated: "2026-03-01T00:00:00Z", + }, + { + Resource: "https://api.example.com/endpoint2", + Type: "http", + X402Version: 1, + Accepts: []json.RawMessage{json.RawMessage(`{"scheme":"exact"}`)}, + LastUpdated: "2026-02-28T00:00:00Z", + }, + { + Resource: "mcp://tools/search", + Type: "mcp", + X402Version: 2, + Accepts: []json.RawMessage{json.RawMessage(`{"scheme":"exact"}`)}, + LastUpdated: "2026-03-01T12:00:00Z", + }, + }, + Pagination: Pagination{ + Limit: 20, + Offset: 0, + Total: 3, + }, + } + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(expectedResponse) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + result, err := client.ListDiscoveryResources(ctx, nil) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + if len(result.Items) != 3 { + t.Fatalf("Expected 3 items, got %d", len(result.Items)) + } + if result.Items[0].Resource != "https://api.example.com/endpoint1" { + t.Errorf("Expected first resource https://api.example.com/endpoint1, got %s", result.Items[0].Resource) + } + if result.Items[2].Type != "mcp" { + t.Errorf("Expected third resource type mcp, got %s", result.Items[2].Type) + } + if result.Pagination.Total != 3 { + t.Errorf("Expected total 3, got %d", result.Pagination.Total) + } +} + +func TestListDiscoveryResources_ContextCancellation(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + cancel() // Cancel immediately + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + t.Error("Request should not have been made with cancelled context") + w.WriteHeader(http.StatusOK) + })) + defer server.Close() + + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: server.URL, + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err == nil { + t.Fatal("Expected error with cancelled context") + } +} + +func TestListDiscoveryResources_ConnectionError(t *testing.T) { + ctx := context.Background() + + // Use a URL that will fail to connect + client := WithBazaar(x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: "http://127.0.0.1:1", // Port 1 should fail + })) + + _, err := client.ListDiscoveryResources(ctx, nil) + if err == nil { + t.Fatal("Expected error for connection failure") + } +} diff --git a/go/http/facilitator_client.go b/go/http/facilitator_client.go index ca868799f9..d48eb22cec 100644 --- a/go/http/facilitator_client.go +++ b/go/http/facilitator_client.go @@ -37,6 +37,7 @@ type AuthHeaders struct { Verify map[string]string Settle map[string]string Supported map[string]string + Discovery map[string]string } // FacilitatorConfig configures the HTTP facilitator client @@ -101,6 +102,21 @@ func NewHTTPFacilitatorClient(config *FacilitatorConfig) *HTTPFacilitatorClient } } +// URL returns the base URL of the facilitator service. +func (c *HTTPFacilitatorClient) URL() string { + return c.url +} + +// HTTPClient returns the underlying HTTP client. +func (c *HTTPFacilitatorClient) HTTPClient() *http.Client { + return c.httpClient +} + +// GetAuthProvider returns the authentication provider, or nil if not configured. +func (c *HTTPFacilitatorClient) GetAuthProvider() AuthProvider { + return c.authProvider +} + // ============================================================================ // FacilitatorClient Implementation (Network Boundary - uses bytes) // ============================================================================ From 0c09ec1ca3beea166fd1d88ea6280b9c63d466be Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 12:34:50 +0900 Subject: [PATCH 008/129] Document Go SDK Bazaar facilitator client (#1418) * Update docs/extensions/bazaar.mdx Generated-By: mintlify-agent * Update docs/sdk-features.md Generated-By: mintlify-agent --------- Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- docs/extensions/bazaar.mdx | 49 ++++++++++++++++++++++++++++++++++++++ docs/sdk-features.md | 3 ++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/docs/extensions/bazaar.mdx b/docs/extensions/bazaar.mdx index 5d4e9b5dce..0f0b18d7b0 100644 --- a/docs/extensions/bazaar.mdx +++ b/docs/extensions/bazaar.mdx @@ -132,6 +132,55 @@ Fetch the list of available x402 services using the facilitator client: ); ``` + + ```go + package main + + import ( + "context" + "fmt" + + "github.com/coinbase/x402/go/extensions/bazaar" + x402http "github.com/coinbase/x402/go/http" + ) + + func main() { + ctx := context.Background() + + // Create facilitator client and extend with bazaar + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: "https://x402.org/facilitator", + }) + client := bazaar.WithBazaar(facilitatorClient) + + // List discovery resources + response, err := client.ListDiscoveryResources(ctx, &bazaar.ListDiscoveryResourcesParams{ + Type: "http", + Limit: 20, + Offset: 0, + }) + if err != nil { + panic(err) + } + + // Filter services under $0.10 + usdcAsset := "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" + maxPrice := 100000 // $0.10 in USDC atomic units (6 decimals) + + for _, item := range response.Items { + for _, paymentReq := range item.Accepts { + // Parse asset and maxAmountRequired from payment requirements + if asset, ok := paymentReq["asset"].(string); ok && asset == usdcAsset { + if maxAmount, ok := paymentReq["maxAmountRequired"].(string); ok { + // Convert and compare price + fmt.Printf("Found service: %s\n", item.Resource) + } + } + } + } + } + ``` + ```python from x402.http import FacilitatorConfig, HTTPFacilitatorClient diff --git a/docs/sdk-features.md b/docs/sdk-features.md index 40a797201a..632f6beeaa 100644 --- a/docs/sdk-features.md +++ b/docs/sdk-features.md @@ -42,7 +42,8 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt | Extension | TypeScript | Go | Python | |-----------|------------|-----|--------| -| bazaar | βœ… | βœ… | βœ… | +| bazaar (server) | βœ… | βœ… | βœ… | +| bazaar (facilitator client) | βœ… | βœ… | βœ… | | sign-in-with-x | βœ… | ❌ | ❌ | | payment-identifier | βœ… | βœ… | βœ… | From 08e149e69be587f2227ee2e7fb82edf52036d6ad Mon Sep 17 00:00:00 2001 From: wonjoon <39115630+wnjoon@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:30:01 +0900 Subject: [PATCH 009/129] feat(go/http): add onProtectedRequest hook for pre-payment request interception (#1371) * feat(go/http): add onProtectedRequest hook for pre-payment request interception * feat(go/http/gin): add PaymentMiddlewareFromHTTPServer for pre-configured server support --- .../unreleased/added-20260227-175046.yaml | 3 + go/http/gin/middleware.go | 39 +++ go/http/gin/middleware_test.go | 207 +++++++++++++++ go/http/server.go | 61 ++++- go/http/server_test.go | 245 ++++++++++++++++++ 5 files changed, 553 insertions(+), 2 deletions(-) create mode 100644 go/.changes/unreleased/added-20260227-175046.yaml diff --git a/go/.changes/unreleased/added-20260227-175046.yaml b/go/.changes/unreleased/added-20260227-175046.yaml new file mode 100644 index 0000000000..5d57a9031e --- /dev/null +++ b/go/.changes/unreleased/added-20260227-175046.yaml @@ -0,0 +1,3 @@ +kind: added +body: Added `onProtectedRequest` hook to HTTP resource server +time: 2026-02-27T17:50:46.051464+09:00 diff --git a/go/http/gin/middleware.go b/go/http/gin/middleware.go index 3d480580fe..e176e21fda 100644 --- a/go/http/gin/middleware.go +++ b/go/http/gin/middleware.go @@ -193,6 +193,45 @@ func PaymentMiddleware(routes x402http.RoutesConfig, server *x402.X402ResourceSe return createMiddlewareHandler(httpServer, config) } +// PaymentMiddlewareFromHTTPServer creates Gin middleware using a pre-configured HTTPServer. +// This allows registering hooks (e.g., OnProtectedRequest) on the server before attaching to the router. +// +// Example: +// +// resourceServer := x402.Newx402ResourceServer( +// x402.WithFacilitatorClient(facilitator), +// ).Register("eip155:*", evm.NewExactEvmScheme()) +// +// httpServer := x402http.Wrappedx402HTTPResourceServer(routes, resourceServer). +// OnProtectedRequest(requestHook) +// +// r.Use(ginmw.PaymentMiddlewareFromHTTPServer(httpServer)) +func PaymentMiddlewareFromHTTPServer(httpServer *x402http.HTTPServer, opts ...MiddlewareOption) gin.HandlerFunc { + config := &MiddlewareConfig{ + SyncFacilitatorOnStart: true, + Timeout: 30 * time.Second, + } + + // Apply options + for _, opt := range opts { + opt(config) + } + + httpServer.RegisterExtension(bazaar.BazaarResourceServerExtension) + + // Initialize if requested - queries facilitator /supported to populate facilitatorClients map + if config.SyncFacilitatorOnStart { + ctx, cancel := context.WithTimeout(context.Background(), config.Timeout) + defer cancel() + if err := httpServer.Initialize(ctx); err != nil { + fmt.Printf("Warning: failed to initialize x402 server: %v\n", err) + } + } + + // Create middleware handler using shared logic + return createMiddlewareHandler(httpServer, config) +} + // PaymentMiddlewareFromConfig creates Gin middleware for x402 payment handling. // This creates the server internally from the provided options. func PaymentMiddlewareFromConfig(routes x402http.RoutesConfig, opts ...MiddlewareOption) gin.HandlerFunc { diff --git a/go/http/gin/middleware_test.go b/go/http/gin/middleware_test.go index 2367beb190..b67b02ecd1 100644 --- a/go/http/gin/middleware_test.go +++ b/go/http/gin/middleware_test.go @@ -882,6 +882,213 @@ func TestPaymentMiddleware_WithTimeout(t *testing.T) { } } +// ============================================================================ +// PaymentMiddlewareFromHTTPServer Tests +// ============================================================================ + +func TestPaymentMiddlewareFromHTTPServer_Returns402ForProtectedRoute(t *testing.T) { + mockClient := &mockFacilitatorClient{ + supportedFunc: func(ctx context.Context) (x402.SupportedResponse, error) { + return x402.SupportedResponse{ + Kinds: []x402.SupportedKind{ + {X402Version: 2, Scheme: "exact", Network: "eip155:1"}, + }, + Extensions: []string{}, + Signers: make(map[string][]string), + }, nil + }, + } + + routes := x402http.RoutesConfig{ + "GET /api": x402http.RouteConfig{ + Accepts: x402http.PaymentOptions{ + { + Scheme: "exact", + PayTo: "0xtest", + Price: "$1.00", + Network: "eip155:1", + }, + }, + }, + } + + // Build the resource server externally + resourceServer := x402.Newx402ResourceServer( + x402.WithFacilitatorClient(mockClient), + ) + resourceServer.Register("eip155:1", &mockSchemeServer{scheme: "exact"}) + + // Wrap with HTTP server + httpServer := x402http.Wrappedx402HTTPResourceServer(routes, resourceServer) + + // Use PaymentMiddlewareFromHTTPServer + router := createTestRouter() + router.Use(PaymentMiddlewareFromHTTPServer(httpServer, WithTimeout(5*time.Second))) + + router.GET("/api", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"data": "protected"}) + }) + + req := httptest.NewRequest("GET", "/api", nil) + req.Header.Set("Accept", "application/json") + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + if w.Code != http.StatusPaymentRequired { + t.Errorf("Expected status 402, got %d", w.Code) + } +} + +func TestPaymentMiddlewareFromHTTPServer_PassesThroughNonProtectedRoute(t *testing.T) { + routes := x402http.RoutesConfig{ + "GET /api": x402http.RouteConfig{ + Accepts: x402http.PaymentOptions{ + { + Scheme: "exact", + PayTo: "0xtest", + Price: "$1.00", + Network: "eip155:1", + }, + }, + }, + } + + resourceServer := x402.Newx402ResourceServer() + httpServer := x402http.Wrappedx402HTTPResourceServer(routes, resourceServer) + + router := createTestRouter() + router.Use(PaymentMiddlewareFromHTTPServer(httpServer, WithSyncFacilitatorOnStart(false))) + + nextCalled := false + router.GET("/public", func(c *gin.Context) { + nextCalled = true + c.JSON(http.StatusOK, gin.H{"message": "public"}) + }) + + req := httptest.NewRequest("GET", "/public", nil) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + if !nextCalled { + t.Error("Expected next() to be called for non-protected route") + } + if w.Code != http.StatusOK { + t.Errorf("Expected status 200, got %d", w.Code) + } +} + +func TestPaymentMiddlewareFromHTTPServer_HookGrantsAccess(t *testing.T) { + mockClient := &mockFacilitatorClient{ + supportedFunc: func(ctx context.Context) (x402.SupportedResponse, error) { + return x402.SupportedResponse{ + Kinds: []x402.SupportedKind{ + {X402Version: 2, Scheme: "exact", Network: "eip155:1"}, + }, + Extensions: []string{}, + Signers: make(map[string][]string), + }, nil + }, + } + + routes := x402http.RoutesConfig{ + "GET /api": x402http.RouteConfig{ + Accepts: x402http.PaymentOptions{ + { + Scheme: "exact", + PayTo: "0xtest", + Price: "$1.00", + Network: "eip155:1", + }, + }, + }, + } + + resourceServer := x402.Newx402ResourceServer( + x402.WithFacilitatorClient(mockClient), + ) + resourceServer.Register("eip155:1", &mockSchemeServer{scheme: "exact"}) + + // Register a hook that grants free access + httpServer := x402http.Wrappedx402HTTPResourceServer(routes, resourceServer). + OnProtectedRequest(func(ctx context.Context, reqCtx x402http.HTTPRequestContext, routeConfig x402http.RouteConfig) (*x402http.ProtectedRequestHookResult, error) { + return &x402http.ProtectedRequestHookResult{GrantAccess: true}, nil + }) + + router := createTestRouter() + router.Use(PaymentMiddlewareFromHTTPServer(httpServer, WithTimeout(5*time.Second))) + + nextCalled := false + router.GET("/api", func(c *gin.Context) { + nextCalled = true + c.JSON(http.StatusOK, gin.H{"data": "free-access"}) + }) + + // Request without payment header - hook should grant access + req := httptest.NewRequest("GET", "/api", nil) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Errorf("Expected status 200 (hook granted access), got %d. Body: %s", w.Code, w.Body.String()) + } + if !nextCalled { + t.Error("Expected next handler to be called when hook grants access") + } +} + +func TestPaymentMiddlewareFromHTTPServer_HookAbortsRequest(t *testing.T) { + mockClient := &mockFacilitatorClient{ + supportedFunc: func(ctx context.Context) (x402.SupportedResponse, error) { + return x402.SupportedResponse{ + Kinds: []x402.SupportedKind{ + {X402Version: 2, Scheme: "exact", Network: "eip155:1"}, + }, + Extensions: []string{}, + Signers: make(map[string][]string), + }, nil + }, + } + + routes := x402http.RoutesConfig{ + "GET /api": x402http.RouteConfig{ + Accepts: x402http.PaymentOptions{ + { + Scheme: "exact", + PayTo: "0xtest", + Price: "$1.00", + Network: "eip155:1", + }, + }, + }, + } + + resourceServer := x402.Newx402ResourceServer( + x402.WithFacilitatorClient(mockClient), + ) + resourceServer.Register("eip155:1", &mockSchemeServer{scheme: "exact"}) + + // Register a hook that aborts the request + httpServer := x402http.Wrappedx402HTTPResourceServer(routes, resourceServer). + OnProtectedRequest(func(ctx context.Context, reqCtx x402http.HTTPRequestContext, routeConfig x402http.RouteConfig) (*x402http.ProtectedRequestHookResult, error) { + return &x402http.ProtectedRequestHookResult{Abort: true, Reason: "IP blocked"}, nil + }) + + router := createTestRouter() + router.Use(PaymentMiddlewareFromHTTPServer(httpServer, WithTimeout(5*time.Second))) + + router.GET("/api", func(c *gin.Context) { + t.Error("Handler should not be called when hook aborts") + }) + + req := httptest.NewRequest("GET", "/api", nil) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + if w.Code != http.StatusForbidden { + t.Errorf("Expected status 403 (hook aborted), got %d", w.Code) + } +} + // ============================================================================ // X402Payment (Builder Pattern) Tests // ============================================================================ diff --git a/go/http/server.go b/go/http/server.go index 13ce8e3438..27adda9873 100644 --- a/go/http/server.go +++ b/go/http/server.go @@ -127,6 +127,23 @@ type CompiledRoute struct { // Request/Response Types // ============================================================================ +// ProtectedRequestHookResult represents the result of a protected request hook. +// A nil result means the hook has no opinion and the next hook (or payment flow) should proceed. +type ProtectedRequestHookResult struct { + // GrantAccess bypasses payment and grants free access to the resource. + GrantAccess bool + // Abort denies the request with a 403 status and the provided Reason. + Abort bool + Reason string +} + +// ProtectedRequestHook is called on every request to a protected route, before payment processing. +// It receives the request context and the matched route configuration. +// Return nil to continue to the next hook or payment flow. +// Return a result with GrantAccess=true to bypass payment. +// Return a result with Abort=true to deny the request with a 403 status. +type ProtectedRequestHook func(ctx context.Context, reqCtx HTTPRequestContext, routeConfig RouteConfig) (*ProtectedRequestHookResult, error) + // HTTPRequestContext encapsulates an HTTP request type HTTPRequestContext struct { Adapter HTTPAdapter @@ -213,8 +230,9 @@ func (e *RouteConfigurationError) Error() string { // x402HTTPResourceServer provides HTTP-specific payment handling type x402HTTPResourceServer struct { *x402.X402ResourceServer - compiledRoutes []CompiledRoute - paywallProvider PaywallProvider + compiledRoutes []CompiledRoute + paywallProvider PaywallProvider + protectedRequestHooks []ProtectedRequestHook } // Newx402HTTPResourceServer creates a new HTTP resource server @@ -256,6 +274,15 @@ func (s *x402HTTPResourceServer) RegisterPaywallProvider(provider PaywallProvide return s } +// OnProtectedRequest registers a hook that runs on every request to a protected route, +// before payment processing. Hooks are executed in registration order; the first hook +// to return a non-nil result determines the outcome. +// Returns the server instance for method chaining. +func (s *x402HTTPResourceServer) OnProtectedRequest(hook ProtectedRequestHook) *x402HTTPResourceServer { + s.protectedRequestHooks = append(s.protectedRequestHooks, hook) + return s +} + // Initialize initializes the server by populating facilitator data and validating route configuration. // It calls the parent server's Initialize to fetch facilitator support, then validates that all // configured routes have matching scheme registrations and facilitator support. @@ -384,6 +411,36 @@ func (s *x402HTTPResourceServer) ProcessHTTPRequest(ctx context.Context, reqCtx return HTTPProcessResult{Type: ResultNoPaymentRequired} } + // Execute protected request hooks before any payment processing + for _, hook := range s.protectedRequestHooks { + result, err := hook(ctx, reqCtx, *routeConfig) + if err != nil { + return HTTPProcessResult{ + Type: ResultPaymentError, + Response: &HTTPResponseInstructions{ + Status: 500, + Headers: map[string]string{"Content-Type": "application/json"}, + Body: map[string]string{"error": fmt.Sprintf("protected request hook error: %v", err)}, + }, + } + } + if result != nil { + if result.GrantAccess { + return HTTPProcessResult{Type: ResultNoPaymentRequired} + } + if result.Abort { + return HTTPProcessResult{ + Type: ResultPaymentError, + Response: &HTTPResponseInstructions{ + Status: 403, + Headers: map[string]string{"Content-Type": "application/json"}, + Body: map[string]string{"error": result.Reason}, + }, + } + } + } + } + // Get payment options from route config paymentOptions := routeConfig.Accepts if len(paymentOptions) == 0 { diff --git a/go/http/server_test.go b/go/http/server_test.go index 7b05fd5524..b5689a76db 100644 --- a/go/http/server_test.go +++ b/go/http/server_test.go @@ -832,3 +832,248 @@ func (m *mockFacilitatorClient) GetSupported(ctx context.Context) (x402.Supporte func (m *mockFacilitatorClient) Identifier() string { return "mock" } + +// ============================================================================ +// OnProtectedRequest Hook Tests +// ============================================================================ + +func TestOnProtectedRequest_GrantAccess(t *testing.T) { + routes := RoutesConfig{ + "GET /api": { + Accepts: PaymentOptions{{Scheme: "exact", PayTo: "0xtest", Price: "$1.00", Network: "eip155:1"}}, + }, + } + + server := Newx402HTTPResourceServer(routes). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + return &ProtectedRequestHookResult{GrantAccess: true}, nil + }) + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/api", url: "http://example.com/api"}, + Path: "/api", + Method: "GET", + } + + result := server.ProcessHTTPRequest(context.Background(), reqCtx, nil) + if result.Type != ResultNoPaymentRequired { + t.Errorf("Expected no-payment-required, got %s", result.Type) + } +} + +func TestOnProtectedRequest_Abort(t *testing.T) { + routes := RoutesConfig{ + "GET /api": { + Accepts: PaymentOptions{{Scheme: "exact", PayTo: "0xtest", Price: "$1.00", Network: "eip155:1"}}, + }, + } + + server := Newx402HTTPResourceServer(routes). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + return &ProtectedRequestHookResult{Abort: true, Reason: "forbidden"}, nil + }) + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/api", url: "http://example.com/api"}, + Path: "/api", + Method: "GET", + } + + result := server.ProcessHTTPRequest(context.Background(), reqCtx, nil) + if result.Type != ResultPaymentError { + t.Errorf("Expected payment-error, got %s", result.Type) + } + if result.Response == nil { + t.Fatal("Expected response instructions") + } + if result.Response.Status != 403 { + t.Errorf("Expected status 403, got %d", result.Response.Status) + } + body, ok := result.Response.Body.(map[string]string) + if !ok { + t.Fatal("Expected body to be map[string]string") + } + if body["error"] != "forbidden" { + t.Errorf("Expected error 'forbidden', got '%s'", body["error"]) + } +} + +func TestOnProtectedRequest_Continue(t *testing.T) { + ctx := context.Background() + + routes := RoutesConfig{ + "GET /api": { + Accepts: PaymentOptions{{Scheme: "exact", PayTo: "0xtest", Price: "$1.00", Network: "eip155:1"}}, + }, + } + + mockServer := &mockSchemeServer{scheme: "exact"} + mockClient := &mockFacilitatorClient{ + supported: func(ctx context.Context) (x402.SupportedResponse, error) { + return x402.SupportedResponse{ + Kinds: []x402.SupportedKind{{X402Version: 2, Scheme: "exact", Network: "eip155:1"}}, + Extensions: []string{}, + Signers: make(map[string][]string), + }, nil + }, + } + + // Hook returns nil β€” should continue to payment flow + server := Newx402HTTPResourceServer(routes, x402.WithFacilitatorClient(mockClient), x402.WithSchemeServer("eip155:1", mockServer)). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + return nil, nil + }) + _ = server.Initialize(ctx) + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/api", url: "http://example.com/api", accept: "application/json"}, + Path: "/api", + Method: "GET", + } + + result := server.ProcessHTTPRequest(ctx, reqCtx, nil) + // Without a payment header, should get 402 + if result.Type != ResultPaymentError { + t.Errorf("Expected payment-error (402), got %s", result.Type) + } + if result.Response != nil && result.Response.Status != 402 { + t.Errorf("Expected status 402, got %d", result.Response.Status) + } +} + +func TestOnProtectedRequest_MultipleHooks_FirstNonNilWins(t *testing.T) { + routes := RoutesConfig{ + "GET /api": { + Accepts: PaymentOptions{{Scheme: "exact", PayTo: "0xtest", Price: "$1.00", Network: "eip155:1"}}, + }, + } + + callOrder := []string{} + + server := Newx402HTTPResourceServer(routes). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + callOrder = append(callOrder, "hook1") + return nil, nil // no opinion + }). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + callOrder = append(callOrder, "hook2") + return &ProtectedRequestHookResult{GrantAccess: true}, nil + }). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + callOrder = append(callOrder, "hook3") + return &ProtectedRequestHookResult{Abort: true, Reason: "should not reach"}, nil + }) + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/api", url: "http://example.com/api"}, + Path: "/api", + Method: "GET", + } + + result := server.ProcessHTTPRequest(context.Background(), reqCtx, nil) + if result.Type != ResultNoPaymentRequired { + t.Errorf("Expected no-payment-required, got %s", result.Type) + } + if len(callOrder) != 2 || callOrder[0] != "hook1" || callOrder[1] != "hook2" { + t.Errorf("Expected [hook1, hook2], got %v", callOrder) + } +} + +func TestOnProtectedRequest_HookError(t *testing.T) { + routes := RoutesConfig{ + "GET /api": { + Accepts: PaymentOptions{{Scheme: "exact", PayTo: "0xtest", Price: "$1.00", Network: "eip155:1"}}, + }, + } + + server := Newx402HTTPResourceServer(routes). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + return nil, errors.New("hook failed") + }) + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/api", url: "http://example.com/api"}, + Path: "/api", + Method: "GET", + } + + result := server.ProcessHTTPRequest(context.Background(), reqCtx, nil) + if result.Type != ResultPaymentError { + t.Errorf("Expected payment-error, got %s", result.Type) + } + if result.Response == nil { + t.Fatal("Expected response instructions") + } + if result.Response.Status != 500 { + t.Errorf("Expected status 500, got %d", result.Response.Status) + } +} + +func TestOnProtectedRequest_ContextPassing(t *testing.T) { + routes := RoutesConfig{ + "GET /api/data": { + Accepts: PaymentOptions{{Scheme: "exact", PayTo: "0xtest", Price: "$2.00", Network: "eip155:1"}}, + Description: "Data endpoint", + }, + } + + var capturedReqCtx HTTPRequestContext + var capturedRoute RouteConfig + + server := Newx402HTTPResourceServer(routes). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + capturedReqCtx = reqCtx + capturedRoute = route + return &ProtectedRequestHookResult{GrantAccess: true}, nil + }) + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/api/data", url: "http://example.com/api/data"}, + Path: "/api/data", + Method: "GET", + } + + server.ProcessHTTPRequest(context.Background(), reqCtx, nil) + + if capturedReqCtx.Path != "/api/data" { + t.Errorf("Expected path '/api/data', got '%s'", capturedReqCtx.Path) + } + if capturedReqCtx.Method != "GET" { + t.Errorf("Expected method 'GET', got '%s'", capturedReqCtx.Method) + } + if capturedRoute.Description != "Data endpoint" { + t.Errorf("Expected description 'Data endpoint', got '%s'", capturedRoute.Description) + } + if len(capturedRoute.Accepts) != 1 || capturedRoute.Accepts[0].Price != "$2.00" { + t.Errorf("Expected route accepts with price $2.00, got %+v", capturedRoute.Accepts) + } +} + +func TestOnProtectedRequest_UnmatchedRoute_HookNotCalled(t *testing.T) { + routes := RoutesConfig{ + "GET /api": { + Accepts: PaymentOptions{{Scheme: "exact", PayTo: "0xtest", Price: "$1.00", Network: "eip155:1"}}, + }, + } + + hookCalled := false + server := Newx402HTTPResourceServer(routes). + OnProtectedRequest(func(ctx context.Context, reqCtx HTTPRequestContext, route RouteConfig) (*ProtectedRequestHookResult, error) { + hookCalled = true + return &ProtectedRequestHookResult{Abort: true, Reason: "should not be called"}, nil + }) + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/public", url: "http://example.com/public"}, + Path: "/public", + Method: "GET", + } + + result := server.ProcessHTTPRequest(context.Background(), reqCtx, nil) + if result.Type != ResultNoPaymentRequired { + t.Errorf("Expected no-payment-required, got %s", result.Type) + } + if hookCalled { + t.Error("Hook should not be called for unmatched routes") + } +} From 1ae9e24fa275d06d8bf0b68a03b085102f5046de Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:37:15 +0900 Subject: [PATCH 010/129] Document Go OnProtectedRequest hook (#1422) * Update docs/advanced-concepts/lifecycle-hooks.mdx Generated-By: mintlify-agent * Update docs/sdk-features.md Generated-By: mintlify-agent --------- Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- docs/advanced-concepts/lifecycle-hooks.mdx | 26 +++++++++++++++++++++- docs/sdk-features.md | 2 +- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/advanced-concepts/lifecycle-hooks.mdx b/docs/advanced-concepts/lifecycle-hooks.mdx index cb8ccd8eb5..c37bab531e 100644 --- a/docs/advanced-concepts/lifecycle-hooks.mdx +++ b/docs/advanced-concepts/lifecycle-hooks.mdx @@ -118,7 +118,31 @@ Register hooks for HTTP-specific request handling before payment processing. Use *Coming soon.* - *Coming soon.* + ```go + import ( + "context" + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + ) + + // Create resource server + resourceServer := x402.Newx402ResourceServer( + x402.WithFacilitatorClient(facilitatorClient), + ) + + // Wrap with HTTP server and register hook + httpServer := x402http.Wrappedx402HTTPResourceServer(routes, resourceServer). + OnProtectedRequest(func(ctx context.Context, reqCtx x402http.HTTPRequestContext, routeConfig x402http.RouteConfig) (*x402http.ProtectedRequestHookResult, error) { + apiKey := reqCtx.Adapter.GetHeader("X-API-Key") + + if apiKey != "" && isValidApiKey(apiKey) { + return &x402http.ProtectedRequestHookResult{GrantAccess: true}, nil + } + + // No valid API key β€” continue to payment flow + return nil, nil + }) + ``` diff --git a/docs/sdk-features.md b/docs/sdk-features.md index 632f6beeaa..d876b2e76b 100644 --- a/docs/sdk-features.md +++ b/docs/sdk-features.md @@ -66,7 +66,7 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt | onBeforeSettle | βœ… | βœ… | βœ… | | onAfterSettle | βœ… | βœ… | βœ… | | onSettleFailure | βœ… | βœ… | βœ… | -| onProtectedRequest (HTTP) | βœ… | ❌ | ❌ | +| onProtectedRequest (HTTP) | βœ… | βœ… | ❌ | ## Facilitator Hooks From 5cb40cd08b94232d7e286c0fc35366e9fa1448da Mon Sep 17 00:00:00 2001 From: "Ryan R. Fox" Date: Tue, 3 Mar 2026 00:40:07 -0500 Subject: [PATCH 011/129] fix(exact): enforce strict amount equality per spec (#1388) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(exact): enforce strict amount equality per spec The exact scheme spec states the transferred amount MUST equal PaymentRequirements.amount exactly. All four facilitators used < instead of !==, silently accepting overpayments. Changes: - SVM V2: amount !== BigInt(requirements.amount), reason: amount_mismatch - SVM V1: amount !== BigInt(requirementsV1.maxAmountRequired), reason: amount_mismatch - EVM EIP-3009: authorization.value !== requirements.amount, reason: authorization_value_mismatch - EVM Permit2: permitted.amount !== requirements.amount, reason: amount_mismatch Error reasons renamed from _insufficient to _mismatch to cover both directions (underpayment and overpayment). Closes #1378 * fix(exact): also enforce strict amount equality in v1 EVM facilitator Applies the same < to !== comparison change to the v1 EVM facilitator for consistency with the v2 EVM and SVM facilitators. * docs(spec): correct exact scheme amount validation description Two inaccuracies in x402-specification-v2.md relative to the authoritative scheme contract in specs/schemes/exact/scheme_exact.md: - Β§6.1.2 step 3: 'meets or exceeds' -> 'exactly matches' The exact scheme requires strict equality (scheme_exact.md L24, scheme_exact_svm.md L143). This section describes the EVM implementation of the exact scheme, not the upto scheme. - Β§9 error table: rename invalid_exact_evm_payload_authorization_value to invalid_exact_evm_payload_authorization_value_mismatch and update description from 'insufficient' to 'does not exactly match'. These error codes are EVM-scheme-layer codes; the table is updated to reflect the renamed code in the accompanying implementation change. * style(evm): wrap long if condition in permit2.ts for prettier compliance --- specs/x402-specification-v2.md | 4 ++-- .../mechanisms/evm/src/exact/facilitator/eip3009.ts | 6 +++--- .../mechanisms/evm/src/exact/facilitator/permit2.ts | 7 +++++-- .../mechanisms/evm/src/exact/v1/facilitator/scheme.ts | 6 +++--- .../mechanisms/evm/test/unit/v1/facilitator.test.ts | 2 +- .../mechanisms/svm/src/exact/facilitator/scheme.ts | 4 ++-- .../mechanisms/svm/src/exact/v1/facilitator/scheme.ts | 6 +++--- 7 files changed, 19 insertions(+), 16 deletions(-) diff --git a/specs/x402-specification-v2.md b/specs/x402-specification-v2.md index 00cdd18cac..8c641c1661 100644 --- a/specs/x402-specification-v2.md +++ b/specs/x402-specification-v2.md @@ -290,7 +290,7 @@ The facilitator performs the following verification steps: 1. **Signature Validation**: Verify the EIP-712 signature is valid and properly signed by the payer 2. **Balance Verification**: Confirm the payer has sufficient token balance for the transfer -3. **Amount Validation**: Ensure the payment amount meets or exceeds the required amount +3. **Amount Validation**: Ensure the payment amount exactly matches the required amount 4. **Time Window Check**: Verify the authorization is within its valid time range 5. **Parameter Matching**: Confirm authorization parameters match the original payment requirements 6. **Transaction Simulation**: Simulate the `transferWithAuthorization` transaction to ensure it would succeed @@ -579,7 +579,7 @@ The x402 protocol defines standard error codes that may be returned by facilitat - **`insufficient_funds`**: Client does not have enough tokens to complete the payment - **`invalid_exact_evm_payload_authorization_valid_after`**: Payment authorization is not yet valid (before validAfter timestamp) - **`invalid_exact_evm_payload_authorization_valid_before`**: Payment authorization has expired (after validBefore timestamp) -- **`invalid_exact_evm_payload_authorization_value`**: Payment amount is insufficient for the required payment +- **`invalid_exact_evm_payload_authorization_value_mismatch`**: Payment amount does not exactly match the required amount - **`invalid_exact_evm_payload_signature`**: Payment authorization signature is invalid or improperly signed - **`invalid_exact_evm_payload_recipient_mismatch`**: Recipient address does not match payment requirements - **`invalid_network`**: Specified blockchain network is not supported diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts index b353b56098..bbe26de00f 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts @@ -197,11 +197,11 @@ export async function verifyEIP3009( // If we can't check balance, continue with other validations } - // Verify amount is sufficient - if (BigInt(eip3009Payload.authorization.value) < BigInt(requirements.amount)) { + // Verify amount exactly matches requirements + if (BigInt(eip3009Payload.authorization.value) !== BigInt(requirements.amount)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_value", + invalidReason: "invalid_exact_evm_payload_authorization_value_mismatch", payer, }; } diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts index 9a30840fd9..c88b35b548 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts @@ -117,10 +117,13 @@ export async function verifyPermit2( }; } - if (BigInt(permit2Payload.permit2Authorization.permitted.amount) < BigInt(requirements.amount)) { + // Verify amount exactly matches requirements + if ( + BigInt(permit2Payload.permit2Authorization.permitted.amount) !== BigInt(requirements.amount) + ) { return { isValid: false, - invalidReason: "permit2_insufficient_amount", + invalidReason: "permit2_amount_mismatch", payer, }; } diff --git a/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts b/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts index 2920dec252..0abfc8d9a7 100644 --- a/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts @@ -258,11 +258,11 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { // If we can't check balance, continue with other validations } - // Verify amount is sufficient - if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) { + // Verify amount exactly matches requirements + if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_value", + invalidReason: "invalid_exact_evm_payload_authorization_value_mismatch", payer: exactEvmPayload.authorization.from, }; } diff --git a/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts b/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts index b430491647..3d1e53761d 100644 --- a/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts +++ b/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts @@ -169,7 +169,7 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.verify(payload as never, requirements as never); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("invalid_exact_evm_payload_authorization_value"); + expect(result.invalidReason).toBe("invalid_exact_evm_payload_authorization_value_mismatch"); }); it("should reject if balance is insufficient", async () => { diff --git a/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts index 0aa54064db..73568a278a 100644 --- a/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts @@ -258,10 +258,10 @@ export class ExactSvmScheme implements SchemeNetworkFacilitator { // Verify transfer amount meets requirements const amount = parsedTransfer.data.amount; - if (amount < BigInt(requirements.amount)) { + if (amount !== BigInt(requirements.amount)) { return { isValid: false, - invalidReason: "invalid_exact_svm_payload_amount_insufficient", + invalidReason: "invalid_exact_svm_payload_amount_mismatch", payer, }; } diff --git a/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts b/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts index 16d0f465f7..82e338cbc9 100644 --- a/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts @@ -259,12 +259,12 @@ export class ExactSvmSchemeV1 implements SchemeNetworkFacilitator { }; } - // Verify transfer amount meets requirements + // Verify transfer amount exactly matches requirements const amount = parsedTransfer.data.amount; - if (amount < BigInt(requirementsV1.maxAmountRequired)) { + if (amount !== BigInt(requirementsV1.maxAmountRequired)) { return { isValid: false, - invalidReason: "invalid_exact_svm_payload_amount_insufficient", + invalidReason: "invalid_exact_svm_payload_amount_mismatch", payer, }; } From 23897bfd5c2e466710caaf167ff69a23d2e39ca3 Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:07:22 +0900 Subject: [PATCH 012/129] Update docs/faq.md (#1423) Generated-By: mintlify-agent Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- docs/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index 4648d881b7..99d48960e8 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -131,7 +131,7 @@ We acknowledge that the repo is primarily under Coinbase ownership today. This i #### I keep getting `402 Payment Required`, even after attaching `PAYMENT-SIGNATURE`. Why? 1. Signature is invalid (wrong chain ID or payload fields). -2. Payment amount is less than the required `amount` in the payment requirements. +2. Payment amount does not exactly match the required `amount` in the payment requirements (the exact scheme requires strict equality - no overpayment or underpayment). 3. Address has insufficient USDC or was flagged by KYT.\ Check the `error` field in the server's JSON response for details. From f41baed744fd0f5a074bf54740cf47692e9164f9 Mon Sep 17 00:00:00 2001 From: JumpboxTech Date: Tue, 3 Mar 2026 00:39:14 -0700 Subject: [PATCH 013/129] fix(specs,ts): add x402Version to facilitator verify/settle request body (#1312) All four SDK implementations (TypeScript, Go, Go legacy, Python) include x402Version as a top-level field in the facilitator /verify and /settle request bodies, but neither the v1/v2 specs nor the TypeScript types document it. This adds x402Version to: - v2 spec section 7.1 (POST /verify) request schema - v1 spec section 7.1 (POST /verify) request schema - VerifyRequest and SettleRequest types in @x402/core - VerifyRequestV1 and SettleRequestV1 types in @x402/core Closes #1176 --- specs/x402-specification-v1.md | 2 ++ specs/x402-specification-v2.md | 2 ++ .../add-x402version-to-facilitator-request-types.md | 5 +++++ typescript/packages/core/src/types/facilitator.ts | 2 ++ typescript/packages/core/src/types/v1/index.ts | 2 ++ 5 files changed, 13 insertions(+) create mode 100644 typescript/.changeset/add-x402version-to-facilitator-request-types.md diff --git a/specs/x402-specification-v1.md b/specs/x402-specification-v1.md index 48a71e2298..32191136ab 100644 --- a/specs/x402-specification-v1.md +++ b/specs/x402-specification-v1.md @@ -280,6 +280,7 @@ Verifies a payment authorization without executing the transaction on the blockc ```json { + "x402Version": 1, "paymentPayload": { /* PaymentPayload schema */ }, @@ -293,6 +294,7 @@ Example with actual data: ```json { + "x402Version": 1, "paymentPayload": { "x402Version": 1, "scheme": "exact", diff --git a/specs/x402-specification-v2.md b/specs/x402-specification-v2.md index 8c641c1661..da55d2b21f 100644 --- a/specs/x402-specification-v2.md +++ b/specs/x402-specification-v2.md @@ -323,6 +323,7 @@ Verifies a payment authorization without executing the transaction on the blockc ```json { + "x402Version": 2, "paymentPayload": { /* PaymentPayload schema */ }, @@ -336,6 +337,7 @@ Example with actual data: ```json { + "x402Version": 2, "paymentPayload": { "x402Version": 2, "resource": { diff --git a/typescript/.changeset/add-x402version-to-facilitator-request-types.md b/typescript/.changeset/add-x402version-to-facilitator-request-types.md new file mode 100644 index 0000000000..63df2d3a3e --- /dev/null +++ b/typescript/.changeset/add-x402version-to-facilitator-request-types.md @@ -0,0 +1,5 @@ +--- +"@x402/core": patch +--- + +Added `x402Version` field to `VerifyRequest`, `SettleRequest`, `VerifyRequestV1`, and `SettleRequestV1` types to match what all SDK implementations already send in facilitator request bodies. diff --git a/typescript/packages/core/src/types/facilitator.ts b/typescript/packages/core/src/types/facilitator.ts index b37c9e8754..3b6adc07cc 100644 --- a/typescript/packages/core/src/types/facilitator.ts +++ b/typescript/packages/core/src/types/facilitator.ts @@ -2,6 +2,7 @@ import { PaymentPayload, PaymentRequirements } from "./payments"; import { Network } from "./"; export type VerifyRequest = { + x402Version: number; paymentPayload: PaymentPayload; paymentRequirements: PaymentRequirements; }; @@ -15,6 +16,7 @@ export type VerifyResponse = { }; export type SettleRequest = { + x402Version: number; paymentPayload: PaymentPayload; paymentRequirements: PaymentRequirements; }; diff --git a/typescript/packages/core/src/types/v1/index.ts b/typescript/packages/core/src/types/v1/index.ts index da674995c5..8de7e425b4 100644 --- a/typescript/packages/core/src/types/v1/index.ts +++ b/typescript/packages/core/src/types/v1/index.ts @@ -30,11 +30,13 @@ export type PaymentPayloadV1 = { // Facilitator Requests/Responses export type VerifyRequestV1 = { + x402Version: number; paymentPayload: PaymentPayloadV1; paymentRequirements: PaymentRequirementsV1; }; export type SettleRequestV1 = { + x402Version: number; paymentPayload: PaymentPayloadV1; paymentRequirements: PaymentRequirementsV1; }; From 749c3219a5ee39bcc96084a5a13e2a201c9a786d Mon Sep 17 00:00:00 2001 From: AI Agent Economy <220628848+up2itnow0822@users.noreply.github.com> Date: Tue, 3 Mar 2026 13:06:57 -0600 Subject: [PATCH 014/129] =?UTF-8?q?ecosystem:=20add=20ClawPay=20MCP=20?= =?UTF-8?q?=E2=80=94=20non-custodial=20x402=20payment=20layer=20for=20AI?= =?UTF-8?q?=20agents=20(#1381)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: AI Agent Economy --- .../app/ecosystem/partners-data/clawpay-mcp/metadata.json | 7 +++++++ typescript/site/public/logos/clawpay-mcp.svg | 6 ++++++ 2 files changed, 13 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/clawpay-mcp/metadata.json create mode 100644 typescript/site/public/logos/clawpay-mcp.svg diff --git a/typescript/site/app/ecosystem/partners-data/clawpay-mcp/metadata.json b/typescript/site/app/ecosystem/partners-data/clawpay-mcp/metadata.json new file mode 100644 index 0000000000..c014ae6230 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/clawpay-mcp/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "ClawPay MCP", + "description": "Open-source, non-custodial x402 MCP payment layer for AI agents. Agents sign transactions locally with no custodial infrastructure required. Supports x402 V2 sessions, spend limits, and multi-chain payments.", + "logoUrl": "/logos/clawpay-mcp.svg", + "websiteUrl": "https://www.npmjs.com/package/clawpay-mcp", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/public/logos/clawpay-mcp.svg b/typescript/site/public/logos/clawpay-mcp.svg new file mode 100644 index 0000000000..96181481b5 --- /dev/null +++ b/typescript/site/public/logos/clawpay-mcp.svg @@ -0,0 +1,6 @@ + + + Claw + Pay + MCP + From c193632e90a54c4815f6aee64ab3b94063658235 Mon Sep 17 00:00:00 2001 From: Dillon <37408368+dillonaux@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:10:38 -0500 Subject: [PATCH 015/129] Add DiamondClaws DeFi Intelligence to ecosystem (#1347) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude --- .../partners-data/diamondclaws/metadata.json | 7 +++++++ typescript/site/public/logos/diamondclaws.png | Bin 0 -> 439 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/diamondclaws/metadata.json create mode 100644 typescript/site/public/logos/diamondclaws.png diff --git a/typescript/site/app/ecosystem/partners-data/diamondclaws/metadata.json b/typescript/site/app/ecosystem/partners-data/diamondclaws/metadata.json new file mode 100644 index 0000000000..45698767d5 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/diamondclaws/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "DiamondClaws DeFi Intelligence", + "description": "DeFi yield scoring, protocol risk analysis, and multi-chain gas oracle for AI agents. 9 paid API endpoints covering 17K+ yield pools, 7K+ protocols, and 7 EVM chains. $0.0005-0.002/request via x402 on Base mainnet.", + "logoUrl": "/logos/diamondclaws.png", + "websiteUrl": "https://diamondclaws.io", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/diamondclaws.png b/typescript/site/public/logos/diamondclaws.png new file mode 100644 index 0000000000000000000000000000000000000000..5e2b1be707354224fdf10083fd0b95e9326ee14b GIT binary patch literal 439 zcmV;o0Z9IdP)!m9)}qOgudrx1rT1VM~LHd0ICtvcmO;l*FF_5QR`0e-=Ol zLQQ-Lz|aV_@udJmBDBQU01SoD8ea=A1Oi2T3jiwuReUP|3j$?41;C{U)bUgRmmu_r zrv&JV&?}xApbJ9o>Mbr~je4Z#T8$tv-VrF{Qv{Qr0lg7Kd<*nMpaKy4V~7Gk^v~f| z0P%l_S^!l1C9VZvkEcSY0T?Ep0-+ROxcF9t5`bajG1K=2Fw=L2Fw^%2G1GU4G1Jcn zU`Gf!05$R09zqJBE*{%Lhym2bV>tvf&k15Ff~hA(u^7SJv%*;JYO|SmEJiRFk0IP- hJZ3uH=kxiv_Xj{_%}j6{Gl&2H002ovPDHLkV1fnUvIGDC literal 0 HcmV?d00001 From 8328999dbf45da09548441dcad2e4743d325cdc0 Mon Sep 17 00:00:00 2001 From: knuckles-stack <243669404+knuckles-stack@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:51:25 -0500 Subject: [PATCH 016/129] feat(ecosystem): add Kevros AI governance gateway (#1399) * feat(ecosystem): add Kevros AI governance gateway * ci: retrigger checks --- .../partners-data/kevros/metadata.json | 7 +++++++ typescript/site/public/logos/kevros.png | Bin 0 -> 10578 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/kevros/metadata.json create mode 100644 typescript/site/public/logos/kevros.png diff --git a/typescript/site/app/ecosystem/partners-data/kevros/metadata.json b/typescript/site/app/ecosystem/partners-data/kevros/metadata.json new file mode 100644 index 0000000000..5c1253dbab --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/kevros/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Kevros", + "description": "AI governance gateway with cryptographic enforcement. Five x402-paid endpoints: action verification ($0.01), provenance attestation ($0.02), intent-command binding ($0.02), outcome verification (free), and compliance evidence bundles ($0.25). Every decision issues a signed release token. Every action is hash-chained. ML-DSA-87 post-quantum signatures for long-term non-repudiation. USDC on Base.", + "logoUrl": "/logos/kevros.png", + "websiteUrl": "https://governance.taskhawktech.com", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/kevros.png b/typescript/site/public/logos/kevros.png new file mode 100644 index 0000000000000000000000000000000000000000..93bfccaa4ce5e9a9f3790474c3ce8a686c440138 GIT binary patch literal 10578 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 literal 0 HcmV?d00001 From 6e2080694785f35951a61d75433ffb12273457e3 Mon Sep 17 00:00:00 2001 From: ACRE <140637602+rhein1@users.noreply.github.com> Date: Tue, 3 Mar 2026 14:55:30 -0500 Subject: [PATCH 017/129] =?UTF-8?q?feat(ecosystem):=20Add=20Agoragentic=20?= =?UTF-8?q?=E2=80=94=20Agent-to-Agent=20Marketplace=20with=20x402=20Gatewa?= =?UTF-8?q?y=20(#1403)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(ecosystem): Add Agoragentic - Agent-to-Agent Marketplace with x402 Gateway * feat(ecosystem): Add Agoragentic logo --------- Co-authored-by: rhein1 --- .../partners-data/agoragentic/metadata.json | 7 +++++++ typescript/site/public/logos/agoragentic.png | Bin 0 -> 288699 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/agoragentic/metadata.json create mode 100644 typescript/site/public/logos/agoragentic.png diff --git a/typescript/site/app/ecosystem/partners-data/agoragentic/metadata.json b/typescript/site/app/ecosystem/partners-data/agoragentic/metadata.json new file mode 100644 index 0000000000..0f4710a078 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/agoragentic/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Agoragentic", + "description": "Agent-to-agent marketplace with x402 pay-per-request gateway. Agents discover, invoke, and pay for API services using USDC on Base β€” no registration required. Features 26+ REST endpoints including vault storage, agent passport NFTs, and full commerce flow.", + "logoUrl": "/logos/agoragentic.png", + "websiteUrl": "https://agoragentic.com/api/x402/info", + "category": "Services/Endpoints" +} \ No newline at end of file diff --git a/typescript/site/public/logos/agoragentic.png b/typescript/site/public/logos/agoragentic.png new file mode 100644 index 0000000000000000000000000000000000000000..af2b496bc23377ba07ee59ea4776f39f1fb23d85 GIT binary patch literal 288699 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 Date: Tue, 3 Mar 2026 14:20:04 -0600 Subject: [PATCH 018/129] feat: add Agent Camo to ecosystem directory (#1420) --- .../partners-data/agent-camo/metadata.json | 7 +++++++ typescript/site/public/logos/agent-camo.png | Bin 0 -> 18946 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/agent-camo/metadata.json create mode 100644 typescript/site/public/logos/agent-camo.png diff --git a/typescript/site/app/ecosystem/partners-data/agent-camo/metadata.json b/typescript/site/app/ecosystem/partners-data/agent-camo/metadata.json new file mode 100644 index 0000000000..5110e567b2 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/agent-camo/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Agent Camo", + "category": "Services/Endpoints", + "logoUrl": "/logos/agent-camo.png", + "description": "Residential proxy sessions with hot-swappable geo-targeting for on-chain agents, paid per-use via x402 micropayments on Base.", + "websiteUrl": "https://agentcamo.xyz" +} diff --git a/typescript/site/public/logos/agent-camo.png b/typescript/site/public/logos/agent-camo.png new file mode 100644 index 0000000000000000000000000000000000000000..b0e734351f9d61aceaa1dcf434b7cf098bb7db6d GIT binary patch literal 18946 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 E0R2qw^8f$< literal 0 HcmV?d00001 From 7b6b3c4856353d02eb63216f2263784394de4f66 Mon Sep 17 00:00:00 2001 From: Erons Date: Tue, 3 Mar 2026 21:54:17 +0000 Subject: [PATCH 019/129] add bloomfilter to list of products (#1426) --- .../partners-data/bloomfilter/metadata.json | 7 +++++++ typescript/site/public/logos/bloomfilter.png | Bin 0 -> 24476 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/bloomfilter/metadata.json create mode 100644 typescript/site/public/logos/bloomfilter.png diff --git a/typescript/site/app/ecosystem/partners-data/bloomfilter/metadata.json b/typescript/site/app/ecosystem/partners-data/bloomfilter/metadata.json new file mode 100644 index 0000000000..1dbed81c5e --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/bloomfilter/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Bloomfilter", + "category": "Services/Endpoints", + "logoUrl": "/logos/bloomfilter.png", + "description": "Register domains and manage DNS with a single API call. No accounts or credit cards required, just x402 payments.", + "websiteUrl": "https://bloomfilter.xyz/docs" +} diff --git a/typescript/site/public/logos/bloomfilter.png b/typescript/site/public/logos/bloomfilter.png new file mode 100644 index 0000000000000000000000000000000000000000..e278a434b2ffc66a3b824071d70b431f1f4b850c GIT binary patch literal 24476 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%0A{ttcTUMwIOj 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 epnV=1ZjRuW+F6u_?FmOZhK?QN~&T literal 0 HcmV?d00001 From 0f2821ba8a047f8868008149f999f5b36e79dd62 Mon Sep 17 00:00:00 2001 From: jonathanbulkeley Date: Tue, 3 Mar 2026 22:56:12 +0100 Subject: [PATCH 020/129] site(ecosystem): add Mycelia Signal to Services/Endpoints (#1389) --- .../partners-data/mycelia-signal/metadata.json | 7 +++++++ typescript/site/public/logos/mycelia-signal.png | Bin 0 -> 17665 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/mycelia-signal/metadata.json create mode 100644 typescript/site/public/logos/mycelia-signal.png diff --git a/typescript/site/app/ecosystem/partners-data/mycelia-signal/metadata.json b/typescript/site/app/ecosystem/partners-data/mycelia-signal/metadata.json new file mode 100644 index 0000000000..6a9088c4ee --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/mycelia-signal/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Mycelia Signal", + "description": "Cryptographically signed price oracle for AI agents and DeFi. 7 real-time price feeds (BTC, ETH, SOL, EUR, XAU, BTC/EUR, VWAP) via x402 micropayments on Base. Ed25519-signed attestations, multi-source median pricing. $0.001/query USDC.", + "logoUrl": "/logos/mycelia-signal.png", + "websiteUrl": "https://myceliasignal.com", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/mycelia-signal.png b/typescript/site/public/logos/mycelia-signal.png new file mode 100644 index 0000000000000000000000000000000000000000..e6586a1e5df2c213f0a58ccd1d3930d532d5f228 GIT binary patch literal 17665 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 Date: Wed, 4 Mar 2026 02:08:38 +0100 Subject: [PATCH 021/129] Add upto payment scheme specification for EVM (#1074) * Add upto payment scheme specification for EVM Introduces the upto scheme which enables usage-based payments where clients authorize a maximum amount and servers settle for the actual amount used. This is ideal for variable-cost resources like LLM token generation, bandwidth metering, or time-based access. Key features: - Uses Permit2 exclusively (permitWitnessTransferFrom) - Client signs for max amount, server settles for actual usage - Settlement amount can be 0 to amount (inclusive) - Adds settledAmount field to SettlementResponse - Reuses existing x402Permit2Proxy contract * Link to existing x402Permit2Proxy contract instead of duplicating * Clarify error codes: standard vs scheme-specific - List standard x402 error codes that apply to upto scheme - Add scheme-specific error codes following naming convention - Add missing error codes for recipient mismatch and time validation * Simplify error codes section and add SettlementResponse link - Link to base SettlementResponse schema in main spec - Reference standard error codes instead of duplicating - Keep only the truly upto-specific error code: settlement_exceeds_amount * docs(upto): add explicit MUST requirements for cross-network properties - Add Core Properties (MUST) section with single-use, time-bound, recipient binding, and max amount enforcement requirements - Add Out of Scope section clarifying what upto does NOT support - Remove invalid use cases: streaming, time-based access, API rate metering - Clarify remaining use cases as single-request patterns Addresses PR feedback from @phdargen and @notorious-d-e-v * docs(upto): rename settledAmount to amount in SettlementResponse Rename for consistency with planned addition of amount field to base SettlementResponse schema in x402-specification-v2.md (per PR feedback) * docs(upto): clarify phase-dependent amount semantics in PaymentRequirements The amount field in PaymentRequirements has different semantics at verify vs settle time for the upto scheme. At verification, it represents the max authorized amount. At settlement, it represents the actual amount to settle. This was ambiguous in the spec and is now explicitly documented across scheme_upto.md, scheme_upto_evm.md, and the main x402 v2 spec. --- specs/schemes/upto/scheme_upto.md | 74 +++++++ specs/schemes/upto/scheme_upto_evm.md | 279 ++++++++++++++++++++++++++ specs/x402-specification-v2.md | 4 +- 3 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 specs/schemes/upto/scheme_upto.md create mode 100644 specs/schemes/upto/scheme_upto_evm.md diff --git a/specs/schemes/upto/scheme_upto.md b/specs/schemes/upto/scheme_upto.md new file mode 100644 index 0000000000..f4890982b7 --- /dev/null +++ b/specs/schemes/upto/scheme_upto.md @@ -0,0 +1,74 @@ +# Scheme: `upto` + +## Summary + +`upto` is a scheme that authorizes a transfer of up to a **maximum amount** of funds from a client to a resource server. The actual amount charged is determined at settlement time based on resource consumption during the request. + +This scheme is ideal for usage-based pricing models where the final cost is not known until after the resource has been consumed. + +## Example Use Cases + +- Paying for LLM token generation (charge per token generated) +- Bandwidth or data transfer metering (charge per byte transferred in a single request) +- Dynamic compute pricing (charge based on actual resources consumed) + +## Core Properties (MUST) + +The `upto` scheme MUST enforce the following properties across ALL network implementations: + +### 1. Single-Use Authorization + +Each authorization MUST be settled at most once. After settlement (regardless of amount), the authorization is consumed and cannot be reused. + +- Rationale: Provides a clear audit trail, simpler mental model, and matches x402's request-response pattern. +- Implementation: On EVM, Permit2's nonce mechanism enforces this. Other networks MUST implement equivalent replay protection. + +### 2. Time-Bound Authorization + +Each authorization MUST have explicit validity time constraints: + +- **Start time** (`validAfter`): Authorization is not valid before this timestamp +- **End time** (`deadline`): Authorization expires after this timestamp + +- Rationale: Limits exposure window for unused authorizations and ensures timely settlement. +- Implementation: On EVM, Permit2's `deadline` and witness `validAfter` enforce this. Other networks MUST implement equivalent time bounds. + +### 3. Recipient Binding + +The authorization MUST cryptographically bind the recipient address. The server/facilitator cannot redirect funds to a different address than what the client signed. + +- Rationale: Prevents malicious facilitators from stealing funds. +- Implementation: On EVM, the Permit2 witness pattern binds `witness.to`. Other networks MUST implement equivalent recipient binding. + +### 4. Maximum Amount Enforcement + +The settled amount MUST be less than or equal to the authorized maximum. + +- The settled `amount` MUST be `<=` the authorized maximum +- The settled `amount` MAY be `0` (no charge if no usage occurred) + +### 5. Phase-Dependent `amount` Semantics in `PaymentRequirements` + +In the x402 protocol, the verify and settle requests share the same `PaymentPayload` and `PaymentRequirements` types. In the `upto` scheme, the `amount` field of `PaymentRequirements` is **phase-dependent** for server-to-facilitator communication: + +- At **verification** time, `amount` represents the **maximum** amount the client authorizes. +- At **settlement** time, `amount` represents the **actual amount to settle**, which MUST be less than or equal to the previously authorized maximum. + +The actual settled amount is communicated by the resource server to the facilitator via the `amount` field in the settlement-time `PaymentRequirements`. This allows the resource server to determine the final charge based on actual resource consumption (e.g., tokens generated, bytes transferred) and communicate it to the facilitator without requiring additional fields or a separate settlement type. + +- Rationale: Reusing the existing `PaymentRequirements` type for both phases keeps the protocol simple and avoids introducing settlement-specific message types. The `amount` field naturally maps to "how much" in both contexts β€” "how much is authorized" at verification time and "how much to charge" at settlement time. +- Implementation: The resource server MUST set the `amount` field in the `PaymentRequirements` passed to the facilitator's settle endpoint to the desired settlement amount. The facilitator MUST verify that this amount does not exceed the authorized maximum from the client's signed authorization. + +## Out of Scope + +The following patterns are NOT supported by `upto` and would require different schemes: + +- **Multi-settlement / streaming**: Settling the same authorization multiple times (e.g., pay-per-chunk streaming) +- **Recurring payments**: Automatic periodic charges without new authorizations +- **Open-ended allowances**: Authorizations without time bounds or single-use constraints + +## Network-Specific Implementation + +Network-specific rules and implementation details are defined in the per-network scheme documents: + +- EVM chains: See [`scheme_upto_evm.md`](./scheme_upto_evm.md) diff --git a/specs/schemes/upto/scheme_upto_evm.md b/specs/schemes/upto/scheme_upto_evm.md new file mode 100644 index 0000000000..7e90c28bda --- /dev/null +++ b/specs/schemes/upto/scheme_upto_evm.md @@ -0,0 +1,279 @@ +# Scheme: `upto` on `EVM` + +## Summary + +The `upto` scheme on EVM enables usage-based payments where the Client (user) authorizes a **maximum amount**, and the Facilitator (server) settles for the **actual amount used** at the end of the request. This is ideal for variable-cost resources like LLM token generation, bandwidth metering, or time-based access. + +This scheme uses the **Permit2** asset transfer method exclusively, leveraging the `permitWitnessTransferFrom` function to allow settling for any amount up to the signed maximum. + +| AssetTransferMethod | Use Case | Notes | +| :------------------ | :-------------------------------------------------------------- | :---------------------------------------------- | +| **Permit2** | All ERC-20 tokens. Client signs max, server settles actual. | Uses existing `x402Permit2Proxy` contract. | + +> **Note**: EIP-3009 (`transferWithAuthorization`) is **not supported** for the `upto` scheme because it requires exact amounts at signature time. + +--- + +## Use Cases + +- **LLM Token Generation**: Client authorizes up to $5, actual charge based on tokens generated +- **Bandwidth/Data Transfer**: Pay per byte transferred in a single request, up to a cap +- **Dynamic Compute**: Authorize max cost, charge based on actual compute resources consumed + +--- + +## 1. AssetTransferMethod: `Permit2` + +This scheme uses the `permitWitnessTransferFrom` from the [canonical **Permit2** contract](#canonical-permit2) combined with the [`x402Permit2Proxy`](#reference-implementation-x402permit2proxy) to enforce receiver address security via the "Witness" pattern. + +The `permit.permitted.amount` represents the **maximum** authorized amount, while the actual settlement amount is determined by the server at settlement time. + +### Phase 1: One-Time Gas Approval + +Permit2 requires the user to approve the [**Permit2 Contract** (Canonical Address)](#canonical-permit2) to spend their tokens. This is a one-time setup. The specification supports three approval methods: + +#### Option A: Direct User Approval (Standard) + +The user submits a standard on-chain `approve(Permit2)` transaction paying their own gas. + +- _Prerequisite:_ User must have Native Gas currency. + +#### Option B: Sponsored ERC20 Approval (Extension: [`erc20ApprovalGasSponsoring`](../../extensions/erc20_gas_sponsoring.md)) + +The Facilitator pays the gas for the approval transaction on the user's behalf. + +- _Prerequisite:_ Server supports this extension. +- _Flow:_ Facilitator batches the following transactions: `from.transfer(gas_amount)` -> `ERC20.approve(Permit2)` -> `settle`. + +#### Option C: EIP2612 Permit (Extension: [`eip2612GasSponsoring`](../../extensions/eip2612_gas_sponsoring.md)) + +If the token supports EIP-2612, the user signs a permit authorizing Permit2. + +- _Prerequisite:_ Token supports EIP-2612. +- _Flow:_ Facilitator calls `x402Permit2Proxy.settleWithPermit()` + +### Phase 2: `PAYMENT-SIGNATURE` Header Payload + +The `payload` field must contain: + +- `signature`: The signature for `permitWitnessTransferFrom`. +- `permit2Authorization`: Parameters to reconstruct the message. + +**Important Logic:** The `permit2Authorization.permitted.amount` represents the **maximum** amount the client is willing to pay. The actual amount charged will be determined at settlement and will be less than or equal to this maximum. + +> **Requirement**: The `x402Permit2Proxy` contract will be deployed to the same address across all supported EVM chains using `CREATE2` to ensure consistent behavior and simpler integration. + +**Example PaymentRequired (402 Response):** + +```json +{ + "x402Version": 2, + "error": "PAYMENT-SIGNATURE header is required", + "resource": { + "url": "https://api.example.com/llm/generate", + "description": "LLM text generation endpoint", + "mimeType": "application/json" + }, + "accepts": [ + { + "scheme": "upto", + "network": "eip155:84532", + "amount": "5000000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2" + } + } + ] +} +``` + +**Example PaymentPayload (Client Request):** + +```json +{ + "x402Version": 2, + "resource": { + "url": "https://api.example.com/llm/generate", + "description": "LLM text generation endpoint", + "mimeType": "application/json" + }, + "accepted": { + "scheme": "upto", + "network": "eip155:84532", + "amount": "5000000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "maxTimeoutSeconds": 300, + "extra": { + "name": "USDC", + "version": "2" + } + }, + "payload": { + "signature": "0x2d6a7588d6acca505cbf0d9a4a227e0c52c6c34008c8e8986a1283259764173608a2ce6496642e377d6da8dbbf5836e9bd15092f9ecab05ded3d6293af148b571c", + "permit2Authorization": { + "permitted": { + "token": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "amount": "5000000" + }, + "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "spender": "0xx402Permit2ProxyAddress", + "nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480", + "deadline": "1740672154", + "witness": { + "to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "validAfter": "1740672089", + "extra": {} + } + } + } +} +``` + +### Phase 3: Verification Logic + +The verifier must execute these checks in order: + +1. **Verify** `payload.signature` is valid and recovers to the `permit2Authorization.from`. + + - Note that `extra` must be converted to its ABI encoded version. + +2. **Verify** that the `client` has enabled the Permit2 approval. + + - if ERC20.allowance(from, Permit2_Address) < amount: + - Check for **Sponsored ERC20 Approval** (Extension): Refers to [`erc20ApprovalGasSponsoring`](../../extensions/erc20_gas_sponsoring.md). + - Check for **EIP2612 Permit** (Extension): Refers to [`eip2612GasSponsoring`](../../extensions/eip2612_gas_sponsoring.md). + - **If neither exists:** Return `412 Precondition Failed` (Error Code: `PERMIT2_ALLOWANCE_REQUIRED`). This signals the client that a one-time Direct Approval transaction is required before retrying. + +3. **Verify** the `client` has sufficient balance of the `asset` to cover `amount`. + +4. **Verify** the `permit2Authorization.permitted.amount` equals the `amount` from requirements. + +5. **Verify** the `deadline` (not expired) and `witness.validAfter` (active). + +6. **Verify** the Token and Network match the requirement. + +7. **Simulation:** + + - _Standard:_ Simulate `x402Permit2Proxy.settle` with the full `amount` (worst case). + - _With "Sponsored ERC20 Approval" (Extension):_ Simulate batch `transfer` -> `approve` -> `settle`. + - _With "EIP2612 Permit" (Extension):_ Simulate `x402Permit2Proxy.settleWithPermit`. + +### Phase 4: Settlement Logic + +Settlement is performed by calling the `x402Permit2Proxy` with the **actual amount** to charge. + +The server determines the actual amount based on resource consumption during the request (tokens generated, bytes transferred, time elapsed, etc.). + +**Settlement Amount Rules:** + +- The settled `amount` MUST be `<=` the authorized maximum +- The settled `amount` MAY be `0` (no charge if no usage occurred) +- The settled `amount` is determined by the resource server, not the client + +**Settlement Process:** + +1. **Standard Settlement:** + Call `x402Permit2Proxy.settle(permit, actualAmount, owner, witness, signature)` where `actualAmount <= permit.permitted.amount`. + +2. **With Sponsored ERC20 Approval (Extension):** + If `erc20ApprovalGasSponsoring` is used, the facilitator must construct a batched transaction that executes the sponsored `ERC20.approve` call strictly before the `x402Permit2Proxy.settle` call. + +3. **With EIP-2612 Permit (Extension):** + If `eip2612GasSponsoring` is used, call `x402Permit2Proxy.settleWithPermit`. + +4. **Zero Settlement:** + If the settled `amount = 0`, no on-chain transaction is required. The authorization simply expires unused. + +**Example SettlementResponse:** + +```json +{ + "success": true, + "transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "network": "eip155:84532", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "amount": "2350000" +} +``` + +--- + +## 2. PaymentRequirements Schema + +The `upto` scheme uses the following `PaymentRequirements` schema: + +| Field Name | Type | Required | Description | +| ------------------- | -------- | -------- | ----------------------------------------------------------------------------- | +| `scheme` | `string` | Required | Must be `"upto"` | +| `network` | `string` | Required | Blockchain network identifier in CAIP-2 format (e.g., "eip155:84532") | +| `amount` | `string` | Required | Phase-dependent: maximum amount at verification, actual amount at settlement | +| `asset` | `string` | Required | Token contract address | +| `payTo` | `string` | Required | Recipient wallet address | +| `maxTimeoutSeconds` | `number` | Required | Maximum time allowed for payment completion | +| `extra` | `object` | Optional | Scheme-specific additional information (must include `name` and `version`) | + +> **Note**: In the `upto` scheme, the `amount` field of `PaymentRequirements` is phase-dependent for server-to-facilitator communication: +> +> - At _verification_ time, `amount` represents the **maximum** amount the client authorizes. +> - At _settlement_ time, `amount` represents the **actual amount to settle**, which MUST be less than or equal to the previously authorized maximum. +> +> The actual settled amount is communicated by the resource server to the facilitator via the `amount` field in the settlement-time payment requirements. This allows the server to determine the final charge based on actual resource consumption without requiring additional fields or a separate settlement type. + +--- + +## 3. SettlementResponse Schema Extension + +The `upto` scheme extends the base [`SettlementResponse`](../../x402-specification-v2.md#53-settlementresponse-schema) with the actual settled amount: + +| Field Name | Type | Required | Description | +| --------------- | --------- | -------- | --------------------------------------------------------------------- | +| `success` | `boolean` | Required | Indicates whether the payment settlement was successful | +| `errorReason` | `string` | Optional | Error reason if settlement failed (omitted if successful) | +| `payer` | `string` | Optional | Address of the payer's wallet | +| `transaction` | `string` | Required | Blockchain transaction hash (empty string if $0 settlement) | +| `network` | `string` | Required | Blockchain network identifier in CAIP-2 format | +| `amount` | `string` | Required | Actual amount charged in atomic token units (may be 0) | + +--- + +## 4. Error Codes + +The `upto` scheme uses the standard x402 error codes defined in the [x402 specification](../../x402-specification-v2.md#9-error-handling). + +### Scheme-Specific Error Code + +The `upto` scheme defines one additional error code: + +- **`invalid_upto_evm_payload_settlement_exceeds_amount`**: Attempted to settle for more than the authorized `amount` + +--- + +## Annex + +### Canonical Permit2 + +The Canonical Permit2 contract address can be found at [https://docs.uniswap.org/contracts/v4/deployments](https://docs.uniswap.org/contracts/v4/deployments). + +### Reference Implementation: `x402Permit2Proxy` + +The `upto` scheme uses the same `x402Permit2Proxy` contract defined in the [exact scheme specification](../exact/scheme_exact_evm.md#reference-implementation-x402permit2proxy). The contract's `settle` function accepts an `amount` parameter that can be less than or equal to `permit.permitted.amount`, which enables the variable settlement amounts required by the `upto` scheme. + +--- + +## Security Considerations + +1. **Maximum Amount Authorization**: Clients should carefully consider the `amount` they authorize. While servers can only charge up to this amount, clients bear the risk of the full amount being charged. + +2. **Server Trust**: The `upto` scheme requires clients to trust that servers will charge fair amounts based on actual usage. Malicious servers could charge up to `amount` regardless of actual usage. + +3. **Signature Reuse Prevention**: The Permit2 nonce mechanism prevents signature reuse. Each authorization can only be settled once. + +4. **Time Constraints**: Authorizations have explicit valid time windows (`deadline`, `validAfter`) to limit their lifetime and reduce exposure. + +5. **Zero Settlement**: Allowing $0 settlements means unused authorizations naturally expire without on-chain transactions, reducing gas costs and blockchain bloat. + diff --git a/specs/x402-specification-v2.md b/specs/x402-specification-v2.md index da55d2b21f..cfdb2f8c5e 100644 --- a/specs/x402-specification-v2.md +++ b/specs/x402-specification-v2.md @@ -407,7 +407,9 @@ Example with actual data: Executes a verified payment by broadcasting the transaction to the blockchain. -**Request:** Same as `/verify` endpoint +**Request:** Same structure as `/verify` endpoint (contains `paymentPayload` and `paymentRequirements`). + +> **Note**: While the request structure is identical, some payment schemes may assign different semantics to fields at settlement time versus verification time. For example, in the `upto` scheme, the `amount` field in `paymentRequirements` represents the maximum authorized amount at verification time, but the actual amount to settle at settlement time. See individual scheme specifications for details. **Successful Response:** From 098ee26690c4e258863bce8b0241302878f2cd44 Mon Sep 17 00:00:00 2001 From: erikreppel-cb Date: Tue, 3 Mar 2026 21:08:46 -0800 Subject: [PATCH 022/129] Update README.md (#1439) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 51ef38a7bc..efcdc0790a 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ go get github.com/coinbase/x402/go - **Open standard:** x402 is an open standard, freely accessible and usable by anyone. It will never force reliance on a single party. - **HTTP / Transport Native:** x402 is meant to seamlessly complement existing data transportation. It should whenever possible not mandate additional requests outside the scope of a typical client / server flow. - **Network, token, and currency agnostic:** we welcome contributions that add support for new networks (both crypto and fiat), signing standards, or schemes, so long as they meet our acceptance criteria laid out in [CONTRIBUTING.md](https://github.com/coinbase/x402/blob/main/CONTRIBUTING.md). x402 may extend support to fiat based networks, but will never deprioritize onchain payments in favor of fiat payments. -- **Backwards Compatible:** x402 will not deprecate support for any existing networks unless such removal is deemed necessary for the security of the standard +- **Backwards Compatible:** x402 will not deprecate support for any existing networks unless such removal is deemed necessary for the security of the standard. Whenever possible, x402 will aim for backwards compatibility for non-major version changes. - **Trust minimizing:** all payment schemes must not allow for the facilitator or resource server to move funds, other than in accordance with client intentions -- **Easy to use:** x402 needs to be 10x better than existing ways to pay on the internet. This means abstracting as many details of crypto as possible away from the client and resource server, and into the facilitator. This means the client/server should not need to think about gas, rpc, etc. +- **Easy to use:** It is the goal of the x402 community to improve ease of use relative to other forms of payment on the Internet. This means abstracting as many details of crypto as possible away from the client and resource server, and into the facilitator. This means the client/server should not need to think about gas, rpc, etc. ## Ecosystem From 013754554ac82b51ccea6ced5a6f59137dd74436 Mon Sep 17 00:00:00 2001 From: Marcelo Salloum dos Santos Date: Wed, 4 Mar 2026 13:56:52 -0800 Subject: [PATCH 023/129] Add Stellar Blockchain Support (#711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add @x402/stellar mechanism package with exact scheme Implement Stellar support for the x402 protocol covering: - Types, constants (network IDs, USDC contracts), and utility functions - Ed25519 signer with client/facilitator variants - Soroban transaction simulation and auth entry handling - Client: builds transfer calls, signs auth entries, serializes XDR - Server: parses prices, enhances payment requirements - Facilitator: verify (structure, amounts, signatures, events) and settle (fee sponsorship, multi-signer round-robin, submission) * Add unit tests for the Stellar mechanism Cover signer, constants, utils, shared helpers, client/server scheme logic, and facilitator verify/settle/getExtra flows. 150 tests across 9 test files. * Add integration tests for Stellar exact scheme End-to-end flows against Stellar testnet covering both the core x402Client/Server/Facilitator and the HTTP middleware variants. Includes resilience to testnet resets via automatic re-funding. * Add Stellar README and cross-reference from evm/svm Document the package API, usage examples, fee sponsorship model, and multi-signer facilitator setup. Link back from evm and svm. * Wire up Stellar in the advanced examples Register Stellar client/server/facilitator schemes alongside EVM and SVM in the all_networks examples. Guarded by env var presence so existing setups keep working without Stellar credentials. * Document Stellar setup in the advanced example READMEs Add STELLAR_PRIVATE_KEY / STELLAR_ADDRESS env vars to .env-local templates and update the example READMEs with Stellar usage notes. * Add Stellar to the e2e test suite Extend the test framework with Stellar network support, add protected-stellar endpoints to express/hono/next servers, register Stellar signers in axios/fetch clients and the TS facilitator. Includes test configs, lockfile, and the Stellar family in the test runner. All 8 serverΓ—client combos pass against testnet. * Update e2e docs with Stellar setup and trustline instructions Add STELLAR env vars to .env-local templates, document the Stellar testnet account setup process (keypair, USDC trustline, faucet), and update all server/client/facilitator READMEs. * Add npm publish workflow for @x402/stellar Manual-dispatch GitHub Actions workflow to publish the Stellar package to npm with provenance, matching the pattern used by the other mechanism packages. * Add CHANGELOG for @x402/stellar v2.5.0 --- .../publish_npm_scoped_x402_stellar.yml | 56 + e2e/.env-local | 3 + e2e/README.md | 17 +- e2e/clients/axios/.env-local | 1 + e2e/clients/axios/README.md | 36 +- e2e/clients/axios/index.ts | 16 +- e2e/clients/axios/package.json | 1 + e2e/clients/axios/test.config.json | 6 +- e2e/clients/fetch/README.md | 19 +- e2e/clients/fetch/index.ts | 13 +- e2e/clients/fetch/package.json | 1 + e2e/clients/fetch/test.config.json | 6 +- e2e/facilitators/typescript/README.md | 24 +- e2e/facilitators/typescript/index.ts | 18 + e2e/facilitators/typescript/package.json | 1 + e2e/facilitators/typescript/test.config.json | 7 +- e2e/pnpm-lock.yaml | 359 +- e2e/servers/express/README.md | 36 +- e2e/servers/express/index.ts | 70 +- e2e/servers/express/package.json | 1 + e2e/servers/express/test.config.json | 11 +- e2e/servers/hono/README.md | 40 +- e2e/servers/hono/index.ts | 69 + e2e/servers/hono/package.json | 1 + e2e/servers/hono/test.config.json | 11 +- e2e/servers/next/.env-local | 8 +- e2e/servers/next/README.md | 20 +- .../app/api/protected-stellar-proxy/route.ts | 16 + .../api/protected-stellar-withx402/route.ts | 55 + e2e/servers/next/package.json | 1 + e2e/servers/next/proxy.ts | 47 +- e2e/servers/next/test.config.json | 18 +- e2e/src/clients/generic-client.ts | 1 + e2e/src/facilitators/facilitator-manager.ts | 1 + e2e/src/facilitators/generic-facilitator.ts | 4 + e2e/src/networks/networks.ts | 18 +- e2e/src/servers/generic-server.ts | 5 + e2e/src/types.ts | 4 +- e2e/test.ts | 23 +- .../typescript/clients/advanced/.env-local | 1 + .../typescript/clients/advanced/README.md | 21 +- .../clients/advanced/all_networks.ts | 18 +- .../typescript/clients/advanced/package.json | 1 + examples/typescript/facilitator/.env-local | 1 + .../typescript/facilitator/advanced/README.md | 15 +- .../facilitator/advanced/all_networks.ts | 21 +- .../facilitator/advanced/package.json | 1 + examples/typescript/pnpm-lock.yaml | 275 +- .../typescript/servers/advanced/.env-local | 2 + .../typescript/servers/advanced/README.md | 21 + .../servers/advanced/all_networks.ts | 23 +- .../typescript/servers/advanced/package.json | 1 + typescript/packages/mechanisms/evm/README.md | 1 + .../mechanisms/stellar/.prettierignore | 7 + .../packages/mechanisms/stellar/.prettierrc | 11 + .../packages/mechanisms/stellar/CHANGELOG.md | 5 + .../packages/mechanisms/stellar/README.md | 168 + .../mechanisms/stellar/eslint.config.js | 131 + .../packages/mechanisms/stellar/package.json | 97 + .../mechanisms/stellar/src/constants.ts | 33 + .../stellar/src/exact/client/index.ts | 1 + .../stellar/src/exact/client/scheme.ts | 151 + .../stellar/src/exact/facilitator/index.ts | 1 + .../stellar/src/exact/facilitator/scheme.ts | 761 ++ .../mechanisms/stellar/src/exact/index.ts | 1 + .../stellar/src/exact/server/index.ts | 1 + .../stellar/src/exact/server/scheme.ts | 150 + .../packages/mechanisms/stellar/src/index.ts | 24 + .../packages/mechanisms/stellar/src/shared.ts | 134 + .../packages/mechanisms/stellar/src/signer.ts | 102 + .../packages/mechanisms/stellar/src/types.ts | 9 + .../packages/mechanisms/stellar/src/utils.ts | 195 + .../test/integrations/exact-stellar.test.ts | 601 ++ .../stellar/test/unit/client.test.ts | 262 + .../stellar/test/unit/constants.test.ts | 98 + .../test/unit/facilitator-getExtra.test.ts | 89 + .../test/unit/facilitator-settle.test.ts | 546 + .../test/unit/facilitator-verify.test.ts | 1037 ++ .../stellar/test/unit/server.test.ts | 156 + .../stellar/test/unit/shared.test.ts | 137 + .../stellar/test/unit/signer.test.ts | 148 + .../stellar/test/unit/utils.test.ts | 397 + .../packages/mechanisms/stellar/tsconfig.json | 9 + .../mechanisms/stellar/tsup.config.ts | 30 + .../mechanisms/stellar/vitest.config.ts | 15 + .../stellar/vitest.integration.config.ts | 13 + typescript/packages/mechanisms/svm/README.md | 2 +- typescript/pnpm-lock.yaml | 9212 ++++++++++------- 88 files changed, 12057 insertions(+), 4123 deletions(-) create mode 100644 .github/workflows/publish_npm_scoped_x402_stellar.yml create mode 100644 e2e/servers/next/app/api/protected-stellar-proxy/route.ts create mode 100644 e2e/servers/next/app/api/protected-stellar-withx402/route.ts create mode 100644 typescript/packages/mechanisms/stellar/.prettierignore create mode 100644 typescript/packages/mechanisms/stellar/.prettierrc create mode 100644 typescript/packages/mechanisms/stellar/CHANGELOG.md create mode 100644 typescript/packages/mechanisms/stellar/README.md create mode 100644 typescript/packages/mechanisms/stellar/eslint.config.js create mode 100644 typescript/packages/mechanisms/stellar/package.json create mode 100644 typescript/packages/mechanisms/stellar/src/constants.ts create mode 100644 typescript/packages/mechanisms/stellar/src/exact/client/index.ts create mode 100644 typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts create mode 100644 typescript/packages/mechanisms/stellar/src/exact/facilitator/index.ts create mode 100644 typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts create mode 100644 typescript/packages/mechanisms/stellar/src/exact/index.ts create mode 100644 typescript/packages/mechanisms/stellar/src/exact/server/index.ts create mode 100644 typescript/packages/mechanisms/stellar/src/exact/server/scheme.ts create mode 100644 typescript/packages/mechanisms/stellar/src/index.ts create mode 100644 typescript/packages/mechanisms/stellar/src/shared.ts create mode 100644 typescript/packages/mechanisms/stellar/src/signer.ts create mode 100644 typescript/packages/mechanisms/stellar/src/types.ts create mode 100644 typescript/packages/mechanisms/stellar/src/utils.ts create mode 100644 typescript/packages/mechanisms/stellar/test/integrations/exact-stellar.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/client.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/constants.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/facilitator-settle.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/facilitator-verify.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/server.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/shared.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/signer.test.ts create mode 100644 typescript/packages/mechanisms/stellar/test/unit/utils.test.ts create mode 100644 typescript/packages/mechanisms/stellar/tsconfig.json create mode 100644 typescript/packages/mechanisms/stellar/tsup.config.ts create mode 100644 typescript/packages/mechanisms/stellar/vitest.config.ts create mode 100644 typescript/packages/mechanisms/stellar/vitest.integration.config.ts diff --git a/.github/workflows/publish_npm_scoped_x402_stellar.yml b/.github/workflows/publish_npm_scoped_x402_stellar.yml new file mode 100644 index 0000000000..92d09e057b --- /dev/null +++ b/.github/workflows/publish_npm_scoped_x402_stellar.yml @@ -0,0 +1,56 @@ +name: Publish @x402/stellar package to NPM + +on: + workflow_dispatch: + +jobs: + publish-npm-x402-stellar: + 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@41ff72655975bd51cab0327fa583b6e92b6d3061 + with: + version: 10.7.0 + + - uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: "https://registry.npmjs.org" + cache: "pnpm" + cache-dependency-path: ./typescript + + - name: Update npm for OIDC trusted publishing + run: npm install -g npm@latest + + - name: Configure npm for trusted publishing + run: npm config delete always-auth 2>/dev/null || true + + - name: Install and build + working-directory: ./typescript + run: | + pnpm install --frozen-lockfile + pnpm -r --filter=@x402/core --filter=@x402/stellar run build + + - name: Publish @x402/stellar package + working-directory: ./typescript/packages/mechanisms/stellar + 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 diff --git a/e2e/.env-local b/e2e/.env-local index d5cfb089e4..77e443bb11 100644 --- a/e2e/.env-local +++ b/e2e/.env-local @@ -1,7 +1,10 @@ # E2E Test Configuration SERVER_EVM_ADDRESS= SERVER_SVM_ADDRESS= +SERVER_STELLAR_ADDRESS= CLIENT_EVM_PRIVATE_KEY= CLIENT_SVM_PRIVATE_KEY= +CLIENT_STELLAR_PRIVATE_KEY= FACILITATOR_EVM_PRIVATE_KEY= FACILITATOR_SVM_PRIVATE_KEY= +FACILITATOR_STELLAR_PRIVATE_KEY= diff --git a/e2e/README.md b/e2e/README.md index 3b0a6fe4d4..c704cbcb0b 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -94,18 +94,33 @@ Required environment variables (set in `.env` file): CLIENT_EVM_PRIVATE_KEY=0x... # EVM private key for client payments CLIENT_SVM_PRIVATE_KEY=... # Solana private key for client payments CLIENT_APTOS_PRIVATE_KEY=... # Aptos private key for client payments (hex string) +CLIENT_STELLAR_PRIVATE_KEY=... # Stellar 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 SERVER_APTOS_ADDRESS=0x... # Where servers receive Aptos payments +SERVER_STELLAR_ADDRESS=... # Where servers receive Stellar 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 FACILITATOR_APTOS_PRIVATE_KEY=... # Aptos private key for facilitator (hex string) +FACILITATOR_STELLAR_PRIVATE_KEY=... # Stellar private key for facilitator ``` +### Account Setup Instructions + +#### Stellar Testnet + +You need **three separate Stellar accounts** for e2e tests (client, server, facilitator): + +1. Go to [Stellar Laboratory](https://lab.stellar.org/account/create) ➑️ Generate keypair ➑️ Fund account with Friendbot, then copy the `Secret` and `Public` keys so you can use them. +2. Add USDC trustline (required for client and server): go to [Fund Account](https://lab.stellar.org/account/fund) ➑️ Paste your `Public Key` ➑️ Add USDC Trustline ➑️ paste your `Secret key` ➑️ Sign transaction ➑️ Add Trustline. +3. Get testnet USDC from [Circle Faucet](https://faucet.circle.com/) (select Stellar network). + +> **Note:** The facilitator account only needs XLM (step 1). Client and server accounts need all three steps. + ## Example Session ```bash @@ -118,7 +133,7 @@ $ pnpm test --min βœ” Select servers β€Ί express, hono, legacy-express βœ” Select clients β€Ί axios, fetch, httpx βœ” Select extensions β€Ί bazaar -βœ” Select protocol families β€Ί EVM, SVM, Aptos +βœ” Select protocol families β€Ί EVM, SVM, Aptos, Stellar πŸ“Š Coverage-Based Minimization Total scenarios: 156 diff --git a/e2e/clients/axios/.env-local b/e2e/clients/axios/.env-local index 73a01182c4..910973a20d 100644 --- a/e2e/clients/axios/.env-local +++ b/e2e/clients/axios/.env-local @@ -3,3 +3,4 @@ ENDPOINT_PATH=/weather EVM_PRIVATE_KEY= SVM_PRIVATE_KEY= APTOS_PRIVATE_KEY= +STELLAR_PRIVATE_KEY= diff --git a/e2e/clients/axios/README.md b/e2e/clients/axios/README.md index 463fb72b1f..8da87a9794 100644 --- a/e2e/clients/axios/README.md +++ b/e2e/clients/axios/README.md @@ -1,13 +1,13 @@ -# E2E Test Client: TypeScript Fetch +# E2E Test Client: TypeScript Axios -This client demonstrates and tests the `@x402/fetch` package with both EVM and SVM payment support. +This client demonstrates and tests the `@x402/axios` package with EVM, SVM, and Stellar 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 +- βœ… **Multi-chain Support** - EVM, SVM, and (optional) Stellar in a single client - βœ… **Automatic Payment Handling** - Transparent 402 response handling - βœ… **Payment Response Decoding** - Extracts settlement information from headers @@ -16,40 +16,44 @@ This client demonstrates and tests the `@x402/fetch` package with both EVM and S - βœ… **EVM V1** - `base-sepolia` and `base` networks - βœ… **SVM V2** - `solana:*` wildcard scheme - βœ… **SVM V1** - `solana-devnet` and `solana` networks +- βœ… **Stellar V2** - `stellar:*` wildcard scheme (optional) ## What It Demonstrates ### Usage Pattern ```typescript -import { wrapFetchWithPayment } from "@x402/fetch"; +import axios from "axios"; +import { wrapAxiosWithPayment } from "@x402/axios"; 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"; +import { ExactStellarClient } from "@x402/stellar"; // Build x402 client with direct registration const client = new x402Client() .register("eip155:*", new ExactEvmClient(evmAccount)) .register("solana:*", new ExactSvmClient(svmSigner)) + .register("stellar:*", new ExactStellarClient(stellarSigner)) .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); +// Wrap axios with payment handling +const axiosWithPayment = wrapAxiosWithPayment(axios.create(), client); // Make request - 402 responses handled automatically -const response = await fetchWithPayment(url, { method: "GET" }); +const response = await axiosWithPayment.get(url); ``` ### Key Concepts Shown 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 +3. **Multi-Chain Support** - EVM, SVM, and (optional) Stellar in one client 4. **Network Flexibility** - Wildcards for V2, specific networks for V1 5. **Transparent Payment** - No manual 402 handling needed @@ -58,8 +62,8 @@ const response = await fetchWithPayment(url, { method: "GET" }); 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) +- **Endpoints:** `/protected` (EVM), `/protected-svm` (SVM), `/protected-stellar` (Stellar) +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM), Stellar Testnet (Stellar) ### Success Criteria - βœ… Request succeeds with 200 status @@ -72,24 +76,29 @@ This client is tested against: ```bash # Via e2e test suite cd e2e -pnpm test --client=fetch +pnpm test --client=axios # Direct execution (requires environment variables) -cd e2e/clients/fetch +cd e2e/clients/axios export RESOURCE_SERVER_URL="http://localhost:4022" export ENDPOINT_PATH="/protected" export EVM_PRIVATE_KEY="0x..." export SVM_PRIVATE_KEY="..." +export STELLAR_PRIVATE_KEY="S..." # optional pnpm start ``` ## Environment Variables +### Required - `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) +### Optional +- `STELLAR_PRIVATE_KEY` - Stellar private key (S... format) - enables Stellar support + ## Output Format ```json @@ -108,11 +117,12 @@ pnpm start ## Package Dependencies -- `@x402/fetch` - HTTP wrapper with payment handling +- `@x402/axios` - Axios 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) +- `@x402/stellar` - Stellar payment mechanisms (V2) - `viem` - Ethereum library for account creation - `@solana/kit` - Solana keypair utilities diff --git a/e2e/clients/axios/index.ts b/e2e/clients/axios/index.ts index cee6f944e5..0b30a8def1 100644 --- a/e2e/clients/axios/index.ts +++ b/e2e/clients/axios/index.ts @@ -11,6 +11,8 @@ import { ExactSvmScheme } from "@x402/svm/exact/client"; import { ExactSvmSchemeV1 } from "@x402/svm/v1"; import { ExactAptosScheme } from "@x402/aptos/exact/client"; import { Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk"; +import { ExactStellarScheme } from "@x402/stellar/exact/client"; +import { createEd25519Signer, type Ed25519Signer } from "@x402/stellar"; import { base58 } from "@scure/base"; import { createKeyPairSignerFromBytes } from "@solana/kit"; import { x402Client } from "@x402/core/client"; @@ -35,11 +37,20 @@ const evmSigner = toClientEvmSigner(evmAccount, publicClient); // Initialize Aptos signer if key is provided let aptosAccount: Account | undefined; if (process.env.APTOS_PRIVATE_KEY) { - const formattedKey = PrivateKey.formatPrivateKey(process.env.APTOS_PRIVATE_KEY, PrivateKeyVariants.Ed25519); + const formattedKey = PrivateKey.formatPrivateKey( + process.env.APTOS_PRIVATE_KEY, + PrivateKeyVariants.Ed25519, + ); const aptosPrivateKey = new Ed25519PrivateKey(formattedKey); aptosAccount = Account.fromPrivateKey({ privateKey: aptosPrivateKey }); } +// Initialize Stellar signer if key is provided +let stellarSigner: Ed25519Signer | undefined; +if (process.env.STELLAR_PRIVATE_KEY) { + stellarSigner = createEd25519Signer(process.env.STELLAR_PRIVATE_KEY); +} + const client = new x402Client() .register("eip155:*", new ExactEvmScheme(evmSigner)) .registerV1("base-sepolia", new ExactEvmSchemeV1(evmSigner)) @@ -50,6 +61,9 @@ const client = new x402Client() if (aptosAccount) { client.register("aptos:*", new ExactAptosScheme(aptosAccount)); } +if (stellarSigner) { + client.register("stellar:*", new ExactStellarScheme(stellarSigner)); +} const axiosWithPayment = wrapAxiosWithPayment(axios.create(), client); diff --git a/e2e/clients/axios/package.json b/e2e/clients/axios/package.json index 32a92fdf10..6c97ae132c 100644 --- a/e2e/clients/axios/package.json +++ b/e2e/clients/axios/package.json @@ -17,6 +17,7 @@ "@x402/axios": "workspace:*", "@x402/core": "workspace:*", "@x402/evm": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/svm": "workspace:*", "axios": "^1.7.9", "dotenv": "^16.4.7", diff --git a/e2e/clients/axios/test.config.json b/e2e/clients/axios/test.config.json index 321b192c54..0ceff02f4d 100644 --- a/e2e/clients/axios/test.config.json +++ b/e2e/clients/axios/test.config.json @@ -5,7 +5,8 @@ "protocolFamilies": [ "evm", "svm", - "aptos" + "aptos", + "stellar" ], "x402Versions": [ 1, @@ -29,7 +30,8 @@ "ENDPOINT_PATH" ], "optional": [ - "APTOS_PRIVATE_KEY" + "APTOS_PRIVATE_KEY", + "STELLAR_PRIVATE_KEY" ] } } \ No newline at end of file diff --git a/e2e/clients/fetch/README.md b/e2e/clients/fetch/README.md index 463fb72b1f..56ba7ef7eb 100644 --- a/e2e/clients/fetch/README.md +++ b/e2e/clients/fetch/README.md @@ -1,13 +1,13 @@ # E2E Test Client: TypeScript Fetch -This client demonstrates and tests the `@x402/fetch` package with both EVM and SVM payment support. +This client demonstrates and tests the `@x402/fetch` package with EVM, SVM, and Stellar 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 +- βœ… **Multi-chain Support** - EVM, SVM, and (optional) Stellar in a single client - βœ… **Automatic Payment Handling** - Transparent 402 response handling - βœ… **Payment Response Decoding** - Extracts settlement information from headers @@ -16,6 +16,7 @@ This client demonstrates and tests the `@x402/fetch` package with both EVM and S - βœ… **EVM V1** - `base-sepolia` and `base` networks - βœ… **SVM V2** - `solana:*` wildcard scheme - βœ… **SVM V1** - `solana-devnet` and `solana` networks +- βœ… **Stellar V2** - `stellar:*` wildcard scheme (optional) ## What It Demonstrates @@ -28,11 +29,13 @@ import { ExactEvmClient } from "@x402/evm"; import { ExactEvmClientV1 } from "@x402/evm/v1"; import { ExactSvmClient } from "@x402/svm"; import { ExactSvmClientV1 } from "@x402/svm/v1"; +import { ExactStellarClient } from "@x402/stellar"; // Build x402 client with direct registration const client = new x402Client() .register("eip155:*", new ExactEvmClient(evmAccount)) .register("solana:*", new ExactSvmClient(svmSigner)) + .register("stellar:*", new ExactStellarClient(stellarSigner)) .registerV1("base-sepolia", new ExactEvmClientV1(evmAccount)) .registerV1("base", new ExactEvmClientV1(evmAccount)) .registerV1("solana-devnet", new ExactSvmClientV1(svmSigner)) @@ -49,7 +52,7 @@ const response = await fetchWithPayment(url, { method: "GET" }); 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 +3. **Multi-Chain Support** - EVM, SVM, and (optional) Stellar in one client 4. **Network Flexibility** - Wildcards for V2, specific networks for V1 5. **Transparent Payment** - No manual 402 handling needed @@ -58,8 +61,8 @@ const response = await fetchWithPayment(url, { method: "GET" }); 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) +- **Endpoints:** `/protected` (EVM), `/protected-svm` (SVM), `/protected-stellar` (Stellar) +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM), Stellar Testnet (Stellar) ### Success Criteria - βœ… Request succeeds with 200 status @@ -80,16 +83,21 @@ export RESOURCE_SERVER_URL="http://localhost:4022" export ENDPOINT_PATH="/protected" export EVM_PRIVATE_KEY="0x..." export SVM_PRIVATE_KEY="..." +export STELLAR_PRIVATE_KEY="S..." # optional pnpm start ``` ## Environment Variables +### Required - `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) +### Optional +- `STELLAR_PRIVATE_KEY` - Stellar private key (S... format) - enables Stellar support + ## Output Format ```json @@ -114,5 +122,6 @@ pnpm start - `@x402/evm/v1` - EVM payment mechanisms (V1) - `@x402/svm` - SVM payment mechanisms (V2) - `@x402/svm/v1` - SVM payment mechanisms (V1) +- `@x402/stellar` - Stellar payment mechanisms (V2) - `viem` - Ethereum library for account creation - `@solana/kit` - Solana keypair utilities diff --git a/e2e/clients/fetch/index.ts b/e2e/clients/fetch/index.ts index 9544bb3f68..57dc68e396 100644 --- a/e2e/clients/fetch/index.ts +++ b/e2e/clients/fetch/index.ts @@ -1,5 +1,5 @@ import { config } from "dotenv"; -import { wrapFetchWithPayment, decodePaymentResponseHeader } from "@x402/fetch"; +import { wrapFetchWithPayment } from "@x402/fetch"; import { createPublicClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { baseSepolia } from "viem/chains"; @@ -10,6 +10,8 @@ import { ExactSvmScheme } from "@x402/svm/exact/client"; import { ExactSvmSchemeV1 } from "@x402/svm/v1"; import { ExactAptosScheme } from "@x402/aptos/exact/client"; import { Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk"; +import { ExactStellarScheme } from "@x402/stellar/exact/client"; +import { createEd25519Signer, Ed25519Signer } from "@x402/stellar"; import { base58 } from "@scure/base"; import { createKeyPairSignerFromBytes } from "@solana/kit"; import { x402Client, x402HTTPClient } from "@x402/core/client"; @@ -37,6 +39,12 @@ if (process.env.APTOS_PRIVATE_KEY) { aptosAccount = Account.fromPrivateKey({ privateKey: aptosPrivateKey }); } +// Initialize Stellar signer if key is provided +let stellarSigner: Ed25519Signer | undefined; +if (process.env.STELLAR_PRIVATE_KEY) { + stellarSigner = createEd25519Signer(process.env.STELLAR_PRIVATE_KEY); +} + const client = new x402Client() .register("eip155:*", new ExactEvmScheme(evmSigner)) .registerV1("base-sepolia", new ExactEvmSchemeV1(evmSigner)) @@ -47,6 +55,9 @@ const client = new x402Client() if (aptosAccount) { client.register("aptos:*", new ExactAptosScheme(aptosAccount)); } +if (stellarSigner) { + client.register("stellar:*", new ExactStellarScheme(stellarSigner)); +} const fetchWithPayment = wrapFetchWithPayment(fetch, client); diff --git a/e2e/clients/fetch/package.json b/e2e/clients/fetch/package.json index 1a051cc038..ae2c29cc60 100644 --- a/e2e/clients/fetch/package.json +++ b/e2e/clients/fetch/package.json @@ -17,6 +17,7 @@ "@x402/core": "workspace:*", "@x402/evm": "workspace:*", "@x402/fetch": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/svm": "workspace:*", "axios": "^1.7.9", "dotenv": "^16.4.7", diff --git a/e2e/clients/fetch/test.config.json b/e2e/clients/fetch/test.config.json index 2c49b460d1..bf946f0b62 100644 --- a/e2e/clients/fetch/test.config.json +++ b/e2e/clients/fetch/test.config.json @@ -5,7 +5,8 @@ "protocolFamilies": [ "evm", "svm", - "aptos" + "aptos", + "stellar" ], "x402Versions": [ 1, @@ -29,7 +30,8 @@ "ENDPOINT_PATH" ], "optional": [ - "APTOS_PRIVATE_KEY" + "APTOS_PRIVATE_KEY", + "STELLAR_PRIVATE_KEY" ] } } diff --git a/e2e/facilitators/typescript/README.md b/e2e/facilitators/typescript/README.md index c7064b9f3c..a87bbcade5 100644 --- a/e2e/facilitators/typescript/README.md +++ b/e2e/facilitators/typescript/README.md @@ -1,6 +1,6 @@ # E2E Test Facilitator: TypeScript -This facilitator demonstrates and tests the TypeScript x402 facilitator implementation with both EVM and SVM payment verification and settlement. +This facilitator demonstrates and tests the TypeScript x402 facilitator implementation with EVM, SVM, and optional Stellar payment verification and settlement. ## What It Tests @@ -9,7 +9,7 @@ This facilitator demonstrates and tests the TypeScript x402 facilitator implemen - βœ… **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 +- βœ… **Multi-chain Support** - EVM, SVM, and (optional) Stellar mechanisms - βœ… **HTTP API** - Express.js server exposing facilitator endpoints ### Facilitator Endpoints @@ -27,6 +27,7 @@ This e2e facilitator showcases **production-ready lifecycle hook patterns**: ```typescript const facilitator = new x402Facilitator() .register("eip155:*", new ExactEvmFacilitator(evmSigner)) + .register("stellar:*", new ExactStellarScheme([stellarSigner])) .registerExtension(BAZAAR) // Hook 1: Track verified payments + extract discovery info .onAfterVerify(async (context) => { @@ -75,6 +76,7 @@ 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"; +import { ExactStellarFacilitator } from "@x402/stellar"; // Create facilitator with bazaar extension const facilitator = new x402Facilitator() @@ -95,6 +97,8 @@ EVM_NETWORKS.forEach(network => { }); // Register SVM schemes similarly... + +// Register Stellar (v2) schemes similarly... ``` ### HTTP Server @@ -118,7 +122,7 @@ app.listen(port, () => { 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:*` +3. **Wildcard Schemes** - Efficient V2 registration with `eip155:*`, `solana:*`, and `stellar:*` 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 @@ -128,12 +132,13 @@ app.listen(port, () => { This facilitator is tested with: - **Clients:** TypeScript Fetch, Go HTTP - **Servers:** Express (TypeScript), Gin (Go) -- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM) -- **Test Cases:** +- **Networks:** Base Sepolia (EVM), Solana Devnet (SVM), Stellar Testnet (Stellar) +- **Test Cases:** - V1 EVM payments - V2 EVM payments - V1 SVM payments - V2 SVM payments + - V2 Stellar payments (optional) ### Success Criteria - βœ… Verification returns valid status @@ -152,16 +157,24 @@ pnpm test --facilitator=typescript cd e2e/facilitators/typescript export EVM_PRIVATE_KEY="0x..." export SVM_PRIVATE_KEY="..." +export STELLAR_PRIVATE_KEY="S..." # optional export PORT=4025 pnpm start ``` ## Environment Variables +### Required - `PORT` - HTTP server port - `EVM_PRIVATE_KEY` - Ethereum private key (hex with 0x prefix) - `SVM_PRIVATE_KEY` - Solana private key (base58 encoded) +### Optional +- `STELLAR_PRIVATE_KEY` - Stellar private key (S... format) - enables Stellar support +- `EVM_NETWORK` - EVM network (default: eip155:84532) +- `SVM_NETWORK` - SVM network (default: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1) +- `STELLAR_NETWORK` - Stellar network (default: stellar:testnet) + ## Package Dependencies - `@x402/core` - Core facilitator @@ -170,6 +183,7 @@ pnpm start - `@x402/evm/v1` - EVM facilitator (V1) + NETWORKS - `@x402/svm` - SVM facilitator (V2) - `@x402/svm/v1` - SVM facilitator (V1) + NETWORKS +- `@x402/stellar` - Stellar facilitator (V2, SEP-41) - `express` - HTTP server - `viem` - Ethereum transactions - `@solana/web3.js` - Solana transactions diff --git a/e2e/facilitators/typescript/index.ts b/e2e/facilitators/typescript/index.ts index a8218f7fe8..464fafdaeb 100644 --- a/e2e/facilitators/typescript/index.ts +++ b/e2e/facilitators/typescript/index.ts @@ -42,6 +42,8 @@ import { toFacilitatorSvmSigner } from "@x402/svm"; import { ExactSvmScheme } from "@x402/svm/exact/facilitator"; import { ExactSvmSchemeV1 } from "@x402/svm/exact/v1/facilitator"; import { NETWORKS as SVM_V1_NETWORKS } from "@x402/svm/v1"; +import { createEd25519Signer, type FacilitatorStellarSigner } from "@x402/stellar"; +import { ExactStellarScheme } from "@x402/stellar/exact/facilitator"; import crypto from "crypto"; import dotenv from "dotenv"; import express from "express"; @@ -58,9 +60,11 @@ const EVM_NETWORK = process.env.EVM_NETWORK || "eip155:84532"; const SVM_NETWORK = process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"; const APTOS_NETWORK = process.env.APTOS_NETWORK || "aptos:2"; +const STELLAR_NETWORK = process.env.STELLAR_NETWORK || "stellar:testnet"; const EVM_RPC_URL = process.env.EVM_RPC_URL; const SVM_RPC_URL = process.env.SVM_RPC_URL; const APTOS_RPC_URL = process.env.APTOS_RPC_URL; +const STELLAR_RPC_URL = process.env.STELLAR_RPC_URL; // Map CAIP-2 network IDs to viem chains function getEvmChain(network: string): Chain { @@ -76,9 +80,11 @@ function getEvmChain(network: string): Chain { console.log(`🌐 EVM Network: ${EVM_NETWORK}`); console.log(`🌐 SVM Network: ${SVM_NETWORK}`); console.log(`🌐 Aptos Network: ${APTOS_NETWORK}`); +console.log(`🌐 Stellar Network: ${STELLAR_NETWORK}`); if (EVM_RPC_URL) console.log(`🌐 EVM RPC URL: ${EVM_RPC_URL}`); if (SVM_RPC_URL) console.log(`🌐 SVM RPC URL: ${SVM_RPC_URL}`); if (APTOS_RPC_URL) console.log(`🌐 Aptos RPC URL: ${APTOS_RPC_URL}`); +if (STELLAR_RPC_URL) console.log(`🌐 Stellar RPC URL: ${STELLAR_RPC_URL}`); // Validate required environment variables if (!process.env.EVM_PRIVATE_KEY) { @@ -117,6 +123,13 @@ if (process.env.APTOS_PRIVATE_KEY) { ); } +// Initialize the Stellar signer from private key (optional) +let stellarSigner: FacilitatorStellarSigner | undefined; +if (process.env.STELLAR_PRIVATE_KEY) { + stellarSigner = createEd25519Signer(process.env.STELLAR_PRIVATE_KEY as string, STELLAR_NETWORK as Network); + console.info(`Stellar Facilitator account: ${stellarSigner.address}`); +} + // Create a Viem client with both wallet and public capabilities const evmChain = getEvmChain(EVM_NETWORK); const viemClient = createWalletClient({ @@ -204,6 +217,9 @@ if (aptosSigner) { new ExactAptosScheme(aptosSigner), ); } +if (stellarSigner) { + facilitator.register(STELLAR_NETWORK as Network, new ExactStellarScheme([stellarSigner])); +} facilitator .registerExtension(BAZAAR) @@ -403,6 +419,7 @@ app.get("/health", (req, res) => { evmNetwork: EVM_NETWORK, svmNetwork: SVM_NETWORK, aptosNetwork: aptosAccount ? APTOS_NETWORK : "(not configured)", + stellarNetwork: stellarSigner ? STELLAR_NETWORK : "(not configured)", facilitator: "typescript", version: "2.0.0", extensions: [BAZAAR.key], @@ -436,6 +453,7 @@ app.listen(parseInt(PORT), () => { β•‘ Aptos Network: ${APTOS_NETWORK} β•‘ β•‘ EVM Address: ${evmAccount.address} β•‘ β•‘ Aptos Address: ${aptosAccount ? aptosAccount.accountAddress.toStringLong().slice(0, 20) + "..." : "(not configured)"} +β•‘ Stellar Address: ${stellarSigner ? stellarSigner.address : "(not configured)"} β•‘ β•‘ Extensions: bazaar β•‘ β•‘ β•‘ β•‘ Endpoints: β•‘ diff --git a/e2e/facilitators/typescript/package.json b/e2e/facilitators/typescript/package.json index 6ce5e4d256..b3e6922b0a 100644 --- a/e2e/facilitators/typescript/package.json +++ b/e2e/facilitators/typescript/package.json @@ -19,6 +19,7 @@ "@x402/core": "workspace:*", "@x402/evm": "workspace:*", "@x402/extensions": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/svm": "workspace:*", "dotenv": "^16.4.5", "express": "^4.19.2", diff --git a/e2e/facilitators/typescript/test.config.json b/e2e/facilitators/typescript/test.config.json index 31f0a5d5ee..7cc0fddb87 100644 --- a/e2e/facilitators/typescript/test.config.json +++ b/e2e/facilitators/typescript/test.config.json @@ -5,7 +5,8 @@ "protocolFamilies": [ "evm", "svm", - "aptos" + "aptos", + "stellar" ], "x402Versions": [ 1, @@ -27,9 +28,11 @@ ], "optional": [ "APTOS_PRIVATE_KEY", + "STELLAR_PRIVATE_KEY", "EVM_NETWORK", "SVM_NETWORK", - "APTOS_NETWORK" + "APTOS_NETWORK", + "STELLAR_NETWORK" ] } } diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index 6e0ce33d8f..efd36bd42e 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -222,12 +222,6 @@ importers: ../typescript/packages/http/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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/kit': - specifier: ^6.1.0 - version: 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) '@x402/core': specifier: workspace:~ version: link:../../core @@ -420,9 +414,6 @@ importers: ../typescript/packages/http/next: 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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@x402/core': specifier: workspace:~ version: link:../../core @@ -504,7 +495,7 @@ importers: version: 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + 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 @@ -795,10 +786,10 @@ importers: 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.19.0(bufferutil@4.0.9)(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@7.5.10(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) express: specifier: ^4.18.2 version: 4.21.2 @@ -1236,6 +1227,61 @@ importers: 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/stellar: + dependencies: + '@stellar/stellar-sdk': + specifier: ^14.4.2 + version: 14.5.0 + '@x402/core': + specifier: workspace:* + version: link:../../core + 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.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': + specifier: ^8.29.1 + version: 8.48.0(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.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-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: '@solana-program/compute-budget': @@ -1326,6 +1372,9 @@ importers: '@x402/evm': specifier: workspace:* version: link:../../../typescript/packages/mechanisms/evm + '@x402/stellar': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../typescript/packages/mechanisms/svm @@ -1393,6 +1442,9 @@ importers: '@x402/fetch': specifier: workspace:* version: link:../../../typescript/packages/http/fetch + '@x402/stellar': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../typescript/packages/mechanisms/svm @@ -1509,6 +1561,9 @@ importers: '@x402/extensions': specifier: workspace:* version: link:../../../typescript/packages/extensions + '@x402/stellar': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../typescript/packages/mechanisms/svm @@ -1827,6 +1882,9 @@ importers: '@x402/extensions': specifier: workspace:* version: link:../../../typescript/packages/extensions + '@x402/stellar': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../typescript/packages/mechanisms/svm @@ -1894,6 +1952,9 @@ importers: '@x402/hono': specifier: workspace:* version: link:../../../typescript/packages/http/hono + '@x402/stellar': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../typescript/packages/mechanisms/svm @@ -2019,6 +2080,9 @@ importers: '@x402/next': specifier: workspace:* version: link:../../../typescript/packages/http/next + '@x402/stellar': + specifier: workspace:* + version: link:../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../typescript/packages/mechanisms/svm @@ -5085,6 +5149,18 @@ packages: '@stablelib/wipe@1.0.1': resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + '@stellar/js-xdr@3.1.2': + resolution: {integrity: sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==} + + '@stellar/stellar-base@14.0.4': + resolution: {integrity: sha512-UbNW6zbdOBXJwLAV2mMak0bIC9nw3IZVlQXkv2w2dk1jgCbJjy3oRVC943zeGE5JAm0Z9PHxrIjmkpGhayY7kw==} + engines: {node: '>=20.0.0'} + + '@stellar/stellar-sdk@14.5.0': + resolution: {integrity: sha512-Uzjq+An/hUA+Q5ERAYPtT0+MMiwWnYYWMwozmZMjxjdL2MmSjucBDF8Q04db6K/ekU4B5cHuOfsdlrfaxQYblw==} + engines: {node: '>=20.0.0'} + hasBin: true + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -5878,6 +5954,9 @@ packages: axios@1.12.2: resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} + axios@1.13.4: + resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -5906,6 +5985,10 @@ packages: base-x@5.0.1: resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} + base32.js@0.1.0: + resolution: {integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==} + engines: {node: '>=0.12.0'} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -5916,6 +5999,9 @@ packages: big.js@6.2.2: resolution: {integrity: sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==} + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -6771,6 +6857,10 @@ packages: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} engines: {node: '>=18.0.0'} + eventsource@2.0.2: + resolution: {integrity: sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==} + engines: {node: '>=12.0.0'} + eventsource@3.0.7: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} @@ -6856,6 +6946,9 @@ packages: picomatch: optional: true + feaxios@0.0.23: + resolution: {integrity: sha512-eghR0A21fvbkcQBgZuMfQhrXxJzC0GNUGC9fXhBge33D+mFDTwl0aJ35zoQQn575BhyjQitRc5N4f+L4cP708g==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -7270,6 +7363,10 @@ packages: resolution: {integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==} engines: {node: '>=10'} + is-retry-allowed@3.0.0: + resolution: {integrity: sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==} + engines: {node: '>=12'} + is-set@2.0.3: resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} @@ -8741,6 +8838,9 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -8993,6 +9093,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + urijs@1.19.11: + resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} + use-sync-external-store@1.2.0: resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: @@ -10254,6 +10357,29 @@ snapshots: - 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-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.12.2 + axios-retry: 4.5.0(axios@1.12.2) + jose: 6.1.3 + md5: 2.3.0 + uncrypto: 0.1.3 + viem: 2.45.1(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.19.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) @@ -11867,6 +11993,10 @@ snapshots: dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(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)))': + 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.19.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -11890,6 +12020,10 @@ snapshots: dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(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.19.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -12422,6 +12556,32 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -12448,6 +12608,32 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/kit@5.0.0(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': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 5.0.0(typescript@5.8.3) + '@solana/functional': 5.0.0(typescript@5.8.3) + '@solana/instruction-plans': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/instructions': 5.0.0(typescript@5.8.3) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@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@7.5.10(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@7.5.10(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 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -12945,14 +13131,23 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.8.3)(ws@8.19.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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.18.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: @@ -12963,6 +13158,15 @@ snapshots: typescript: 5.8.3 ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@solana/rpc-subscriptions-channel-websocket@5.0.0(typescript@5.8.3)(ws@7.5.10(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: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@solana/rpc-subscriptions-channel-websocket@5.0.0(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -13038,7 +13242,7 @@ snapshots: optionalDependencies: typescript: 5.8.3 - '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.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) @@ -13046,7 +13250,7 @@ snapshots: '@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.19.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)) '@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) @@ -13056,6 +13260,24 @@ snapshots: - 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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 3.0.3(typescript@5.8.3) @@ -13074,6 +13296,24 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/rpc-subscriptions@5.0.0(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': 5.0.0(typescript@5.8.3) + '@solana/fast-stable-stringify': 5.0.0(typescript@5.8.3) + '@solana/functional': 5.0.0(typescript@5.8.3) + '@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@7.5.10(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) + '@solana/subscribable': 5.0.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -13491,7 +13731,7 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.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) @@ -13499,7 +13739,7 @@ snapshots: '@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.19.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)) '@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) @@ -13508,6 +13748,23 @@ snapshots: - 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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -13525,6 +13782,23 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/transaction-confirmation@5.0.0(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': 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) + '@solana/errors': 5.0.0(typescript@5.8.3) + '@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@7.5.10(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) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/transaction-confirmation@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -13794,6 +14068,31 @@ snapshots: '@stablelib/wipe@1.0.1': {} + '@stellar/js-xdr@3.1.2': {} + + '@stellar/stellar-base@14.0.4': + dependencies: + '@noble/curves': 1.9.7 + '@stellar/js-xdr': 3.1.2 + base32.js: 0.1.0 + bignumber.js: 9.3.1 + buffer: 6.0.3 + sha.js: 2.4.12 + + '@stellar/stellar-sdk@14.5.0': + dependencies: + '@stellar/stellar-base': 14.0.4 + axios: 1.13.4 + bignumber.js: 9.3.1 + commander: 14.0.2 + eventsource: 2.0.2 + feaxios: 0.0.23 + randombytes: 2.1.0 + toml: 3.0.0 + urijs: 1.19.11 + transitivePeerDependencies: + - debug + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.4)': dependencies: '@babel/core': 7.28.4 @@ -15426,6 +15725,14 @@ snapshots: transitivePeerDependencies: - debug + axios@1.13.4: + 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.4): @@ -15460,12 +15767,16 @@ snapshots: base-x@5.0.1: {} + base32.js@0.1.0: {} + base64-js@1.5.1: {} baseline-browser-mapping@2.8.19: {} big.js@6.2.2: {} + bignumber.js@9.3.1: {} + binary-extensions@2.3.0: {} bn.js@4.12.2: {} @@ -16623,6 +16934,8 @@ snapshots: eventsource-parser@3.0.6: {} + eventsource@2.0.2: {} + eventsource@3.0.7: dependencies: eventsource-parser: 3.0.6 @@ -16768,6 +17081,10 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + feaxios@0.0.23: + dependencies: + is-retry-allowed: 3.0.0 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -17232,6 +17549,8 @@ snapshots: is-retry-allowed@2.2.0: {} + is-retry-allowed@3.0.0: {} + is-set@2.0.3: {} is-shared-array-buffer@1.0.4: @@ -18958,6 +19277,8 @@ snapshots: toidentifier@1.0.1: {} + toml@3.0.0: {} + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -19201,6 +19522,8 @@ snapshots: dependencies: punycode: 2.3.1 + urijs@1.19.11: {} + use-sync-external-store@1.2.0(react@19.2.0): dependencies: react: 19.2.0 diff --git a/e2e/servers/express/README.md b/e2e/servers/express/README.md index c28f19f801..0e0d0aaf44 100644 --- a/e2e/servers/express/README.md +++ b/e2e/servers/express/README.md @@ -1,13 +1,13 @@ # E2E Test Server: Express (TypeScript) -This server demonstrates and tests the x402 Express.js middleware with both EVM and SVM payment protection. +This server demonstrates and tests the x402 Express.js middleware with EVM, SVM, and optional Stellar 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 +- βœ… **Multi-chain Support** - EVM, SVM, and (optional) Stellar payment acceptance - βœ… **Facilitator Integration** - HTTP communication with facilitator - βœ… **Extension Support** - Bazaar discovery metadata - βœ… **Settlement Handling** - Payment verification and confirmation @@ -15,6 +15,7 @@ This server demonstrates and tests the x402 Express.js middleware with both EVM ### Protected Endpoints - βœ… `GET /protected` - Requires EVM payment (USDC on Base Sepolia) - βœ… `GET /protected-svm` - Requires SVM payment (USDC on Solana Devnet) +- βœ… `GET /protected-stellar` - Requires Stellar payment (USDC on Stellar Testnet) ## What It Demonstrates @@ -24,7 +25,8 @@ This server demonstrates and tests the x402 Express.js middleware with both EVM import express from "express"; import { x402Middleware } from "@x402/server/express"; import { ExactEvmServer } from "@x402/evm"; -import { ExactEvmServer } from "@x402/svm"; +import { ExactSvmServer } from "@x402/svm"; +import { ExactStellarServer } from "@x402/stellar"; const app = express(); @@ -47,16 +49,26 @@ const routes = { extensions: { bazaar: discoveryMetadata } + }, + "GET /protected-stellar": { + scheme: "exact", + network: "stellar:testnet", + payTo: "YourStellarAddress", + price: "$0.001", + extensions: { + bazaar: discoveryMetadata + } } }; -// Apply x402 middleware with EVM and SVM servers +// Apply x402 middleware with EVM, SVM, and Stellar servers app.use(x402Middleware({ routes, facilitatorUrl: "http://localhost:4023", servers: { "eip155:84532": new ExactEvmServer(), - "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": new ExactSvmServer() + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": new ExactSvmServer(), + "stellar:testnet": new ExactStellarServer() } })); @@ -68,6 +80,10 @@ app.get("/protected", (req, res) => { app.get("/protected-svm", (req, res) => { res.json({ message: "SVM payment successful!" }); }); + +app.get("/protected-stellar", (req, res) => { + res.json({ message: "Stellar payment successful!" }); +}); ``` ### Key Concepts Shown @@ -84,7 +100,7 @@ app.get("/protected-svm", (req, res) => { This server is tested with: - **Clients:** TypeScript Fetch, Go HTTP - **Facilitators:** TypeScript, Go -- **Payment Types:** EVM (Base Sepolia), SVM (Solana Devnet) +- **Payment Types:** EVM (Base Sepolia), SVM (Solana Devnet), Stellar (Stellar Testnet) - **Protocols:** V2 (primary), V1 (via client negotiation) ### Request Flow @@ -107,18 +123,24 @@ cd e2e/servers/express export FACILITATOR_URL="http://localhost:4023" export EVM_PAYEE_ADDRESS="0x..." export SVM_PAYEE_ADDRESS="..." +export STELLAR_PAYEE_ADDRESS="G..." # optional export PORT=4022 pnpm start ``` ## Environment Variables +### Required - `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 + +### Optional +- `STELLAR_PAYEE_ADDRESS` - Stellar address to receive payments - enables Stellar endpoint - `EVM_NETWORK` - EVM network (default: eip155:84532) - `SVM_NETWORK` - SVM network (default: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1) +- `STELLAR_NETWORK` - Stellar network (default: stellar:testnet) ## Response Examples @@ -151,6 +173,7 @@ PAYMENT-RESPONSE: - `@x402/server` - Express middleware - `@x402/evm` - EVM server - `@x402/svm` - SVM server +- `@x402/stellar` - Stellar server - `@x402/extensions/bazaar` - Discovery extension - `express` - HTTP server framework @@ -166,5 +189,6 @@ PAYMENT-RESPONSE: ### Service Integration - **EVM Server** - Handles Base Sepolia USDC payments - **SVM Server** - Handles Solana Devnet USDC payments +- **Stellar Server** - Handles Stellar Testnet USDC contract payments (SEP-41) - **Price Conversion** - "$0.001" β†’ token amounts with decimals - **Asset Resolution** - Automatic USDC contract/mint lookup diff --git a/e2e/servers/express/index.ts b/e2e/servers/express/index.ts index 364a1ca7dd..013a168a6c 100644 --- a/e2e/servers/express/index.ts +++ b/e2e/servers/express/index.ts @@ -4,6 +4,7 @@ import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { ExactSvmScheme } from "@x402/svm/exact/server"; import { ExactAptosScheme } from "@x402/aptos/exact/server"; +import { ExactStellarScheme } from "@x402/stellar/exact/server"; import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; import { declareEip2612GasSponsoringExtension, @@ -24,9 +25,11 @@ const PORT = process.env.PORT || "4021"; const EVM_NETWORK = (process.env.EVM_NETWORK || "eip155:84532") as `${string}:${string}`; const SVM_NETWORK = (process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; +const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") 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 APTOS_PAYEE_ADDRESS = process.env.APTOS_PAYEE_ADDRESS as string; +const STELLAR_PAYEE_ADDRESS = process.env.STELLAR_PAYEE_ADDRESS as string | undefined; const facilitatorUrl = process.env.FACILITATOR_URL; if (!EVM_PAYEE_ADDRESS) { @@ -60,6 +63,9 @@ server.register("solana:*", new ExactSvmScheme()); if (APTOS_PAYEE_ADDRESS) { server.register("aptos:*", new ExactAptosScheme()); } +if (STELLAR_PAYEE_ADDRESS) { + server.register("stellar:*", new ExactStellarScheme()); +} // Register Bazaar discovery extension server.registerExtension(bazaarResourceServerExtension); @@ -81,11 +87,25 @@ app.get("/protected-aptos", (req, res, next) => { next(); }); +/** + * Pre-middleware guard for optional Stellar endpoint + * Returns 501 Not Implemented if Stellar is not configured + */ +app.use("/protected-stellar", (req, res, next) => { + if (!STELLAR_PAYEE_ADDRESS) { + return res.status(501).json({ + error: "Stellar payments not configured", + message: "STELLAR_PAYEE_ADDRESS environment variable is not set", + }); + } + next(); +}); + /** * Configure x402 payment middleware using builder pattern * * This middleware protects endpoints with $0.001 USDC payment requirements - * on Base Sepolia, Solana Devnet, and Aptos Testnet with bazaar discovery extension. + * on Base Sepolia, Solana Devnet, Aptos Testnet, and Stellar Testnet with bazaar discovery extension. */ app.use( paymentMiddleware( @@ -227,6 +247,35 @@ app.use( ...declareEip2612GasSponsoringExtension(), }, }, + ...(STELLAR_PAYEE_ADDRESS + ? { + "GET /protected-stellar": { + accepts: { + payTo: STELLAR_PAYEE_ADDRESS!, + scheme: "exact", + price: "$0.001", + network: STELLAR_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected Stellar 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 ), @@ -301,6 +350,22 @@ app.get("/protected-permit2", (req, res) => { }); }); +/** + * Protected Stellar endpoint - requires payment to access + * + * This endpoint demonstrates a resource protected by x402 payment middleware for Stellar. + * Clients must provide a valid payment signature to access this endpoint. + * Note: 501 check is handled by pre-middleware guard above. + */ +if (STELLAR_PAYEE_ADDRESS) { + app.get("/protected-stellar", (req, res) => { + res.json({ + message: "Protected Stellar endpoint accessed successfully", + timestamp: new Date().toISOString(), + }); + }); +} + /** * Health check endpoint - no payment required * @@ -340,9 +405,11 @@ app.listen(parseInt(PORT), () => { β•‘ EVM Network: ${EVM_NETWORK} β•‘ β•‘ SVM Network: ${SVM_NETWORK} β•‘ β•‘ Aptos Network: ${APTOS_NETWORK} β•‘ +β•‘ Stellar Network: ${STELLAR_NETWORK}β•‘ β•‘ EVM Payee: ${EVM_PAYEE_ADDRESS} β•‘ β•‘ SVM Payee: ${SVM_PAYEE_ADDRESS} β•‘ β•‘ Aptos Payee: ${APTOS_PAYEE_ADDRESS || "(not configured)"} +β•‘ Stellar Payee: ${STELLAR_PAYEE_ADDRESS || "(not configured)"} β•‘ β•‘ β•‘ Endpoints: β•‘ β•‘ β€’ GET /protected (EIP-3009 payment - EVM) β•‘ @@ -350,6 +417,7 @@ app.listen(parseInt(PORT), () => { β•‘ β€’ GET /protected-aptos (Aptos payment) β•‘ β•‘ β€’ GET /protected-permit2 (Permit2 payment - EVM) β•‘ β•‘ β€’ GET /protected-permit2-erc20 (Permit2 + ERC-20 approval) β•‘ +β•‘ β€’ GET /protected-stellar (Stellar payment) β•‘ β•‘ β€’ GET /health (no payment required) β•‘ β•‘ β€’ POST /close (shutdown server) β•‘ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• diff --git a/e2e/servers/express/package.json b/e2e/servers/express/package.json index eee39400e0..8150f1dd95 100644 --- a/e2e/servers/express/package.json +++ b/e2e/servers/express/package.json @@ -15,6 +15,7 @@ "@x402/express": "workspace:*", "@x402/evm": "workspace:*", "@x402/extensions": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/svm": "workspace:*", "dotenv": "^16.6.1", "express": "^4.18.2" diff --git a/e2e/servers/express/test.config.json b/e2e/servers/express/test.config.json index 52deba0120..d10b4b9f12 100644 --- a/e2e/servers/express/test.config.json +++ b/e2e/servers/express/test.config.json @@ -48,6 +48,13 @@ "requiresPayment": true, "protocolFamily": "aptos" }, + { + "path": "/protected-stellar", + "method": "GET", + "description": "Protected endpoint requiring payment on Stellar network", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/health", "method": "GET", @@ -69,7 +76,9 @@ "FACILITATOR_URL" ], "optional": [ - "APTOS_PAYEE_ADDRESS" + "APTOS_PAYEE_ADDRESS", + "STELLAR_PAYEE_ADDRESS", + "STELLAR_NETWORK" ] } } diff --git a/e2e/servers/hono/README.md b/e2e/servers/hono/README.md index 708dd989df..2f0483f54b 100644 --- a/e2e/servers/hono/README.md +++ b/e2e/servers/hono/README.md @@ -1,13 +1,13 @@ -# E2E Test Server: Express (TypeScript) +# E2E Test Server: Hono (TypeScript) -This server demonstrates and tests the x402 Express.js middleware with both EVM and SVM payment protection. +This server demonstrates and tests the x402 Hono middleware with EVM, SVM, and optional Stellar 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 +- βœ… **Multi-chain Support** - EVM, SVM, and optional Stellar payment acceptance - βœ… **Facilitator Integration** - HTTP communication with facilitator - βœ… **Extension Support** - Bazaar discovery metadata - βœ… **Settlement Handling** - Payment verification and confirmation @@ -15,6 +15,7 @@ This server demonstrates and tests the x402 Express.js middleware with both EVM ### Protected Endpoints - βœ… `GET /protected` - Requires EVM payment (USDC on Base Sepolia) - βœ… `GET /protected-svm` - Requires SVM payment (USDC on Solana Devnet) +- βœ… `GET /protected-stellar` - Requires Stellar payment (USDC on Stellar Testnet, optional) ## What It Demonstrates @@ -25,6 +26,7 @@ import express from "express"; import { x402Middleware } from "@x402/server/express"; import { ExactEvmServer } from "@x402/evm"; import { ExactEvmServer } from "@x402/svm"; +import { ExactStellarServer } from "@x402/stellar"; const app = express(); @@ -47,6 +49,15 @@ const routes = { extensions: { bazaar: discoveryMetadata } + }, + "GET /protected-stellar": { + scheme: "exact", + network: "stellar:testnet", + payTo: "YourStellarAddress", + price: "$0.001", + extensions: { + bazaar: discoveryMetadata + } } }; @@ -56,7 +67,8 @@ app.use(x402Middleware({ facilitatorUrl: "http://localhost:4023", servers: { "eip155:84532": new ExactEvmServer(), - "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": new ExactSvmServer() + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": new ExactSvmServer(), + "stellar:testnet": new ExactStellarServer() } })); @@ -68,6 +80,10 @@ app.get("/protected", (req, res) => { app.get("/protected-svm", (req, res) => { res.json({ message: "SVM payment successful!" }); }); + +app.get("/protected-stellar", (req, res) => { + res.json({ message: "Stellar payment successful!" }); +}); ``` ### Key Concepts Shown @@ -84,7 +100,7 @@ app.get("/protected-svm", (req, res) => { This server is tested with: - **Clients:** TypeScript Fetch, Go HTTP - **Facilitators:** TypeScript, Go -- **Payment Types:** EVM (Base Sepolia), SVM (Solana Devnet) +- **Payment Types:** EVM (Base Sepolia), SVM (Solana Devnet), Stellar (Stellar Testnet) - **Protocols:** V2 (primary), V1 (via client negotiation) ### Request Flow @@ -100,25 +116,31 @@ This server is tested with: ```bash # Via e2e test suite cd e2e -pnpm test --server=express +pnpm test --server=hono # Direct execution -cd e2e/servers/express +cd e2e/servers/hono export FACILITATOR_URL="http://localhost:4023" export EVM_PAYEE_ADDRESS="0x..." export SVM_PAYEE_ADDRESS="..." +export STELLAR_PAYEE_ADDRESS="G..." # optional export PORT=4022 pnpm start ``` ## Environment Variables +### Required - `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 + +### Optional +- `STELLAR_PAYEE_ADDRESS` - Stellar address to receive payments - enables Stellar endpoint - `EVM_NETWORK` - EVM network (default: eip155:84532) - `SVM_NETWORK` - SVM network (default: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1) +- `STELLAR_NETWORK` - Stellar network (default: stellar:testnet) ## Response Examples @@ -151,8 +173,9 @@ PAYMENT-RESPONSE: - `@x402/server` - Express middleware - `@x402/evm` - EVM service - `@x402/svm` - SVM service +- `@x402/stellar` - Stellar server (optional) - `@x402/extensions/bazaar` - Discovery extension -- `express` - HTTP server framework +- `hono` - HTTP server framework ## Implementation Highlights @@ -166,5 +189,6 @@ PAYMENT-RESPONSE: ### Service Integration - **EVM Service** - Handles Base Sepolia USDC payments - **SVM Service** - Handles Solana Devnet USDC payments +- **Stellar Service** - Handles Stellar Testnet USDC contract payments - **Price Conversion** - "$0.001" β†’ token amounts with decimals - **Asset Resolution** - Automatic USDC contract/mint lookup diff --git a/e2e/servers/hono/index.ts b/e2e/servers/hono/index.ts index 0eb94b4744..1392834b22 100644 --- a/e2e/servers/hono/index.ts +++ b/e2e/servers/hono/index.ts @@ -5,6 +5,7 @@ import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { ExactSvmScheme } from "@x402/svm/exact/server"; import { ExactAptosScheme } from "@x402/aptos/exact/server"; +import { ExactStellarScheme } from "@x402/stellar/exact/server"; import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; import { declareEip2612GasSponsoringExtension, @@ -25,9 +26,11 @@ const PORT = process.env.PORT || "4023"; const EVM_NETWORK = (process.env.EVM_NETWORK || "eip155:84532") as `${string}:${string}`; const SVM_NETWORK = (process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; +const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") 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 APTOS_PAYEE_ADDRESS = process.env.APTOS_PAYEE_ADDRESS as string; +const STELLAR_PAYEE_ADDRESS = process.env.STELLAR_PAYEE_ADDRESS as string | undefined; const facilitatorUrl = process.env.FACILITATOR_URL; if (!EVM_PAYEE_ADDRESS) { @@ -61,6 +64,9 @@ x402Server.register("solana:*", new ExactSvmScheme()); if (APTOS_PAYEE_ADDRESS) { x402Server.register("aptos:*", new ExactAptosScheme()); } +if (STELLAR_PAYEE_ADDRESS) { + x402Server.register("stellar:*", new ExactStellarScheme()); +} // Register Bazaar discovery extension x402Server.registerExtension(bazaarResourceServerExtension); @@ -84,6 +90,20 @@ app.use("/protected-aptos", async (c, next) => { await next(); }); +/** + * Pre-middleware guard for optional Stellar endpoint + * Returns 501 Not Implemented if Stellar is not configured + */ +app.use("/protected-stellar", async (c, next) => { + if (!STELLAR_PAYEE_ADDRESS) { + return c.json({ + error: "Stellar payments not configured", + message: "STELLAR_PAYEE_ADDRESS environment variable is not set", + }, 501); + } + await next(); +}); + /** * Configure x402 payment middleware using builder pattern * @@ -227,6 +247,35 @@ app.use( ...declareErc20ApprovalGasSponsoringExtension(), }, }, + ...(STELLAR_PAYEE_ADDRESS + ? { + "GET /protected-stellar": { + accepts: { + payTo: STELLAR_PAYEE_ADDRESS!, + scheme: "exact", + price: "$0.001", + network: STELLAR_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected Stellar endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, + }, + } + : {}), }, x402Server, // Pass pre-configured server instance ), @@ -283,6 +332,7 @@ app.get("/protected-permit2", (c) => { }); }); +/** /** * Protected Permit2 ERC-20 endpoint - requires Permit2 payment with ERC-20 approval gas sponsoring */ @@ -294,6 +344,22 @@ app.get("/protected-permit2-erc20", (c) => { }); }); +/** + * Protected Stellar endpoint - requires payment to access + * + * This endpoint demonstrates a resource protected by x402 payment middleware for Stellar. + * Clients must provide a valid payment signature to access this endpoint. + * Note: 501 check is handled by pre-middleware guard above. + */ +if (STELLAR_PAYEE_ADDRESS) { + app.get("/protected-stellar", c => { + return c.json({ + message: "Protected Stellar endpoint accessed successfully", + timestamp: new Date().toISOString(), + }); + }); +} + /** * Health check endpoint - no payment required * @@ -338,9 +404,11 @@ console.log(` β•‘ EVM Network: ${EVM_NETWORK} β•‘ β•‘ SVM Network: ${SVM_NETWORK} β•‘ β•‘ Aptos Network: ${APTOS_NETWORK} β•‘ +β•‘ Stellar Network: ${STELLAR_NETWORK} β•‘ β•‘ EVM Payee: ${EVM_PAYEE_ADDRESS} β•‘ β•‘ SVM Payee: ${SVM_PAYEE_ADDRESS} β•‘ β•‘ Aptos Payee: ${APTOS_PAYEE_ADDRESS || "(not configured)"} +β•‘ Stellar Payee: ${STELLAR_PAYEE_ADDRESS || "(not configured)"} β•‘ β•‘ β•‘ Endpoints: β•‘ β•‘ β€’ GET /protected (EIP-3009 payment) β•‘ @@ -348,6 +416,7 @@ console.log(` β•‘ β€’ GET /protected-permit2-erc20 (Permit2 + ERC-20 approval)β•‘ β•‘ β€’ GET /protected-svm (SVM payment) β•‘ β•‘ β€’ GET /protected-aptos (Aptos payment) β•‘ +β•‘ β€’ GET /protected-stellar (Stellar payment) β•‘ β•‘ β€’ GET /health (no payment required) β•‘ β•‘ β€’ POST /close (shutdown server) β•‘ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β• diff --git a/e2e/servers/hono/package.json b/e2e/servers/hono/package.json index c4924a9b02..0e486907d3 100644 --- a/e2e/servers/hono/package.json +++ b/e2e/servers/hono/package.json @@ -16,6 +16,7 @@ "@x402/evm": "workspace:*", "@x402/extensions": "workspace:*", "@x402/hono": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/svm": "workspace:*", "dotenv": "^16.6.1", "hono": "^4.7.1" diff --git a/e2e/servers/hono/test.config.json b/e2e/servers/hono/test.config.json index 2030b88cf0..8f9cd44efc 100644 --- a/e2e/servers/hono/test.config.json +++ b/e2e/servers/hono/test.config.json @@ -48,6 +48,13 @@ "requiresPayment": true, "protocolFamily": "aptos" }, + { + "path": "/protected-stellar", + "method": "GET", + "description": "Protected endpoint requiring payment on Stellar network", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/health", "method": "GET", @@ -69,7 +76,9 @@ "FACILITATOR_URL" ], "optional": [ - "APTOS_PAYEE_ADDRESS" + "APTOS_PAYEE_ADDRESS", + "STELLAR_PAYEE_ADDRESS", + "STELLAR_NETWORK" ] } } \ No newline at end of file diff --git a/e2e/servers/next/.env-local b/e2e/servers/next/.env-local index 922c516362..4fb43f9906 100644 --- a/e2e/servers/next/.env-local +++ b/e2e/servers/next/.env-local @@ -1,3 +1,5 @@ -NEXT_PUBLIC_FACILITATOR_URL=https://x402.org/facilitator -NETWORK=base-sepolia -RESOURCE_WALLET_ADDRESS= +PORT=3000 +EVM_PAYEE_ADDRESS= +SVM_PAYEE_ADDRESS= +STELLAR_PAYEE_ADDRESS= +FACILITATOR_URL=http://localhost:4000 diff --git a/e2e/servers/next/README.md b/e2e/servers/next/README.md index 87fb5e128a..5992b03e2d 100644 --- a/e2e/servers/next/README.md +++ b/e2e/servers/next/README.md @@ -1,16 +1,18 @@ # 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. +This is a Next.js application that demonstrates how to use the `x402-next` middleware to implement paywall functionality in your Next.js routes with EVM, SVM, and optional Stellar payment support. ## 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 +- A valid Solana address for receiving payments +- (Optional) A valid Stellar address for receiving payments ## Setup -1. Copy `.env.local` to `.env` and add your Ethereum address to receive payments: +1. Copy `.env.local` to `.env` and add your addresses to receive payments: ```bash cp .env.local .env @@ -125,3 +127,17 @@ export const config = { matcher: ["/protected/:path*", "/api/premium/:path*"], }; ``` + +## Environment Variables + +### Required +- `PORT` - HTTP server port +- `EVM_PAYEE_ADDRESS` - Ethereum address to receive payments +- `SVM_PAYEE_ADDRESS` - Solana address to receive payments +- `FACILITATOR_URL` - Facilitator endpoint URL + +### Optional +- `STELLAR_PAYEE_ADDRESS` - Stellar address to receive payments - enables Stellar endpoints +- `EVM_NETWORK` - EVM network (default: eip155:84532) +- `SVM_NETWORK` - SVM network (default: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1) +- `STELLAR_NETWORK` - Stellar network (default: stellar:testnet) diff --git a/e2e/servers/next/app/api/protected-stellar-proxy/route.ts b/e2e/servers/next/app/api/protected-stellar-proxy/route.ts new file mode 100644 index 0000000000..eab18c156f --- /dev/null +++ b/e2e/servers/next/app/api/protected-stellar-proxy/route.ts @@ -0,0 +1,16 @@ +import { NextResponse } from "next/server"; + +/** + * Protected Stellar endpoint requiring payment (proxy middleware) + */ +export const runtime = "nodejs"; + +/** + * Protected Stellar endpoint requiring payment (proxy middleware) + */ +export async function GET() { + return NextResponse.json({ + message: "Protected Stellar endpoint accessed successfully", + timestamp: new Date().toISOString(), + }); +} diff --git a/e2e/servers/next/app/api/protected-stellar-withx402/route.ts b/e2e/servers/next/app/api/protected-stellar-withx402/route.ts new file mode 100644 index 0000000000..7082891b44 --- /dev/null +++ b/e2e/servers/next/app/api/protected-stellar-withx402/route.ts @@ -0,0 +1,55 @@ +import { NextRequest, NextResponse } from "next/server"; +import { withX402 } from "@x402/next"; +import { declareDiscoveryExtension } from "@x402/extensions/bazaar"; +import { server, STELLAR_PAYEE_ADDRESS, STELLAR_NETWORK } from "../../../proxy"; + +/** + * Handler for the protected endpoint + */ +const handler = async (_: NextRequest) => { + return NextResponse.json({ + message: "Protected Stellar endpoint accessed successfully (withX402)", + timestamp: new Date().toISOString(), + }); +}; + +/** + * Protected Stellar endpoint using withX402 wrapper + * Only exported if STELLAR_PAYEE_ADDRESS is configured + */ +export const GET = STELLAR_PAYEE_ADDRESS + ? withX402( + handler, + { + accepts: { + payTo: STELLAR_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: STELLAR_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected Stellar endpoint accessed successfully (withX402)", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + }, + required: ["message", "timestamp"], + }, + }, + }), + }, + }, + server, + ) + : async () => { + return NextResponse.json( + { error: "Stellar not configured" }, + { status: 503 }, + ); + }; diff --git a/e2e/servers/next/package.json b/e2e/servers/next/package.json index 917e7c47ad..27083854bd 100644 --- a/e2e/servers/next/package.json +++ b/e2e/servers/next/package.json @@ -18,6 +18,7 @@ "@x402/evm": "workspace:*", "@x402/extensions": "workspace:*", "@x402/next": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/svm": "workspace:*", "@heroicons/react": "^2.2.0", "next": "^16.0.10", diff --git a/e2e/servers/next/proxy.ts b/e2e/servers/next/proxy.ts index 5225b8204c..5021a801da 100644 --- a/e2e/servers/next/proxy.ts +++ b/e2e/servers/next/proxy.ts @@ -3,6 +3,7 @@ import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { ExactSvmScheme } from "@x402/svm/exact/server"; import { ExactAptosScheme } from "@x402/aptos/exact/server"; +import { ExactStellarScheme } from "@x402/stellar/exact/server"; import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; import { declareEip2612GasSponsoringExtension, @@ -12,9 +13,11 @@ import { 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 APTOS_PAYEE_ADDRESS = process.env.APTOS_PAYEE_ADDRESS as string; +export const STELLAR_PAYEE_ADDRESS = process.env.STELLAR_PAYEE_ADDRESS as string | undefined; export const EVM_NETWORK = (process.env.EVM_NETWORK || "eip155:84532") as `${string}:${string}`; export const SVM_NETWORK = (process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; export const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; +export const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") as `${string}:${string}`; const facilitatorUrl = process.env.FACILITATOR_URL; if (!facilitatorUrl) { @@ -34,11 +37,17 @@ server.register("solana:*", new ExactSvmScheme()); if (APTOS_PAYEE_ADDRESS) { server.register("aptos:*", new ExactAptosScheme()); } +if (STELLAR_PAYEE_ADDRESS) { + server.register("stellar:*", new ExactStellarScheme()); +} // Register Bazaar discovery extension server.registerExtension(bazaarResourceServerExtension); console.log(`Using remote facilitator at: ${facilitatorUrl}`); +if (STELLAR_PAYEE_ADDRESS) { + console.log(`Stellar Payee Address: ${STELLAR_PAYEE_ADDRESS}`); +} export const proxy = paymentProxy( { @@ -174,10 +183,46 @@ export const proxy = paymentProxy( ...declareErc20ApprovalGasSponsoringExtension(), }, }, + ...(STELLAR_PAYEE_ADDRESS + ? { + "/api/protected-stellar-proxy": { + accepts: { + payTo: STELLAR_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: STELLAR_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected Stellar 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 ); export const config = { - matcher: ["/api/protected-proxy", "/api/protected-svm-proxy", "/api/protected-aptos-proxy", "/api/protected-permit2-proxy", "/api/protected-permit2-erc20-proxy"], + matcher: [ + "/api/protected-proxy", + "/api/protected-svm-proxy", + "/api/protected-aptos-proxy", + "/api/protected-permit2-proxy", + "/api/protected-permit2-erc20-proxy", + "/api/protected-stellar-proxy", + ], }; diff --git a/e2e/servers/next/test.config.json b/e2e/servers/next/test.config.json index cc502099bb..07b63d174d 100644 --- a/e2e/servers/next/test.config.json +++ b/e2e/servers/next/test.config.json @@ -48,6 +48,13 @@ "requiresPayment": true, "protocolFamily": "aptos" }, + { + "path": "/api/protected-stellar-proxy", + "method": "GET", + "description": "Protected endpoint using proxy middleware on Stellar", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/api/protected-withx402", "method": "GET", @@ -63,6 +70,13 @@ "requiresPayment": true, "protocolFamily": "svm" }, + { + "path": "/api/protected-stellar-withx402", + "method": "GET", + "description": "Protected endpoint using withX402 wrapper on Stellar", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/api/health", "method": "GET", @@ -84,7 +98,9 @@ "FACILITATOR_URL" ], "optional": [ - "APTOS_PAYEE_ADDRESS" + "APTOS_PAYEE_ADDRESS", + "STELLAR_PAYEE_ADDRESS", + "STELLAR_NETWORK" ] } } \ No newline at end of file diff --git a/e2e/src/clients/generic-client.ts b/e2e/src/clients/generic-client.ts index c4d0ec8142..1bad2d5e94 100644 --- a/e2e/src/clients/generic-client.ts +++ b/e2e/src/clients/generic-client.ts @@ -23,6 +23,7 @@ export class GenericClientProxy extends BaseProxy implements ClientProxy { EVM_PRIVATE_KEY: config.evmPrivateKey, SVM_PRIVATE_KEY: config.svmPrivateKey, APTOS_PRIVATE_KEY: config.aptosPrivateKey, + STELLAR_PRIVATE_KEY: config.stellarPrivateKey, RESOURCE_SERVER_URL: config.serverUrl, ENDPOINT_PATH: config.endpointPath, } diff --git a/e2e/src/facilitators/facilitator-manager.ts b/e2e/src/facilitators/facilitator-manager.ts index 9583c31228..e54be2da78 100644 --- a/e2e/src/facilitators/facilitator-manager.ts +++ b/e2e/src/facilitators/facilitator-manager.ts @@ -36,6 +36,7 @@ export class FacilitatorManager { evmPrivateKey: process.env.FACILITATOR_EVM_PRIVATE_KEY, svmPrivateKey: process.env.FACILITATOR_SVM_PRIVATE_KEY, aptosPrivateKey: process.env.FACILITATOR_APTOS_PRIVATE_KEY, + stellarPrivateKey: process.env.FACILITATOR_STELLAR_PRIVATE_KEY, networks, }); diff --git a/e2e/src/facilitators/generic-facilitator.ts b/e2e/src/facilitators/generic-facilitator.ts index 03f510bbae..672f758a8a 100644 --- a/e2e/src/facilitators/generic-facilitator.ts +++ b/e2e/src/facilitators/generic-facilitator.ts @@ -54,6 +54,7 @@ export interface FacilitatorConfig { evmPrivateKey?: string; svmPrivateKey?: string; aptosPrivateKey?: string; + stellarPrivateKey?: string; networks: NetworkSet; } @@ -114,6 +115,7 @@ export class GenericFacilitatorProxy extends BaseProxy implements FacilitatorPro EVM_PRIVATE_KEY: config.evmPrivateKey || '', SVM_PRIVATE_KEY: config.svmPrivateKey || '', APTOS_PRIVATE_KEY: config.aptosPrivateKey || '', + STELLAR_PRIVATE_KEY: config.stellarPrivateKey || '', // Network configs from NetworkSet EVM_NETWORK: config.networks.evm.caip2, @@ -122,6 +124,8 @@ export class GenericFacilitatorProxy extends BaseProxy implements FacilitatorPro SVM_RPC_URL: config.networks.svm.rpcUrl, APTOS_NETWORK: config.networks.aptos.caip2, APTOS_RPC_URL: config.networks.aptos.rpcUrl, + STELLAR_NETWORK: config.networks.stellar.caip2, + STELLAR_RPC_URL: config.networks.stellar.rpcUrl, }; // Pass through any additional environment variables required by the facilitator diff --git a/e2e/src/networks/networks.ts b/e2e/src/networks/networks.ts index c4d64d65c3..8425f255e2 100644 --- a/e2e/src/networks/networks.ts +++ b/e2e/src/networks/networks.ts @@ -6,7 +6,7 @@ */ export type NetworkMode = 'testnet' | 'mainnet'; -export type ProtocolFamily = 'evm' | 'svm' | 'aptos'; +export type ProtocolFamily = 'evm' | 'svm' | 'aptos' | 'stellar'; export type NetworkConfig = { name: string; @@ -18,6 +18,7 @@ export type NetworkSet = { evm: NetworkConfig; svm: NetworkConfig; aptos: NetworkConfig; + stellar: NetworkConfig; }; /** @@ -40,6 +41,11 @@ const NETWORK_SETS: Record = { caip2: 'aptos:2', rpcUrl: process.env.APTOS_TESTNET_RPC_URL || 'https://fullnode.testnet.aptoslabs.com/v1', }, + stellar: { + name: 'Stellar Testnet', + caip2: 'stellar:testnet', + rpcUrl: process.env.STELLAR_TESTNET_RPC_URL || 'https://soroban-testnet.stellar.org', + }, }, mainnet: { evm: { @@ -57,6 +63,11 @@ const NETWORK_SETS: Record = { caip2: 'aptos:1', rpcUrl: process.env.APTOS_RPC_URL || 'https://fullnode.mainnet.aptoslabs.com/v1', }, + stellar: { + name: 'Stellar Pubnet', + caip2: 'stellar:pubnet', + rpcUrl: process.env.STELLAR_RPC_URL || 'https://mainnet.sorobanrpc.com', + }, }, }; @@ -74,7 +85,7 @@ export function getNetworkSet(mode: NetworkMode): NetworkSet { * Get network config for a protocol family in a given mode * * @param mode - 'testnet' or 'mainnet' - * @param protocolFamily - 'evm', 'svm', or 'aptos' + * @param protocolFamily - 'evm', 'svm', 'aptos', or 'stellar' * @returns NetworkConfig for the specified protocol */ export function getNetworkForProtocol( @@ -92,5 +103,6 @@ export function getNetworkForProtocol( */ export function getNetworkModeDescription(mode: NetworkMode): string { const set = NETWORK_SETS[mode]; - return `${set.evm.name} + ${set.svm.name} + ${set.aptos.name}`; + const networks = [set.evm.name, set.svm.name, set.aptos.name, set.stellar.name]; + return networks.join(' + '); } diff --git a/e2e/src/servers/generic-server.ts b/e2e/src/servers/generic-server.ts index 83783aa513..36c7895d80 100644 --- a/e2e/src/servers/generic-server.ts +++ b/e2e/src/servers/generic-server.ts @@ -103,6 +103,11 @@ export class GenericServerProxy extends BaseProxy implements ServerProxy { APTOS_RPC_URL: config.networks.aptos.rpcUrl, APTOS_PAYEE_ADDRESS: config.aptosPayTo, + // Stellar network config + STELLAR_NETWORK: config.networks.stellar.caip2, + STELLAR_RPC_URL: config.networks.stellar.rpcUrl, + STELLAR_PAYEE_ADDRESS: config.stellarPayTo, + // Facilitator FACILITATOR_URL: config.facilitatorUrl || '', } diff --git a/e2e/src/types.ts b/e2e/src/types.ts index 991e6050cb..f4c200557f 100644 --- a/e2e/src/types.ts +++ b/e2e/src/types.ts @@ -1,6 +1,6 @@ import type { NetworkSet } from './networks/networks'; -export type ProtocolFamily = 'evm' | 'svm' | 'aptos'; +export type ProtocolFamily = 'evm' | 'svm' | 'aptos' | 'stellar'; export type Transport = 'http' | 'mcp'; export type TransferMethod = 'eip3009' | 'permit2'; @@ -16,6 +16,7 @@ export interface ClientConfig { evmPrivateKey: string; svmPrivateKey: string; aptosPrivateKey: string; + stellarPrivateKey: string; serverUrl: string; endpointPath: string; } @@ -25,6 +26,7 @@ export interface ServerConfig { evmPayTo: string; svmPayTo: string; aptosPayTo: string; + stellarPayTo: string; networks: NetworkSet; facilitatorUrl?: string; } diff --git a/e2e/test.ts b/e2e/test.ts index 8d0fcb17e1..e3e2d37eb5 100644 --- a/e2e/test.ts +++ b/e2e/test.ts @@ -237,13 +237,15 @@ async function runTest() { const serverEvmAddress = process.env.SERVER_EVM_ADDRESS; const serverSvmAddress = process.env.SERVER_SVM_ADDRESS; const serverAptosAddress = process.env.SERVER_APTOS_ADDRESS; + const serverStellarAddress = process.env.SERVER_STELLAR_ADDRESS; const clientEvmPrivateKey = process.env.CLIENT_EVM_PRIVATE_KEY; const clientSvmPrivateKey = process.env.CLIENT_SVM_PRIVATE_KEY; const clientAptosPrivateKey = process.env.CLIENT_APTOS_PRIVATE_KEY; + const clientStellarPrivateKey = process.env.CLIENT_STELLAR_PRIVATE_KEY; const facilitatorEvmPrivateKey = process.env.FACILITATOR_EVM_PRIVATE_KEY; const facilitatorSvmPrivateKey = process.env.FACILITATOR_SVM_PRIVATE_KEY; const facilitatorAptosPrivateKey = process.env.FACILITATOR_APTOS_PRIVATE_KEY; - + const facilitatorStellarPrivateKey = process.env.FACILITATOR_STELLAR_PRIVATE_KEY; if (!serverEvmAddress || !serverSvmAddress || !clientEvmPrivateKey || !clientSvmPrivateKey || !facilitatorEvmPrivateKey || !facilitatorSvmPrivateKey) { errorLog('❌ Missing required environment variables:'); 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'); @@ -320,6 +322,7 @@ async function runTest() { log(` EVM: ${networks.evm.name} (${networks.evm.caip2})`); log(` SVM: ${networks.svm.name} (${networks.svm.caip2})`); log(` APTOS: ${networks.aptos.name} (${networks.aptos.caip2})`); + log(` STELLAR: ${networks.stellar.name} (${networks.stellar.caip2})`); if (networkMode === 'mainnet') { log('\n⚠️ WARNING: Running on MAINNET - real funds will be used!'); @@ -396,7 +399,21 @@ async function runTest() { 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', 'APTOS_PRIVATE_KEY', 'EVM_NETWORK', 'SVM_NETWORK', 'APTOS_NETWORK', 'EVM_RPC_URL', 'SVM_RPC_URL', 'APTOS_RPC_URL']); + const systemManagedVars = new Set([ + 'PORT', + 'EVM_PRIVATE_KEY', + 'SVM_PRIVATE_KEY', + 'APTOS_PRIVATE_KEY', + 'STELLAR_PRIVATE_KEY', + 'EVM_NETWORK', + 'SVM_NETWORK', + 'APTOS_NETWORK', + 'STELLAR_NETWORK', + 'EVM_RPC_URL', + 'SVM_RPC_URL', + 'APTOS_RPC_URL', + 'STELLAR_RPC_URL', + ]); for (const [facilitatorName, facilitator] of uniqueFacilitators) { const requiredVars = facilitator.config.environment?.required || []; @@ -551,6 +568,7 @@ async function runTest() { evmPrivateKey: clientEvmPrivateKey!, svmPrivateKey: clientSvmPrivateKey!, aptosPrivateKey: clientAptosPrivateKey || '', + stellarPrivateKey: clientStellarPrivateKey || '', serverUrl: `http://localhost:${port}`, endpointPath: scenario.endpoint.path, }; @@ -636,6 +654,7 @@ async function runTest() { evmPayTo: serverEvmAddress!, svmPayTo: serverSvmAddress!, aptosPayTo: facilitatorSupportsAptos ? (serverAptosAddress || '') : '', + stellarPayTo: serverStellarAddress || '', networks, facilitatorUrl, }; diff --git a/examples/typescript/clients/advanced/.env-local b/examples/typescript/clients/advanced/.env-local index 8339ac0ab9..57f92e9636 100644 --- a/examples/typescript/clients/advanced/.env-local +++ b/examples/typescript/clients/advanced/.env-local @@ -1,4 +1,5 @@ EVM_PRIVATE_KEY= SVM_PRIVATE_KEY= +STELLAR_PRIVATE_KEY= RESOURCE_SERVER_URL=http://localhost:4021 ENDPOINT_PATH=/weather \ No newline at end of file diff --git a/examples/typescript/clients/advanced/README.md b/examples/typescript/clients/advanced/README.md index 743e968637..4c3470db26 100644 --- a/examples/typescript/clients/advanced/README.md +++ b/examples/typescript/clients/advanced/README.md @@ -24,7 +24,7 @@ const response = await fetchWithPayment("http://localhost:4021/weather"); - 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 +- Valid EVM, SVM, and/or Stellar private keys for making payments - A running x402 server (see [server examples](../../servers/)) - Familiarity with the [basic fetch client](../fetch/) @@ -40,6 +40,7 @@ and fill required environment variables: - `EVM_PRIVATE_KEY` - Ethereum private key for EVM payments - `SVM_PRIVATE_KEY` - Solana private key for SVM payments +- `STELLAR_PRIVATE_KEY` - Stellar secret key (starts with `S`) for signing Stellar payments 2. Install and build all packages from the typescript examples root: @@ -55,6 +56,16 @@ cd clients/advanced pnpm dev ``` +### Account Setup Instructions + +#### Stellar Testnet + +Stellar accounts need to be created and funded with both XLM and USDC. Instructions: + +1. Go to [Stellar Laboratory](https://lab.stellar.org/account/create) ➑️ Generate keypair ➑️ Fund account with Friendbot, then copy the `Secret` and `Public` keys so you can use them. +2. Add USDC trustline (required to transact USDC): go to [Fund Account](https://lab.stellar.org/account/fund) ➑️ Paste your `Public Key` ➑️ Add USDC Trustline ➑️ paste your `Secret key` ➑️ Sign transaction ➑️ Add Trustline. +3. Get testnet USDC from [Circle Faucet](https://faucet.circle.com/) (select Stellar network). + ## Available Examples Each example demonstrates a specific advanced pattern: @@ -90,6 +101,7 @@ Use the builder pattern for fine-grained control over which networks are support import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { ExactSvmScheme } from "@x402/svm/exact/client"; +import { ExactStellarScheme } from "@x402/stellar/exact/client"; import { privateKeyToAccount } from "viem/accounts"; const evmSigner = privateKeyToAccount(evmPrivateKey); @@ -100,6 +112,7 @@ const client = new x402Client() .register("eip155:*", new ExactEvmScheme(evmSigner)) // All EVM networks .register("eip155:1", new ExactEvmScheme(mainnetSigner)) // Ethereum mainnet override .register("solana:*", new ExactSvmScheme(svmSigner)); // All Solana networks + .register("stellar:*", new ExactStellarScheme(stellarSigner)); // All Stellar networks const fetchWithPayment = wrapFetchWithPayment(fetch, client); const response = await fetchWithPayment("http://localhost:4021/weather"); @@ -162,9 +175,10 @@ Configure client-side network preferences with automatic fallback: import { x402Client, wrapFetchWithPayment, type PaymentRequirements } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { ExactSvmScheme } from "@x402/svm/exact/client"; +import { ExactStellarScheme } from "@x402/stellar/exact/client"; // Define network preference order (most preferred first) -const networkPreferences = ["solana:", "eip155:"]; +const networkPreferences = ["eip155:", "solana:", "stellar:"]; const preferredNetworkSelector = ( _x402Version: number, @@ -181,7 +195,8 @@ const preferredNetworkSelector = ( const client = new x402Client(preferredNetworkSelector) .register("eip155:*", new ExactEvmScheme(evmSigner)) - .register("solana:*", new ExactSvmScheme(svmSigner)); + .register("solana:*", new ExactSvmScheme(svmSigner)) + .register("stellar:*", new ExactStellarScheme(stellarSigner)); const fetchWithPayment = wrapFetchWithPayment(fetch, client); const response = await fetchWithPayment("http://localhost:4021/weather"); diff --git a/examples/typescript/clients/advanced/all_networks.ts b/examples/typescript/clients/advanced/all_networks.ts index 620819f476..61620e2c72 100644 --- a/examples/typescript/clients/advanced/all_networks.ts +++ b/examples/typescript/clients/advanced/all_networks.ts @@ -5,13 +5,15 @@ * optional chain configuration via environment variables. * * New chain support should be added here in alphabetic order by network prefix - * (e.g., "eip155" before "solana"). + * (e.g., "eip155" before "solana" before "stellar"). */ import { config } from "dotenv"; import { x402Client, wrapFetchWithPayment, x402HTTPClient } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { ExactSvmScheme } from "@x402/svm/exact/client"; +import { ExactStellarScheme } from "@x402/stellar/exact/client"; +import { createEd25519Signer } from "@x402/stellar"; import { privateKeyToAccount } from "viem/accounts"; import { createKeyPairSignerFromBytes } from "@solana/kit"; import { base58 } from "@scure/base"; @@ -21,6 +23,7 @@ config(); // Configuration - optional per network const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}` | undefined; const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string | undefined; +const stellarPrivateKey = process.env.STELLAR_PRIVATE_KEY as string | undefined; const baseURL = process.env.RESOURCE_SERVER_URL || "http://localhost:4021"; const endpointPath = process.env.ENDPOINT_PATH || "/weather"; const url = `${baseURL}${endpointPath}`; @@ -31,8 +34,10 @@ const url = `${baseURL}${endpointPath}`; */ async function main(): Promise { // Validate at least one private key is provided - if (!evmPrivateKey && !svmPrivateKey) { - console.error("❌ At least one of EVM_PRIVATE_KEY or SVM_PRIVATE_KEY is required"); + if (!evmPrivateKey && !svmPrivateKey && !stellarPrivateKey) { + console.error( + "❌ At least one of EVM_PRIVATE_KEY, SVM_PRIVATE_KEY, or STELLAR_PRIVATE_KEY is required", + ); process.exit(1); } @@ -53,6 +58,13 @@ async function main(): Promise { console.log(`Initialized SVM account: ${svmSigner.address}`); } + // Register Stellar scheme if private key is provided + if (stellarPrivateKey) { + const stellarSigner = createEd25519Signer(stellarPrivateKey); + client.register("stellar:*", new ExactStellarScheme(stellarSigner)); + console.log(`Initialized Stellar account: ${stellarSigner.address}`); + } + // Wrap fetch with payment handling const fetchWithPayment = wrapFetchWithPayment(fetch, client); diff --git a/examples/typescript/clients/advanced/package.json b/examples/typescript/clients/advanced/package.json index fa8b4a4b4d..66b2fc1a26 100644 --- a/examples/typescript/clients/advanced/package.json +++ b/examples/typescript/clients/advanced/package.json @@ -18,6 +18,7 @@ "@scure/base": "^1.2.6", "@x402/evm": "workspace:*", "@x402/svm": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/fetch": "workspace:*", "dotenv": "^16.4.7", "viem": "^2.39.0", diff --git a/examples/typescript/facilitator/.env-local b/examples/typescript/facilitator/.env-local index 7534548c3f..b9b7a2492b 100644 --- a/examples/typescript/facilitator/.env-local +++ b/examples/typescript/facilitator/.env-local @@ -1,3 +1,4 @@ PORT= EVM_PRIVATE_KEY= +STELLAR_PRIVATE_KEY= SVM_PRIVATE_KEY= \ No newline at end of file diff --git a/examples/typescript/facilitator/advanced/README.md b/examples/typescript/facilitator/advanced/README.md index e0fbb94a6a..a0ab84758e 100644 --- a/examples/typescript/facilitator/advanced/README.md +++ b/examples/typescript/facilitator/advanced/README.md @@ -8,6 +8,7 @@ Express.js facilitator service demonstrating advanced x402 patterns including al - pnpm v10 (install via [pnpm.io/installation](https://pnpm.io/installation)) - EVM private key with Base Sepolia ETH for transaction fees - SVM private key with Solana Devnet SOL for transaction fees +- Stellar private key with testnet XLM for transaction fees (fund via [Stellar Laboratory](https://lab.stellar.org/account/create) ➑️ Generate keypair ➑️ Fund account with Friendbot) ## Setup @@ -21,6 +22,7 @@ and fill required environment variables: - `EVM_PRIVATE_KEY` - Ethereum private key - `SVM_PRIVATE_KEY` - Solana private key +- `STELLAR_PRIVATE_KEY` - Stellar secret key (starts with `S`) - `PORT` - Server port (optional, defaults to 4022) 2. Install and build all packages from the typescript examples root: @@ -68,12 +70,21 @@ Returns payment schemes and networks this facilitator supports. "extra": { "feePayer": "..." } + }, + { + "x402Version": 2, + "scheme": "exact", + "network": "stellar:testnet", + "extra": { + "areFeesSponsored": true + } } ], "extensions": [], "signers": { "eip155": ["0x..."], - "solana": ["..."] + "solana": ["..."], + "stellar": ["G..."] } } ``` @@ -229,3 +240,5 @@ Networks use [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/cai - `eip155:8453` β€” Base Mainnet - `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` β€” Solana Devnet - `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` β€” Solana Mainnet +- `stellar:testnet` β€” Stellar Testnet +- `stellar:pubnet` β€” Stellar Mainnet diff --git a/examples/typescript/facilitator/advanced/all_networks.ts b/examples/typescript/facilitator/advanced/all_networks.ts index c56b07523b..1513417b41 100644 --- a/examples/typescript/facilitator/advanced/all_networks.ts +++ b/examples/typescript/facilitator/advanced/all_networks.ts @@ -5,7 +5,7 @@ * optional chain configuration via environment variables. * * New chain support should be added here in alphabetic order by network prefix - * (e.g., "eip155" before "solana"). + * (e.g., "eip155" before "solana" before "stellar"). */ import { base58 } from "@scure/base"; @@ -21,6 +21,8 @@ import { toFacilitatorEvmSigner } from "@x402/evm"; import { ExactEvmScheme } from "@x402/evm/exact/facilitator"; import { toFacilitatorSvmSigner } from "@x402/svm"; import { ExactSvmScheme } from "@x402/svm/exact/facilitator"; +import { createEd25519Signer } from "@x402/stellar"; +import { ExactStellarScheme } from "@x402/stellar/exact/facilitator"; import dotenv from "dotenv"; import express from "express"; import { createWalletClient, http, publicActions } from "viem"; @@ -35,11 +37,12 @@ const PORT = process.env.PORT || "4022"; // Configuration - optional per network const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}` | undefined; const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string | undefined; +const stellarPrivateKey = process.env.STELLAR_PRIVATE_KEY as string | undefined; // Validate at least one private key is provided -if (!evmPrivateKey && !svmPrivateKey) { +if (!evmPrivateKey && !svmPrivateKey && !stellarPrivateKey) { console.error( - "❌ At least one of EVM_PRIVATE_KEY or SVM_PRIVATE_KEY is required", + "❌ At least one of EVM_PRIVATE_KEY, SVM_PRIVATE_KEY, or STELLAR_PRIVATE_KEY is required", ); process.exit(1); } @@ -47,6 +50,7 @@ if (!evmPrivateKey && !svmPrivateKey) { // Network configuration const EVM_NETWORK = "eip155:84532"; // Base Sepolia const SVM_NETWORK = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"; // Solana Devnet +const STELLAR_NETWORK = "stellar:testnet"; // Stellar Testnet // Initialize the x402 Facilitator const facilitator = new x402Facilitator() @@ -137,6 +141,17 @@ if (svmPrivateKey) { facilitator.register(SVM_NETWORK, new ExactSvmScheme(svmSigner)); } +// Register Stellar scheme if private key is provided +if (stellarPrivateKey) { + const stellarSigner = createEd25519Signer(stellarPrivateKey); + console.info(`Stellar Facilitator account: ${stellarSigner.address}`); + + facilitator.register( + STELLAR_NETWORK, + new ExactStellarScheme([stellarSigner]), + ); +} + // Initialize Express app const app = express(); app.use(express.json()); diff --git a/examples/typescript/facilitator/advanced/package.json b/examples/typescript/facilitator/advanced/package.json index 05f03aa129..34253157d8 100644 --- a/examples/typescript/facilitator/advanced/package.json +++ b/examples/typescript/facilitator/advanced/package.json @@ -20,6 +20,7 @@ "@x402/evm": "workspace:*", "@x402/extensions": "workspace:*", "@x402/svm": "workspace:*", + "@x402/stellar": "workspace:*", "dotenv": "^16.4.5", "express": "^4.19.2", "viem": "^2.21.54" diff --git a/examples/typescript/pnpm-lock.yaml b/examples/typescript/pnpm-lock.yaml index 024cf50dd3..58c3c84532 100644 --- a/examples/typescript/pnpm-lock.yaml +++ b/examples/typescript/pnpm-lock.yaml @@ -367,7 +367,7 @@ importers: version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) hono: specifier: ^4.7.1 - version: 4.9.2 + version: 4.10.7 prettier: specifier: 3.5.2 version: 3.5.2 @@ -898,7 +898,7 @@ importers: version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) hono: specifier: ^4.7.1 - version: 4.9.2 + version: 4.10.7 viem: specifier: ^2.21.26 version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -1205,6 +1205,61 @@ importers: specifier: ^3.0.5 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.17.2)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.4)(yaml@2.8.1) + ../../typescript/packages/mechanisms/stellar: + dependencies: + '@stellar/stellar-sdk': + specifier: ^14.4.2 + version: 14.5.0 + '@x402/core': + specifier: workspace:* + version: link:../../core + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.33.0 + '@types/node': + specifier: ^22.13.4 + version: 22.17.2 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.24.0 + version: 9.33.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.4)(typescript@5.9.2)(yaml@2.8.1) + tsx: + specifier: ^4.19.2 + version: 4.20.4 + typescript: + specifier: ^5.7.3 + version: 5.9.2 + vite: + specifier: ^6.2.6 + version: 6.3.5(@types/node@22.17.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.4)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.17.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.4)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.17.2)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.4)(yaml@2.8.1) + ../../typescript/packages/mechanisms/svm: dependencies: '@solana-program/compute-budget': @@ -1286,6 +1341,9 @@ importers: '@x402/fetch': specifier: workspace:* version: link:../../../../typescript/packages/http/fetch + '@x402/stellar': + specifier: workspace:* + version: link:../../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../../typescript/packages/mechanisms/svm @@ -1569,7 +1627,7 @@ importers: version: 16.6.1 openai: specifier: ^4.77.3 - version: 4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + version: 4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) viem: specifier: ^2.39.0 version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -1735,6 +1793,9 @@ importers: '@x402/extensions': specifier: workspace:* version: link:../../../../typescript/packages/extensions + '@x402/stellar': + specifier: workspace:* + version: link:../../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../../typescript/packages/mechanisms/svm @@ -2179,7 +2240,7 @@ importers: dependencies: '@hono/node-server': specifier: ^1.13.8 - version: 1.19.0(hono@4.9.2) + version: 1.19.0(hono@4.10.7) axios: specifier: ^1.7.9 version: 1.13.2 @@ -2188,7 +2249,7 @@ importers: version: 16.6.1 hono: specifier: ^4.7.2 - version: 4.9.2 + version: 4.10.7 viem: specifier: ^2.23.5 version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) @@ -2253,7 +2314,7 @@ importers: version: 0.39.0(encoding@0.1.13) '@hono/node-server': specifier: ^1.14.1 - version: 1.19.0(hono@4.9.2) + version: 1.19.0(hono@4.10.7) '@llamaindex/anthropic': specifier: ^0.3.3 version: 0.3.23(@llamaindex/core@0.6.5)(@llamaindex/env@0.1.30) @@ -2265,7 +2326,7 @@ importers: version: 1.13.2 hono: specifier: ^4.7.7 - version: 4.9.2 + version: 4.10.7 llamaindex: specifier: ^0.10.2 version: 0.10.6(encoding@0.1.13)(tree-sitter@0.22.4)(web-tree-sitter@0.24.7)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) @@ -2366,13 +2427,13 @@ importers: dependencies: '@hono/node-server': specifier: ^1.11.2 - version: 1.19.0(hono@4.9.2) + version: 1.19.0(hono@4.10.7) dotenv: specifier: ^16.4.5 version: 16.6.1 hono: specifier: ^4.4.0 - version: 4.9.2 + version: 4.10.7 node-fetch: specifier: ^3.3.2 version: 3.3.2 @@ -2409,7 +2470,7 @@ importers: dependencies: '@hono/node-server': specifier: ^1.14.0 - version: 1.19.0(hono@4.9.2) + version: 1.19.0(hono@4.10.7) axios: specifier: ^1.10.0 version: 1.13.2 @@ -2418,7 +2479,7 @@ importers: version: 16.6.1 hono: specifier: ^4.6.17 - version: 4.9.2 + version: 4.10.7 react: specifier: ^18.3.1 version: 18.3.1 @@ -2887,13 +2948,13 @@ importers: dependencies: '@hono/node-server': specifier: ^1.13.8 - version: 1.19.0(hono@4.9.2) + version: 1.19.0(hono@4.10.7) dotenv: specifier: ^16.4.7 version: 16.6.1 hono: specifier: ^4.7.1 - version: 4.9.2 + version: 4.10.7 x402-hono: specifier: workspace:* version: link:../../../../../typescript/packages/legacy/x402-hono @@ -2946,6 +3007,9 @@ importers: '@x402/extensions': specifier: workspace:* version: link:../../../../typescript/packages/extensions + '@x402/stellar': + specifier: workspace:* + version: link:../../../../typescript/packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../../../../typescript/packages/mechanisms/svm @@ -3109,7 +3173,7 @@ importers: dependencies: '@hono/node-server': specifier: ^1.14.0 - version: 1.19.0(hono@4.9.2) + version: 1.19.0(hono@4.10.7) '@x402/core': specifier: workspace:* version: link:../../../../typescript/packages/core @@ -3130,7 +3194,7 @@ importers: version: 16.6.1 hono: specifier: ^4.7.1 - version: 4.9.2 + version: 4.10.7 devDependencies: '@eslint/js': specifier: ^9.24.0 @@ -3288,70 +3352,6 @@ importers: specifier: ^5.3.0 version: 5.9.2 - servers/receipt-attestation: - 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.4.7 - version: 16.6.1 - express: - specifier: ^4.18.2 - version: 4.21.2 - viem: - specifier: ^2.39.0 - version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - devDependencies: - '@eslint/js': - specifier: ^9.24.0 - version: 9.33.0 - '@types/express': - specifier: ^5.0.1 - version: 5.0.3 - '@types/node': - specifier: ^20.0.0 - version: 20.19.11 - '@typescript-eslint/eslint-plugin': - specifier: ^8.29.1 - version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) - '@typescript-eslint/parser': - specifier: ^8.29.1 - version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) - eslint: - specifier: ^9.24.0 - version: 9.33.0(jiti@2.6.1) - eslint-plugin-import: - specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) - eslint-plugin-jsdoc: - specifier: ^50.6.9 - version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) - eslint-plugin-prettier: - specifier: ^5.2.6 - version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) - prettier: - specifier: 3.5.2 - version: 3.5.2 - tsx: - specifier: ^4.7.0 - version: 4.20.4 - typescript: - specifier: ^5.3.0 - version: 5.9.2 - servers/sign-in-with-x: dependencies: '@x402/core': @@ -7594,6 +7594,18 @@ packages: '@stablelib/wipe@1.0.1': resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + '@stellar/js-xdr@3.1.2': + resolution: {integrity: sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==} + + '@stellar/stellar-base@14.0.4': + resolution: {integrity: sha512-UbNW6zbdOBXJwLAV2mMak0bIC9nw3IZVlQXkv2w2dk1jgCbJjy3oRVC943zeGE5JAm0Z9PHxrIjmkpGhayY7kw==} + engines: {node: '>=20.0.0'} + + '@stellar/stellar-sdk@14.5.0': + resolution: {integrity: sha512-Uzjq+An/hUA+Q5ERAYPtT0+MMiwWnYYWMwozmZMjxjdL2MmSjucBDF8Q04db6K/ekU4B5cHuOfsdlrfaxQYblw==} + engines: {node: '>=20.0.0'} + hasBin: true + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -8616,6 +8628,9 @@ packages: axios@1.13.2: resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + axios@1.13.4: + resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} + axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -8647,6 +8662,10 @@ packages: base-x@5.0.1: resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} + base32.js@0.1.0: + resolution: {integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==} + engines: {node: '>=0.12.0'} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -9752,6 +9771,10 @@ packages: resolution: {integrity: sha512-bSRG85ZrMdmWtm7qkF9He9TNRzc/Bm99gEJMaQoHJ9E6Kv9QBbsldh2oMj7iXmYNEAVvNgvv5vPorG6W+XtBhQ==} engines: {node: '>=20.0.0'} + eventsource@2.0.2: + resolution: {integrity: sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==} + engines: {node: '>=12.0.0'} + eventsource@3.0.7: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} @@ -9852,6 +9875,9 @@ packages: picomatch: optional: true + feaxios@0.0.23: + resolution: {integrity: sha512-eghR0A21fvbkcQBgZuMfQhrXxJzC0GNUGC9fXhBge33D+mFDTwl0aJ35zoQQn575BhyjQitRc5N4f+L4cP708g==} + fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} @@ -10162,10 +10188,6 @@ packages: resolution: {integrity: sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw==} engines: {node: '>=16.9.0'} - hono@4.9.2: - resolution: {integrity: sha512-UG2jXGS/gkLH42l/1uROnwXpkjvvxkl3kpopL3LBo27NuaDPI6xHNfuUSilIHcrBkPfl4y0z6y2ByI455TjNRw==} - engines: {node: '>=16.9.0'} - hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} @@ -10407,6 +10429,10 @@ packages: resolution: {integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==} engines: {node: '>=10'} + is-retry-allowed@3.0.0: + resolution: {integrity: sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==} + engines: {node: '>=12'} + is-set@2.0.3: resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} @@ -11731,6 +11757,9 @@ packages: radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -12504,6 +12533,9 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -12848,6 +12880,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + urijs@1.19.11: + resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} + url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} @@ -15544,9 +15579,9 @@ snapshots: dependencies: react: 19.2.3 - '@hono/node-server@1.19.0(hono@4.9.2)': + '@hono/node-server@1.19.0(hono@4.10.7)': dependencies: - hono: 4.9.2 + hono: 4.10.7 '@hpke/chacha20poly1305@1.7.1': dependencies: @@ -20788,6 +20823,31 @@ snapshots: '@stablelib/wipe@1.0.1': {} + '@stellar/js-xdr@3.1.2': {} + + '@stellar/stellar-base@14.0.4': + dependencies: + '@noble/curves': 1.9.7 + '@stellar/js-xdr': 3.1.2 + base32.js: 0.1.0 + bignumber.js: 9.3.1 + buffer: 6.0.3 + sha.js: 2.4.12 + + '@stellar/stellar-sdk@14.5.0': + dependencies: + '@stellar/stellar-base': 14.0.4 + axios: 1.13.4 + bignumber.js: 9.3.1 + commander: 14.0.2 + eventsource: 2.0.2 + feaxios: 0.0.23 + randombytes: 2.1.0 + toml: 3.0.0 + urijs: 1.19.11 + transitivePeerDependencies: + - debug + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.3)': dependencies: '@babel/core': 7.28.3 @@ -23870,6 +23930,14 @@ snapshots: transitivePeerDependencies: - debug + axios@1.13.4: + dependencies: + follow-redirects: 1.15.11 + 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.3): @@ -23906,6 +23974,8 @@ snapshots: base-x@5.0.1: {} + base32.js@0.1.0: {} + base64-js@1.5.1: {} big.js@6.2.2: {} @@ -25116,7 +25186,7 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.40.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -25568,6 +25638,8 @@ snapshots: eventsource-parser@3.0.5: {} + eventsource@2.0.2: {} + eventsource@3.0.7: dependencies: eventsource-parser: 3.0.5 @@ -25728,6 +25800,10 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + feaxios@0.0.23: + dependencies: + is-retry-allowed: 3.0.0 + fecha@4.2.3: {} fetch-blob@3.2.0: @@ -26099,8 +26175,6 @@ snapshots: hono@4.10.7: {} - hono@4.9.2: {} - hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 @@ -26344,6 +26418,8 @@ snapshots: is-retry-allowed@2.2.0: {} + is-retry-allowed@3.0.0: {} + is-set@2.0.3: {} is-shared-array-buffer@1.0.4: @@ -27126,6 +27202,21 @@ snapshots: dependencies: mimic-fn: 2.1.0 + openai@4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): + dependencies: + '@types/node': 18.19.123 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0(encoding@0.1.13) + optionalDependencies: + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + zod: 3.25.76 + transitivePeerDependencies: + - encoding + openai@4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): dependencies: '@types/node': 18.19.123 @@ -27911,6 +28002,10 @@ snapshots: radix3@1.1.2: {} + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + range-parser@1.2.1: {} raw-body@2.5.2: @@ -28877,6 +28972,8 @@ snapshots: toidentifier@1.0.1: {} + toml@3.0.0: {} + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -29192,6 +29289,8 @@ snapshots: dependencies: punycode: 2.3.1 + urijs@1.19.11: {} + url-parse@1.5.10: dependencies: querystringify: 2.2.0 diff --git a/examples/typescript/servers/advanced/.env-local b/examples/typescript/servers/advanced/.env-local index 9ec8cdc305..e16c5a2761 100644 --- a/examples/typescript/servers/advanced/.env-local +++ b/examples/typescript/servers/advanced/.env-local @@ -1,2 +1,4 @@ EVM_ADDRESS= +SVM_ADDRESS= +STELLAR_ADDRESS= FACILITATOR_URL= \ No newline at end of file diff --git a/examples/typescript/servers/advanced/README.md b/examples/typescript/servers/advanced/README.md index 8372d128a8..17d98b2314 100644 --- a/examples/typescript/servers/advanced/README.md +++ b/examples/typescript/servers/advanced/README.md @@ -5,10 +5,12 @@ Express.js server demonstrating advanced x402 patterns including dynamic pricing ```typescript import { paymentMiddleware, x402ResourceServer } from "@x402/express"; import { ExactEvmScheme } from "@x402/evm/exact/server"; +import { ExactStellarScheme } from "@x402/stellar/exact/server"; import { HTTPFacilitatorClient } from "@x402/core/server"; const resourceServer = new x402ResourceServer(new HTTPFacilitatorClient({ url: facilitatorUrl })) .register("eip155:84532", new ExactEvmScheme()) + .register("stellar:*", new ExactStellarScheme()) .onBeforeVerify(async ctx => console.log("Verifying payment...")) .onAfterSettle(async ctx => console.log("Settled:", ctx.result.transaction)); @@ -23,6 +25,14 @@ app.use( payTo: evmAddress, }, }, + "GET /weather-stellar": { + accepts: { + scheme: "exact", + price: ctx => (ctx.adapter.getQueryParam?.("tier") === "premium" ? "$0.01" : "$0.001"), + network: "stellar:*", + payTo: stellarAddress, + }, + }, }, resourceServer, ), @@ -48,6 +58,7 @@ and fill required environment variables: - `FACILITATOR_URL` - Facilitator endpoint URL - `EVM_ADDRESS` - Ethereum address to receive payments +- `STELLAR_ADDRESS` - Stellar public address (starts with `G`) to receive payments 2. Install and build all packages from the typescript examples root: @@ -63,6 +74,16 @@ cd servers/advanced pnpm dev ``` +### Account Setup Instructions + +#### Stellar Testnet + +Stellar accounts need to be created and funded with both XLM and USDC. Instructions: + +1. Go to [Stellar Laboratory](https://lab.stellar.org/account/create) ➑️ Generate keypair ➑️ Fund account with Friendbot, then copy the `Secret` and `Public` keys so you can use them. +2. Add USDC trustline (required to transact USDC): go to [Fund Account](https://lab.stellar.org/account/fund) ➑️ Paste your `Public Key` ➑️ Add USDC Trustline ➑️ paste your `Secret key` ➑️ Sign transaction ➑️ Add Trustline. +3. Get testnet USDC from [Circle Faucet](https://faucet.circle.com/) (select Stellar network). + ## Available Examples Each example demonstrates a specific advanced pattern: diff --git a/examples/typescript/servers/advanced/all_networks.ts b/examples/typescript/servers/advanced/all_networks.ts index e3b474e236..8d7f639642 100644 --- a/examples/typescript/servers/advanced/all_networks.ts +++ b/examples/typescript/servers/advanced/all_networks.ts @@ -5,7 +5,7 @@ * optional chain configuration via environment variables. * * New chain support should be added here in alphabetic order by network prefix - * (e.g., "eip155" before "solana"). + * (e.g., "eip155" before "solana" before "stellar"). */ import { config } from "dotenv"; @@ -13,6 +13,7 @@ import express from "express"; import { paymentMiddleware, x402ResourceServer } from "@x402/express"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { ExactSvmScheme } from "@x402/svm/exact/server"; +import { ExactStellarScheme } from "@x402/stellar/exact/server"; import { HTTPFacilitatorClient } from "@x402/core/server"; config(); @@ -20,10 +21,11 @@ config(); // Configuration - optional per network const evmAddress = process.env.EVM_ADDRESS as `0x${string}` | undefined; const svmAddress = process.env.SVM_ADDRESS as string | undefined; +const stellarAddress = process.env.STELLAR_ADDRESS as string | undefined; // Validate at least one address is provided -if (!evmAddress && !svmAddress) { - console.error("❌ At least one of EVM_ADDRESS or SVM_ADDRESS is required"); +if (!evmAddress && !svmAddress && !stellarAddress) { + console.error("❌ At least one of EVM_ADDRESS, SVM_ADDRESS, or STELLAR_ADDRESS is required"); process.exit(1); } @@ -36,6 +38,7 @@ if (!facilitatorUrl) { // Network configuration const EVM_NETWORK = "eip155:84532" as const; // Base Sepolia const SVM_NETWORK = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" as const; // Solana Devnet +const STELLAR_NETWORK = "stellar:testnet" as const; // Stellar Testnet // Build accepts array dynamically based on configured addresses const accepts: Array<{ @@ -60,6 +63,14 @@ if (svmAddress) { payTo: svmAddress, }); } +if (stellarAddress) { + accepts.push({ + scheme: "exact", + price: "$0.001", + network: STELLAR_NETWORK, + payTo: stellarAddress, + }); +} // Create facilitator client const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); @@ -72,6 +83,9 @@ if (evmAddress) { if (svmAddress) { server.register(SVM_NETWORK, new ExactSvmScheme()); } +if (stellarAddress) { + server.register(STELLAR_NETWORK, new ExactStellarScheme()); +} // Create Express app const app = express(); @@ -115,6 +129,9 @@ app.listen(port, () => { if (svmAddress) { console.log(` SVM: ${svmAddress} on ${SVM_NETWORK}`); } + if (stellarAddress) { + console.log(` Stellar: ${stellarAddress} on ${STELLAR_NETWORK}`); + } console.log(` Facilitator: ${facilitatorUrl}`); console.log(); }); diff --git a/examples/typescript/servers/advanced/package.json b/examples/typescript/servers/advanced/package.json index 140935e5c6..a7fa9475ae 100644 --- a/examples/typescript/servers/advanced/package.json +++ b/examples/typescript/servers/advanced/package.json @@ -23,6 +23,7 @@ "@x402/express": "workspace:*", "@x402/evm": "workspace:*", "@x402/svm": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/extensions": "workspace:*" }, "devDependencies": { diff --git a/typescript/packages/mechanisms/evm/README.md b/typescript/packages/mechanisms/evm/README.md index 6c9fff9141..9eb90f7337 100644 --- a/typescript/packages/mechanisms/evm/README.md +++ b/typescript/packages/mechanisms/evm/README.md @@ -181,3 +181,4 @@ npm run format - `@x402/core` - Core protocol types and client - `@x402/fetch` - HTTP wrapper with automatic payment handling - `@x402/svm` - Solana/SVM implementation +- `@x402/stellar` - Stellar implementation diff --git a/typescript/packages/mechanisms/stellar/.prettierignore b/typescript/packages/mechanisms/stellar/.prettierignore new file mode 100644 index 0000000000..9fd1bade5d --- /dev/null +++ b/typescript/packages/mechanisms/stellar/.prettierignore @@ -0,0 +1,7 @@ +docs/ +dist/ +node_modules/ +coverage/ +.github/ +**/**/*.json +*.md diff --git a/typescript/packages/mechanisms/stellar/.prettierrc b/typescript/packages/mechanisms/stellar/.prettierrc new file mode 100644 index 0000000000..ffb416b74b --- /dev/null +++ b/typescript/packages/mechanisms/stellar/.prettierrc @@ -0,0 +1,11 @@ +{ + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "avoid", + "printWidth": 100, + "proseWrap": "never" +} diff --git a/typescript/packages/mechanisms/stellar/CHANGELOG.md b/typescript/packages/mechanisms/stellar/CHANGELOG.md new file mode 100644 index 0000000000..92f159f6dd --- /dev/null +++ b/typescript/packages/mechanisms/stellar/CHANGELOG.md @@ -0,0 +1,5 @@ +# @x402/stellar Changelog + +## 2.5.0 + +- Implement x402 v2 protocol support for the Stellar mechanism (exact scheme). diff --git a/typescript/packages/mechanisms/stellar/README.md b/typescript/packages/mechanisms/stellar/README.md new file mode 100644 index 0000000000..efffd237f6 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/README.md @@ -0,0 +1,168 @@ +# @x402/stellar + +Stellar implementation of the x402 payment protocol using the **Exact** payment scheme with [Soroban token](https://stellar.org/protocol/sep-41) transfers. + +## Installation + +```bash +npm install @x402/stellar +``` + +## Overview + +This package provides three main components for handling x402 payments on Stellar: + +- **Client** - For applications that need to make payments (have wallets/signers) +- **Facilitator** - For payment processors that verify and execute on-chain transactions +- **Server** - For resource servers that accept payments and build payment requirements + +**Key Differences from EVM/SVM:** + +- **Ledger-based expiration** (not timestamps) - default ~12 ledgers β‰ˆ 60 seconds +- **Auth entry signing** - client signs authorization entries only, facilitator rebuilds and submits transaction +- **Mainnet requires custom RPC URL** (see [Stellar RPC Providers](https://developers.stellar.org/docs/data/apis/rpc/providers)) + +## Package Exports + +### Main Package (`@x402/stellar`) + +**V2 Protocol Support** - x402 v2 protocol with CAIP-2 network identifiers + +**Client:** + +- `ExactStellarScheme` - Client implementation using Soroban token transfers +- `createEd25519Signer(privateKey, defaultNetwork)` - Creates a Stellar signer from private key that implements `SignAuthEntry` and `SignTransaction` according to [SEP-43](https://stellar.org/protocol/sep-43) +- `ClientStellarSigner` - TypeScript type for client signers + +**Facilitator:** + +- `ExactStellarScheme` - Facilitator for payment verification and settlement +- `FacilitatorStellarSigner` - TypeScript type for facilitator signers + +> [!NOTE] +> Facilitators currently always sponsor transaction fees (`areFeesSponsored: true`). A non-sponsored flow will be added later. See [spec](../../../specs/schemes/exact/scheme_exact_stellar.md#paymentrequirements-for-exact) for details. + +**Server:** + +- `ExactStellarScheme` - Server for building payment requirements + +**Utilities:** + +- `getRpcUrl(network, config?)` - Get RPC URL for a network +- `getRpcClient(network, config?)` - Create Soroban RPC client +- `getNetworkPassphrase(network)` - Get network passphrase +- `validateStellarDestinationAddress(address)` - Validate destination address +- `validateStellarAssetAddress(address)` - Validate asset/contract address +- `convertToTokenAmount(amount, decimals)` - Convert decimal to token units +- `getUsdcAddress(network)` - Get USDC contract address + +**Constants:** + +- `STELLAR_PUBNET_CAIP2` = `"stellar:pubnet"` +- `STELLAR_TESTNET_CAIP2` = `"stellar:testnet"` +- `USDC_PUBNET_ADDRESS` - USDC contract on mainnet +- `USDC_TESTNET_ADDRESS` - USDC contract on testnet +- `DEFAULT_TOKEN_DECIMALS` = `7` + +### Subpath Exports + +- `@x402/stellar/exact/client` - `ExactStellarScheme` (client) +- `@x402/stellar/exact/server` - `ExactStellarScheme` (server) +- `@x402/stellar/exact/facilitator` - `ExactStellarScheme` (facilitator) + +## Supported Networks + +**V2 Networks** (via [CAIP-28](https://namespaces.chainagnostic.org/stellar/caip2)): + +- `stellar:pubnet` - Mainnet (requires custom RPC URL) +- `stellar:testnet` - Testnet (default: [https://soroban-testnet.stellar.org](https://soroban-testnet.stellar.org)) +- `stellar:*` - Wildcard (matches all Stellar networks) + +## Asset Support + +Supports Soroban tokens implementing [SEP-41](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0041.md): + +- Any Soroban token contract with `transfer(from, to, amount)` function +- Default asset is USDC (primary, 7 decimals) + +> **For detailed protocol flow, transaction structure, and verification rules, see the [Exact Scheme Specification](../../../specs/schemes/exact/scheme_exact_stellar.md).** + +## Usage Patterns + +### 1. Direct Registration (Recommended) + +```typescript +import { x402Client } from "@x402/core/client"; +import { createEd25519Signer } from "@x402/stellar"; +import { ExactStellarScheme } from "@x402/stellar/exact/client"; + +const signer = createEd25519Signer(privateKey, "stellar:testnet"); +const client = new x402Client().register("stellar:*", new ExactStellarScheme(signer)); +``` + +### 2. Custom Configuration + +```typescript +// Client with custom RPC +const client = new x402Client().register( + "stellar:*", + new ExactStellarScheme(signer, { url: "https://custom-rpc.example.com" }), +); + +// Server with custom money parser +const scheme = new ExactStellarScheme().registerMoneyParser(async (amount, network) => ({ + amount: customConvert(amount), + asset: "TOKEN_ADDRESS", + extra: {}, +})); + +// Facilitator +const facilitator = new x402Facilitator().register( + "stellar:testnet", + new ExactStellarScheme([signer]), +); +``` + +## Development + +```bash +# Build +pnpm build + +# Test +pnpm test + +# Integration tests +pnpm test:integration + +# Lint & Format +pnpm lint +pnpm format +``` + +## Integration Tests + +Integration tests require four funded Stellar testnet accounts: + +```bash +CLIENT_PRIVATE_KEY=S... # Client's secret key +FACILITATOR_PRIVATE_KEY=S... # Facilitator's secret key +FACILITATOR_ADDRESS=G... # Facilitator's public address +RESOURCE_SERVER_ADDRESS=G... # Resource server's public address +``` + +### Stellar Testnet Account Setup + +1. Go to [Stellar Laboratory](https://lab.stellar.org/account/create) ➑️ Generate keypair ➑️ Fund account with Friendbot, then copy the `Secret` and `Public` keys so you can use them. +2. Add USDC trustline (required for client and resource server): go to [Fund Account](https://lab.stellar.org/account/fund) ➑️ Paste your `Public Key` ➑️ Add USDC Trustline ➑️ paste your `Secret key` ➑️ Sign transaction ➑️ Add Trustline. +3. Get testnet USDC from [Circle Faucet](https://faucet.circle.com/) (select Stellar network). + +> [!NOTE] +> The facilitator account only needs XLM (step 1). Client and resource server accounts need all three steps. + +## Related Packages + +- `@x402/core` - Core protocol types and client +- `@x402/fetch` - HTTP wrapper with automatic payment handling +- `@x402/evm` - EVM/Ethereum implementation +- `@x402/svm` - Solana/SVM implementation diff --git a/typescript/packages/mechanisms/stellar/eslint.config.js b/typescript/packages/mechanisms/stellar/eslint.config.js new file mode 100644 index 0000000000..8aecb38e3b --- /dev/null +++ b/typescript/packages/mechanisms/stellar/eslint.config.js @@ -0,0 +1,131 @@ +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", "**/*.tsx"], + ignores: ["**/*.test.ts", "test/**/*"], + languageOptions: { + parser: tsParser, + sourceType: "module", + ecmaVersion: 2020, + globals: { + process: "readonly", + __dirname: "readonly", + module: "readonly", + require: "readonly", + Buffer: "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", + "import/order": [ + "error", + { + groups: [ + "builtin", + "external", + "internal", + ["parent", "sibling"], + "index", + "object", + "type", + ], + "newlines-between": "never", + alphabetize: { + order: "asc", + caseInsensitive: true, + }, + }, + ], + "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"], + }, + }, + { + files: ["**/*.test.ts", "test/**/*"], + languageOptions: { + parser: tsParser, + sourceType: "module", + ecmaVersion: 2020, + }, + plugins: { + "@typescript-eslint": ts, + prettier: prettier, + import: importPlugin, + }, + rules: { + "import/first": "error", + "import/order": [ + "error", + { + groups: [ + "builtin", + "external", + "internal", + ["parent", "sibling"], + "index", + "object", + "type", + ], + "newlines-between": "never", + alphabetize: { + order: "asc", + caseInsensitive: true, + }, + }, + ], + "prettier/prettier": "error", + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/member-ordering": "off", + }, + }, +]; diff --git a/typescript/packages/mechanisms/stellar/package.json b/typescript/packages/mechanisms/stellar/package.json new file mode 100644 index 0000000000..24adee8547 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/package.json @@ -0,0 +1,97 @@ +{ + "name": "@x402/stellar", + "version": "2.5.0", + "main": "./dist/cjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/cjs/index.d.ts", + "scripts": { + "start": "tsx --env-file=.env index.ts", + "build": "tsup", + "test": "vitest run", + "test:integration": "vitest run --config vitest.integration.config.ts", + "test:all": "vitest run --config vitest.config.ts && vitest run --config vitest.integration.config.ts", + "test:watch": "vitest", + "watch": "tsc --watch", + "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" + }, + "keywords": [ + "x402", + "payment", + "protocol", + "stellar", + "soroban" + ], + "license": "Apache-2.0", + "author": "Coinbase Inc.", + "repository": "https://github.com/coinbase/x402", + "description": "x402 Payment Protocol Stellar Implementation", + "devDependencies": { + "@eslint/js": "^9.24.0", + "@types/node": "^22.13.4", + "@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": "^8.4.0", + "tsx": "^4.19.2", + "typescript": "^5.7.3", + "vite": "^6.2.6", + "vite-tsconfig-paths": "^5.1.4", + "vitest": "^3.0.5" + }, + "dependencies": { + "@stellar/stellar-sdk": "^14.4.2", + "@x402/core": "workspace:*" + }, + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.mts", + "default": "./dist/esm/index.mjs" + }, + "require": { + "types": "./dist/cjs/index.d.ts", + "default": "./dist/cjs/index.js" + } + }, + "./exact/client": { + "import": { + "types": "./dist/esm/exact/client/index.d.mts", + "default": "./dist/esm/exact/client/index.mjs" + }, + "require": { + "types": "./dist/cjs/exact/client/index.d.ts", + "default": "./dist/cjs/exact/client/index.js" + } + }, + "./exact/server": { + "import": { + "types": "./dist/esm/exact/server/index.d.mts", + "default": "./dist/esm/exact/server/index.mjs" + }, + "require": { + "types": "./dist/cjs/exact/server/index.d.ts", + "default": "./dist/cjs/exact/server/index.js" + } + }, + "./exact/facilitator": { + "import": { + "types": "./dist/esm/exact/facilitator/index.d.mts", + "default": "./dist/esm/exact/facilitator/index.mjs" + }, + "require": { + "types": "./dist/cjs/exact/facilitator/index.d.ts", + "default": "./dist/cjs/exact/facilitator/index.js" + } + } + }, + "files": [ + "dist" + ] +} diff --git a/typescript/packages/mechanisms/stellar/src/constants.ts b/typescript/packages/mechanisms/stellar/src/constants.ts new file mode 100644 index 0000000000..0afcc7ea3b --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/constants.ts @@ -0,0 +1,33 @@ +/** + * CAIP-2 network identifiers for Stellar (V2) + */ +export const STELLAR_PUBNET_CAIP2 = "stellar:pubnet"; +export const STELLAR_TESTNET_CAIP2 = "stellar:testnet"; +export const STELLAR_WILDCARD_CAIP2 = "stellar:*"; + +/** + * Default testnet RPC URL + */ +export const DEFAULT_TESTNET_RPC_URL = "https://soroban-testnet.stellar.org"; + +/** + * Stellar validation regex for destination and asset addresses + */ +export const STELLAR_DESTINATION_ADDRESS_REGEX = /^(?:[GC][ABCD][A-Z2-7]{54}|M[ABCD][A-Z2-7]{67})$/; // Stellar address: G-account (56 chars), C-account (56 chars), or M-account (69 chars, muxed) +export const STELLAR_ASSET_ADDRESS_REGEX = /^(?:[C][ABCD][A-Z2-7]{54})$/; // Stellar token contract address: C-account (56 chars) + +/** + * USDC contract addresses (default stablecoin) + */ +export const USDC_PUBNET_ADDRESS = "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75"; +export const USDC_TESTNET_ADDRESS = "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"; + +export const STELLAR_NETWORK_TO_PASSPHRASE: ReadonlyMap = new Map([ + [STELLAR_PUBNET_CAIP2, "Public Global Stellar Network ; September 2015"], + [STELLAR_TESTNET_CAIP2, "Test SDF Network ; September 2015"], +]); + +/** + * Default token decimals + */ +export const DEFAULT_TOKEN_DECIMALS = 7; diff --git a/typescript/packages/mechanisms/stellar/src/exact/client/index.ts b/typescript/packages/mechanisms/stellar/src/exact/client/index.ts new file mode 100644 index 0000000000..9e91e067eb --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/exact/client/index.ts @@ -0,0 +1 @@ +export { ExactStellarScheme } from "./scheme"; diff --git a/typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts b/typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts new file mode 100644 index 0000000000..0e78c31d10 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts @@ -0,0 +1,151 @@ +import { nativeToScVal, TransactionBuilder, contract } from "@stellar/stellar-sdk"; +import { Api } from "@stellar/stellar-sdk/rpc"; +import { handleSimulationResult } from "../../shared"; +import { + getEstimatedLedgerCloseTimeSeconds, + getNetworkPassphrase, + getRpcClient, + getRpcUrl, + isStellarNetwork, + RpcConfig, + validateStellarAssetAddress, + validateStellarDestinationAddress, +} from "../../utils"; +import type { ClientStellarSigner } from "../../signer"; +import type { PaymentPayload, PaymentRequirements, SchemeNetworkClient } from "@x402/core/types"; + +/** Base fee in stroops (0.001 XLM) used when building the final tx fee after auth signing. */ +const DEFAULT_BASE_FEE_STROOPS = 10_000; + +/** + * Stellar client implementation for the Exact payment scheme. + */ +export class ExactStellarScheme implements SchemeNetworkClient { + readonly scheme = "exact"; + + /** + * Creates a new ExactStellarScheme instance. + * + * @param signer - The Stellar signer for client operations + * @param rpcConfig - Optional configuration with custom RPC URL + * @returns ExactStellarScheme instance + */ + constructor( + private readonly signer: ClientStellarSigner, + private readonly rpcConfig?: RpcConfig, + ) {} + + /** + * Creates a payment payload for the Exact scheme. + * + * @param x402Version - The x402 protocol version + * @param paymentRequirements - The payment requirements + * @returns Promise resolving to a payment payload + */ + async createPaymentPayload( + x402Version: number, + paymentRequirements: PaymentRequirements, + ): Promise> { + try { + this.validateCreateAndSignPaymentInput(paymentRequirements); + } catch (error) { + throw new Error(`Invalid input parameters for creating Stellar payment, cause: ${error}`); + } + + const sourcePublicKey = this.signer.address; + const { network, payTo, asset, amount, extra, maxTimeoutSeconds } = paymentRequirements; + const networkPassphrase = getNetworkPassphrase(network); + const rpcUrl = getRpcUrl(network, this.rpcConfig); + + if (!extra.areFeesSponsored) { + throw new Error(`Exact scheme requires areFeesSponsored to be true`); + } + + // Fetch current ledger and calculate maxLedger (uses RPC getLedgers for close time) + const rpcServer = getRpcClient(network, this.rpcConfig); + const latestLedger = await rpcServer.getLatestLedger(); + const currentLedger = latestLedger.sequence; + const estimatedLedgerSeconds = await getEstimatedLedgerCloseTimeSeconds(rpcServer); + const maxLedger = currentLedger + Math.ceil(maxTimeoutSeconds / estimatedLedgerSeconds); + + const tx = await contract.AssembledTransaction.build({ + contractId: asset, + method: "transfer", + args: [ + // SEP-41 spec: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0041.md#interface + nativeToScVal(sourcePublicKey, { type: "address" }), // from + nativeToScVal(payTo, { type: "address" }), // to + nativeToScVal(amount, { type: "i128" }), // amount + ], + networkPassphrase, + rpcUrl, + parseResultXdr: result => result, + }); + handleSimulationResult(tx.simulation); + + let missingSigners = tx.needsNonInvokerSigningBy(); + if (!missingSigners.includes(sourcePublicKey) || missingSigners.length > 1) { + throw new Error( + `Expected to sign with [${sourcePublicKey}], but got [${missingSigners.join(", ")}]`, + ); + } + await tx.signAuthEntries({ + address: sourcePublicKey, + signAuthEntry: this.signer.signAuthEntry, + expiration: maxLedger, + }); + + await tx.simulate(); + handleSimulationResult(tx.simulation); + + missingSigners = tx.needsNonInvokerSigningBy(); + if (missingSigners.length > 0) { + throw new Error(`unexpected signer(s) required: [${missingSigners.join(", ")}]`); + } + + const finalTx = + tx.simulation && Api.isSimulationSuccess(tx.simulation) + ? TransactionBuilder.cloneFrom(tx.built!, { + fee: (DEFAULT_BASE_FEE_STROOPS + parseInt(tx.simulation.minResourceFee, 10)).toString(), + sorobanData: tx.simulationData.transactionData, + networkPassphrase, + }).build() + : tx.built!; + + return { + x402Version, + payload: { + transaction: finalTx.toXDR(), + }, + }; + } + + /** + * Validates the input parameters for the createAndSignPayment function. + * + * @param paymentRequirements - Payment requirements + * @throws Error if validation fails + */ + private validateCreateAndSignPaymentInput(paymentRequirements: PaymentRequirements): void { + const { scheme, network, payTo, asset, amount } = paymentRequirements; + if (typeof amount !== "string" || !Number.isInteger(Number(amount)) || Number(amount) <= 0) { + throw new Error(`Invalid amount: ${amount}. Amount must be a positive integer.`); + } + + if (scheme !== "exact") { + throw new Error(`Unsupported scheme: ${scheme}`); + } + + if (!isStellarNetwork(network)) { + throw new Error(`Unsupported Stellar network: ${network}`); + } + + if (!validateStellarDestinationAddress(payTo)) { + throw new Error(`Invalid Stellar destination address: ${payTo}`); + } + + if (!validateStellarAssetAddress(asset)) { + throw new Error(`Invalid Stellar asset address: ${asset}`); + } + } +} diff --git a/typescript/packages/mechanisms/stellar/src/exact/facilitator/index.ts b/typescript/packages/mechanisms/stellar/src/exact/facilitator/index.ts new file mode 100644 index 0000000000..9e91e067eb --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/exact/facilitator/index.ts @@ -0,0 +1 @@ +export { ExactStellarScheme } from "./scheme"; diff --git a/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts new file mode 100644 index 0000000000..554302f430 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts @@ -0,0 +1,761 @@ +import { + scValToNative, + Transaction, + FeeBumpTransaction, + Address, + Operation, + xdr, + rpc, + TransactionBuilder, +} from "@stellar/stellar-sdk"; +import { Api } from "@stellar/stellar-sdk/rpc"; +import { STELLAR_WILDCARD_CAIP2 } from "../../constants"; +import { gatherAuthEntrySignatureStatus } from "../../shared"; +import { ExactStellarPayloadV2 } from "../../types"; +import { + getEstimatedLedgerCloseTimeSeconds, + getRpcClient, + getNetworkPassphrase, + isStellarNetwork, + RpcConfig, +} from "../../utils"; +import type { FacilitatorStellarSigner } from "../../signer"; +import type { + Network, + PaymentPayload, + PaymentRequirements, + SchemeNetworkFacilitator, + SettleResponse, + VerifyResponse, +} from "@x402/core/types"; + +const DEFAULT_TIMEOUT_SECONDS = 60; +const SUPPORTED_X402_VERSION = 2; +const DEFAULT_MAX_TRANSACTION_FEE_STROOPS = 50_000; +const SIGNATURE_EXPIRATION_LEDGER_TOLERANCE = 2; + +/** + * Returns a round-robin selector for choosing which signer to use. + * Each invocation returns a new selector with its own counter. + * + * @returns A function that selects the next address from the given array on each call + */ +const roundRobinSelectSigner = (): ((addresses: readonly string[]) => string) => { + let index = 0; + return addrs => addrs[index++ % addrs.length]; +}; + +/** + * Helper to create a `VerifyResponse` with `isValid: false`. + * + * @param reason - The error reason code + * @param payer - Optional payer address + * @returns a `VerifyResponse` with `isValid: false` and the provided reason and (optional) payer + */ +export function invalidVerifyResponse(reason: string, payer?: string): VerifyResponse { + return { isValid: false, invalidReason: reason, payer }; +} + +/** + * Helper to create a `VerifyResponse` with `isValid: true`. + * + * @param payer - The payer address + * @returns a `VerifyResponse` with `isValid: true` and the provided payer + */ +export function validVerifyResponse(payer: string): VerifyResponse { + return { isValid: true, payer }; +} + +/** + * Stellar facilitator implementation for the Exact payment scheme. + */ +export class ExactStellarScheme implements SchemeNetworkFacilitator { + readonly scheme = "exact"; + readonly caipFamily = STELLAR_WILDCARD_CAIP2; + + public readonly signingAddresses: ReadonlySet; + public readonly areFeesSponsored: boolean; + public readonly rpcConfig?: RpcConfig; + public readonly maxTransactionFeeStroops: number; + public readonly feeBumpSigner?: FacilitatorStellarSigner; + private readonly signerMap: Map; + private readonly selectSigner: (addresses: readonly string[]) => string; + + /** + * Creates a new ExactStellarScheme instance. + * + * @param signers - One or more Stellar signers managed by the facilitator for settlement + * @param options - Configuration options + * @param options.rpcConfig - Optional RPC configuration with custom RPC URL + * @param options.areFeesSponsored - Indicates if fees are sponsored (default: true) + * @param options.maxTransactionFeeStroops - Maximum fee in stroops the facilitator will pay (default: 50_000) + * @param options.selectSigner - Callback to select which signer to use (default: round-robin) + * @param options.feeBumpSigner - Optional signer used as fee source in a fee bump transaction wrapper. + * When provided, settle() wraps the inner transaction (signed by the selected signer) in a + * FeeBumpTransaction where the feeBumpSigner pays the fees, decoupling fee payment from sequence number management. + * @returns ExactStellarScheme instance + */ + constructor( + signers: FacilitatorStellarSigner[], + { + rpcConfig, + areFeesSponsored = true, + maxTransactionFeeStroops = DEFAULT_MAX_TRANSACTION_FEE_STROOPS, + selectSigner = roundRobinSelectSigner(), + feeBumpSigner, + }: { + /** Optional RPC configuration with custom RPC URL */ + rpcConfig?: RpcConfig; + /** Indicates if fees are sponsored (default: true) */ + areFeesSponsored?: boolean; + /** Maximum fee in stroops the facilitator will pay (default: 50_000) */ + maxTransactionFeeStroops?: number; + /** Optional callback to select which signer to use. Receives addresses array, returns selected address. Defaults to round-robin. */ + selectSigner?: (addresses: readonly string[]) => string; + /** Optional signer used as fee source in a fee bump transaction wrapper. Decouples fee payment from sequence number management. */ + feeBumpSigner?: FacilitatorStellarSigner; + } = {}, + ) { + // Validate signers and store their data + if (!signers || signers.length === 0) { + throw new Error("At least one signer is required"); + } + this.signerMap = new Map(signers.map(s => [s.address, s])); + this.signingAddresses = new Set(this.signerMap.keys()); + + // Apply configuration options (with defaults) + this.rpcConfig = rpcConfig; + this.areFeesSponsored = areFeesSponsored ?? true; + this.maxTransactionFeeStroops = maxTransactionFeeStroops ?? DEFAULT_MAX_TRANSACTION_FEE_STROOPS; + this.selectSigner = selectSigner ?? roundRobinSelectSigner(); + this.feeBumpSigner = feeBumpSigner; + } + + /** + * Get mechanism-specific extra data for the supported kinds endpoint. + * For Stellar, returns `areFeesSponsored` indicating to clients if they can expect fees to be sponsored. + * As of now, the spec only supports `areFeesSponsored: true`. + * + * @param _ - The network identifier (unused, offset is network-agnostic) + * @returns Extra data with the `areFeesSponsored` flag + */ + getExtra(_: Network): Record | undefined { + return { + areFeesSponsored: this.areFeesSponsored, + }; + } + + /** + * Get signer addresses used by this facilitator. + * For Stellar, returns all facilitator addresses. + * + * @param _ - The network identifier (unused for Stellar) + * @returns Array containing all facilitator addresses + */ + getSigners(_: string): string[] { + return [...this.signingAddresses]; + } + + /** + * Verifies a payment payload. + * + * @param payload - The payment payload to verify + * @param requirements - The payment requirements + * @returns Promise resolving to verification response + */ + async verify( + payload: PaymentPayload, + requirements: PaymentRequirements, + ): Promise { + let fromAddress: string | undefined; + try { + // Step 1: Validate protocol version, scheme, and network + if (payload.x402Version !== SUPPORTED_X402_VERSION) { + return invalidVerifyResponse("invalid_x402_version"); + } + + if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { + return invalidVerifyResponse("unsupported_scheme"); + } + + if (requirements.network !== payload.accepted.network) { + return invalidVerifyResponse("network_mismatch"); + } + if (!isStellarNetwork(requirements.network)) { + return invalidVerifyResponse("invalid_network"); + } + + const networkPassphrase = getNetworkPassphrase(requirements.network); + const server = getRpcClient(requirements.network, this.rpcConfig); + + // Step 2: Parse and decode transaction + const stellarPayload = payload.payload as ExactStellarPayloadV2; + if (!stellarPayload || typeof stellarPayload.transaction !== "string") { + return invalidVerifyResponse("invalid_exact_stellar_payload_malformed"); + } + + let transaction: Transaction; + try { + transaction = new Transaction(stellarPayload.transaction, networkPassphrase); + } catch (error) { + console.error("Error parsing transaction:", error); + return invalidVerifyResponse("invalid_exact_stellar_payload_malformed"); + } + + // Step 3: Validate transaction structure + if (transaction.operations.length !== 1) { + return invalidVerifyResponse("invalid_exact_stellar_payload_wrong_operation"); + } + + const operation = transaction.operations[0]; + if (operation.type !== "invokeHostFunction") { + return invalidVerifyResponse("invalid_exact_stellar_payload_wrong_operation"); + } + + if ( + this.signingAddresses.has(operation.source ?? "") || + this.signingAddresses.has(transaction.source) + ) { + return invalidVerifyResponse("invalid_exact_stellar_payload_unsafe_tx_or_op_source"); + } + + // Step 4: Extract and validate contract invocation details + const invokeOp = operation as Operation.InvokeHostFunction; + const func = invokeOp.func; + + if (!func || func.switch().name !== "hostFunctionTypeInvokeContract") { + return invalidVerifyResponse("invalid_exact_stellar_payload_wrong_operation"); + } + + // Step 5: Validate contract address and function name + const invokeContractArgs = func.invokeContract(); + const contractAddress = Address.fromScAddress( + invokeContractArgs.contractAddress(), + ).toString(); + const functionName = invokeContractArgs.functionName().toString(); + + const args = invokeContractArgs.args(); + if (contractAddress !== requirements.asset) { + return invalidVerifyResponse("invalid_exact_stellar_payload_wrong_asset"); + } + + if (functionName !== "transfer" || args.length !== 3) { + return invalidVerifyResponse("invalid_exact_stellar_payload_wrong_function_name"); + } + + // Step 6: Extract and validate transfer arguments + fromAddress = scValToNative(args[0]) as string; + const toAddress = scValToNative(args[1]) as string; + const amount = scValToNative(args[2]) as bigint; + + if (this.signingAddresses.has(fromAddress)) { + return invalidVerifyResponse("invalid_exact_stellar_payload_facilitator_is_payer"); + } + + if (toAddress !== requirements.payTo) { + return invalidVerifyResponse("invalid_exact_stellar_payload_wrong_recipient", fromAddress); + } + + const expectedAmount = BigInt(requirements.amount); + if (amount !== expectedAmount) { + return invalidVerifyResponse("invalid_exact_stellar_payload_wrong_amount", fromAddress); + } + + // Step 7: Re-simulate to ensure transaction will succeed + const simResponse = await server.simulateTransaction(transaction); + if (!Api.isSimulationSuccess(simResponse)) { + const errorMsg = simResponse.error ? `: ${simResponse.error}` : ""; + console.error("Simulation error:", errorMsg); + return invalidVerifyResponse( + "invalid_exact_stellar_payload_simulation_failed", + fromAddress, + ); + } + + // Step 8: Validate if the resource fees are within acceptable bounds + const clientFeeStroops = parseInt(transaction.fee, 10); + const minResourceFee = parseInt(simResponse.minResourceFee, 10); + + // Fee must be at least the minimum required by simulation + if (clientFeeStroops < minResourceFee) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_fee_below_minimum", + fromAddress, + ); + } + + // Fee must not exceed the facilitator's maximum + if (clientFeeStroops > this.maxTransactionFeeStroops) { + return invalidVerifyResponse("invalid_exact_stellar_payload_fee_exceeds_maximum"); + } + + // Step 9: Validate simulation events for expected transfer only. + const eventValidation = this.validateSimulationEvents( + simResponse.events, + fromAddress, + requirements.payTo, + expectedAmount, + requirements.asset, + ); + if (eventValidation) { + return eventValidation; + } + + const latestLedger = await server.getLatestLedger(); + const currentLedger = latestLedger.sequence; + const maxTimeoutSeconds = requirements.maxTimeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS; + const estimatedLedgerSeconds = await getEstimatedLedgerCloseTimeSeconds(server); + const maxLedgerOffset = Math.ceil(maxTimeoutSeconds / estimatedLedgerSeconds); + const maxLedger = currentLedger + maxLedgerOffset; + + // Step 10: Validate auth entries (structure, credential type, expiration, facilitator safety, and signature status). + const authValidation = this.validateAuthEntries( + invokeOp, + this.signingAddresses, + fromAddress, + maxLedger, + transaction, + simResponse, + ); + if (authValidation) { + return authValidation; + } + + return validVerifyResponse(fromAddress); + } catch (error) { + console.error("Unexpected verification error:", error); + return invalidVerifyResponse("unexpected_verify_error", fromAddress); + } + } + + /** + * Settles a payment by submitting the transaction on-chain. + * + * @param payload - The payment payload to settle + * @param requirements - The payment requirements + * @returns Promise resolving to settlement response + */ + async settle( + payload: PaymentPayload, + requirements: PaymentRequirements, + ): Promise { + const server = getRpcClient(requirements.network, this.rpcConfig); + const networkPassphrase = getNetworkPassphrase(requirements.network); + let payer: string | undefined; + let txHash: string | undefined; + + try { + // Step 1: Verify payment before settlement + const verifyResult = await this.verify(payload, requirements); + + if (!verifyResult.isValid) { + return { + success: false, + network: payload.accepted.network, + transaction: "", + errorReason: verifyResult.invalidReason ?? "verification_failed", + payer: verifyResult.payer, + }; + } + + payer = verifyResult.payer!; + + // Step 2: Parse transaction envelope once to extract both transaction and Soroban data + const stellarPayload = payload.payload as ExactStellarPayloadV2; + const txEnvelope = xdr.TransactionEnvelope.fromXDR(stellarPayload.transaction, "base64"); + const transaction = new Transaction(stellarPayload.transaction, networkPassphrase); + const sorobanData = txEnvelope.v1()?.tx()?.ext()?.sorobanData() || undefined; + + // Validate Soroban data is present for Soroban transactions + if (!sorobanData) { + return { + success: false, + network: payload.accepted.network, + transaction: "", + errorReason: "invalid_exact_stellar_payload_malformed", + payer, + }; + } + + // Step 3: Extract operation + const invokeOp = transaction.operations[0] as Operation.InvokeHostFunction; + + // Step 4: Rebuild transaction with facilitator as source and facilitator-chosen fee + const signer = this.signerMap.get(this.selectSigner([...this.signingAddresses])); + if (!signer) { + return { + success: false, + network: payload.accepted.network, + transaction: "", + errorReason: "settle_exact_stellar_signer_selection_failed", + payer, + }; + } + const facilitatorAccount = await server.getAccount(signer.address); + + // Use the minimum of the client's fee and the maximum cap + const clientFeeStroops = parseInt(transaction.fee, 10); + const maxFeeStroops = Math.min(clientFeeStroops, this.maxTransactionFeeStroops); + + const rebuiltTx = new TransactionBuilder(facilitatorAccount, { + fee: maxFeeStroops.toString(), + networkPassphrase, + ledgerbounds: transaction.ledgerBounds, + memo: transaction.memo, + minAccountSequence: transaction.minAccountSequence, + minAccountSequenceAge: transaction.minAccountSequenceAge, + minAccountSequenceLedgerGap: transaction.minAccountSequenceLedgerGap, + extraSigners: transaction.extraSigners, + sorobanData, + }) + .setTimeout(requirements.maxTimeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS) + .addOperation(Operation.invokeHostFunction(invokeOp)) + .build(); + + // Step 5: Sign inner transaction with the selected signer's key + const { signedTxXdr, error: signError } = await signer.signTransaction(rebuiltTx.toXDR(), { + networkPassphrase, + }); + + if (signError) { + return { + success: false, + network: payload.accepted.network, + transaction: "", + errorReason: "settle_exact_stellar_transaction_signing_failed", + payer, + }; + } + + // Step 6: Optionally wrap in a fee bump transaction + let txToSubmit: Transaction | FeeBumpTransaction; + + if (this.feeBumpSigner) { + const signedInnerTx = TransactionBuilder.fromXDR( + signedTxXdr, + networkPassphrase, + ) as Transaction; + + const feeBumpTx = TransactionBuilder.buildFeeBumpTransaction( + this.feeBumpSigner.address, + maxFeeStroops.toString(), // Same as the inner transaction fee + signedInnerTx, + networkPassphrase, + ); + + const { signedTxXdr: signedFeeBumpXdr, error: feeBumpSignError } = + await this.feeBumpSigner.signTransaction(feeBumpTx.toXDR(), { networkPassphrase }); + + if (feeBumpSignError) { + return { + success: false, + network: payload.accepted.network, + transaction: "", + errorReason: "settle_exact_stellar_fee_bump_signing_failed", + payer, + }; + } + + txToSubmit = TransactionBuilder.fromXDR( + signedFeeBumpXdr, + networkPassphrase, + ) as FeeBumpTransaction; + } else { + txToSubmit = TransactionBuilder.fromXDR(signedTxXdr, networkPassphrase) as Transaction; + } + + // Step 7: Submit transaction to network + const sendResult = await server.sendTransaction(txToSubmit); + + if (sendResult.status !== "PENDING") { + return { + success: false, + network: payload.accepted.network, + transaction: "", + errorReason: "settle_exact_stellar_transaction_submission_failed", + payer, + }; + } + + // Step 8: Poll for transaction confirmation + txHash = sendResult.hash; + const maxPollAttempts = requirements.maxTimeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS; + const confirmResult = await this.pollForTransaction(server, txHash, maxPollAttempts); + + if (!confirmResult.success) { + return { + success: false, + network: payload.accepted.network, + transaction: txHash, + errorReason: "settle_exact_stellar_transaction_failed", + payer, + }; + } + + // Step 9: Return success + return { + success: true, + transaction: txHash, + network: payload.accepted.network, + payer: payer, + }; + } catch (error) { + console.error("Unexpected settlement error:", error); + return { + success: false, + network: payload.accepted.network, + transaction: txHash || "", + errorReason: "unexpected_settle_error", + payer, + }; + } + } + + /** + * Polls for transaction confirmation on Soroban. + * + * @param server - Soroban RPC server + * @param txHash - Transaction hash to poll for + * @param maxPollAttempts - Maximum number of polling attempts (default: 15) + * @param delayMs - Delay between attempts in milliseconds (default: 1000) + * @returns Result with success status + */ + private async pollForTransaction( + server: rpc.Server, + txHash: string, + maxPollAttempts = 15, + delayMs = 1000, + ): Promise<{ success: boolean }> { + for (let i = 0; i < maxPollAttempts; i++) { + try { + const txResult = await server.getTransaction(txHash); + + if (txResult.status === "SUCCESS") { + return { success: true }; + } else if (txResult.status === "FAILED") { + return { success: false }; + } + + // Transaction still pending, wait and retry + await new Promise(resolve => setTimeout(resolve, delayMs)); + } catch (error: unknown) { + if (error instanceof Error && !error.message.includes("NOT_FOUND")) { + console.warn(`Poll attempt ${i} failed:`, error); + } + await new Promise(resolve => setTimeout(resolve, delayMs)); + } + } + + // Timeout + return { success: false }; + } + + /** + * Validates simulation events for transfer correctness. + * Ensures there is exactly one token transfer event, the transfer matches the + * expected sender, recipient, amount, and asset (contract address), and the + * facilitator address is not involved in the transfer. + * + * @param events - The array of DiagnosticEvent objects from the simulation + * @param fromAddress - The payer's address + * @param toAddress - The recipient's address + * @param expectedAmount - The expected transfer amount + * @param expectedAsset - The expected token contract address + * @returns undefined if the validation succeeds, otherwise an invalid VerifyResponse + */ + private validateSimulationEvents( + events: xdr.DiagnosticEvent[], + fromAddress: string, + toAddress: string, + expectedAmount: bigint, + expectedAsset: string, + ): VerifyResponse | undefined { + // Soroban token transfer events follow the [CAP-46](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0046-06.md) format: + // Topic: ["transfer", from, to], Data: amount + const transferEvents: Array<{ + from: string; + to: string; + amount: bigint; + }> = []; + + // Parse events into + for (const diagnosticEvent of events) { + try { + const event = diagnosticEvent.event(); + + // Skip non-contract events + if (event.type().name !== "contract") { + continue; + } + + const body = event.body().v0(); + const topics = body.topics(); + + // Check if this is a transfer event (first topic is "transfer" symbol) + if (topics.length < 3) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_event_not_transfer", + fromAddress, + ); + } + + const topicType = topics[0].switch().name; + if (topicType !== "scvSymbol") { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_event_not_transfer", + fromAddress, + ); + } + + const symbol = topics[0].sym().toString(); + if (symbol !== "transfer") { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_event_not_transfer", + fromAddress, + ); + } + + const contractIdHash = event.contractId(); + if (!contractIdHash) + return invalidVerifyResponse( + "invalid_exact_stellar_payload_event_missing_contract_id", + fromAddress, + ); + const eventContractAddress = Address.fromScAddress( + xdr.ScAddress.scAddressTypeContract(contractIdHash), + ).toString(); + if (eventContractAddress !== expectedAsset) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_event_wrong_asset", + fromAddress, + ); + } + + // Extract from, to, and amount + const from = scValToNative(topics[1]) as string; + const to = scValToNative(topics[2]) as string; + const amount = scValToNative(body.data()) as bigint; + + transferEvents.push({ from, to, amount }); + } catch (error: unknown) { + if (error instanceof Error) { + console.error("Error parsing diagnostic event:", error.message); + } else { + console.error("Error parsing diagnostic event:", String(error)); + } + return invalidVerifyResponse("unexpected_verify_error", fromAddress); + } + } + + // If no transfer events are present, reject. + if (transferEvents.length === 0) { + return invalidVerifyResponse("invalid_exact_stellar_payload_no_transfer_events", fromAddress); + } + + if (transferEvents.length > 1) { + return invalidVerifyResponse("invalid_exact_stellar_payload_multiple_transfers", fromAddress); + } + + const transferEvent = transferEvents[0]; + + // Validate the transfer matches the expected sender, recipient, and amount + if (transferEvent.from !== fromAddress) { + return invalidVerifyResponse("invalid_exact_stellar_payload_event_wrong_from", fromAddress); + } + if (transferEvent.to !== toAddress) { + return invalidVerifyResponse("invalid_exact_stellar_payload_event_wrong_to", fromAddress); + } + if (transferEvent.amount !== expectedAmount) { + return invalidVerifyResponse("invalid_exact_stellar_payload_event_wrong_amount", fromAddress); + } + + return undefined; + } + + /** + * Validates authorization entries: structure, credential type, expiration, + * facilitator safety, no sub-invocations, and that the payer has signed and + * no other signatures are pending (per simulation). + * + * @param invokeOp - The invoke host function operation + * @param facilitatorAddresses - Set of all facilitator addresses + * @param fromAddress - The payer's address (for error reporting) + * @param maxLedger - The maximum allowed expiration ledger + * @param transaction - The full transaction (for signature status) + * @param simResponse - The simulation result (used to interpret auth entry signatures) + * @returns Invalid VerifyResponse when validation fails + */ + private validateAuthEntries( + invokeOp: Operation.InvokeHostFunction, + facilitatorAddresses: ReadonlySet, + fromAddress: string, + maxLedger: number, + transaction: Transaction, + simResponse: Api.SimulateTransactionSuccessResponse, + ): VerifyResponse | undefined { + if (!invokeOp.auth || invokeOp.auth.length === 0) { + return invalidVerifyResponse("invalid_exact_stellar_payload_no_auth_entries", fromAddress); + } + + for (const auth of invokeOp.auth) { + const credentialsType = auth.credentials().switch(); + + // Only address-based credentials are allowed + if (credentialsType !== xdr.SorobanCredentialsType.sorobanCredentialsAddress()) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_unsupported_credential_type", + fromAddress, + ); + } + + // Extract address from credentials + const addressCredentials = auth.credentials().address(); + const authAddress = Address.fromScAddress(addressCredentials.address()).toString(); + + // Facilitator must not appear in auth entries + if (facilitatorAddresses.has(authAddress)) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_facilitator_in_auth", + fromAddress, + ); + } + + // Check signature expiration is within allowed window (with ledger tolerance for RPC skew) + const expirationLedger = addressCredentials.signatureExpirationLedger(); + if (expirationLedger > maxLedger + SIGNATURE_EXPIRATION_LEDGER_TOLERANCE) { + return invalidVerifyResponse( + "invalid_exact_stellar_signature_expiration_too_far", + fromAddress, + ); + } + + // No sub-invocations allowed + const rootInvocation = auth.rootInvocation(); + if (rootInvocation.subInvocations().length > 0) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_has_subinvocations", + fromAddress, + ); + } + } + + const authStatus = gatherAuthEntrySignatureStatus({ + transaction, + simulationResponse: simResponse, + }); + if (!authStatus.alreadySigned.includes(fromAddress)) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_missing_payer_signature", + fromAddress, + ); + } + if (authStatus.pendingSignature.length > 0) { + return invalidVerifyResponse( + "invalid_exact_stellar_payload_unexpected_pending_signatures", + fromAddress, + ); + } + + return undefined; + } +} diff --git a/typescript/packages/mechanisms/stellar/src/exact/index.ts b/typescript/packages/mechanisms/stellar/src/exact/index.ts new file mode 100644 index 0000000000..028d97c00a --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/exact/index.ts @@ -0,0 +1 @@ +export { ExactStellarScheme } from "./client/scheme"; diff --git a/typescript/packages/mechanisms/stellar/src/exact/server/index.ts b/typescript/packages/mechanisms/stellar/src/exact/server/index.ts new file mode 100644 index 0000000000..9e91e067eb --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/exact/server/index.ts @@ -0,0 +1 @@ +export { ExactStellarScheme } from "./scheme"; diff --git a/typescript/packages/mechanisms/stellar/src/exact/server/scheme.ts b/typescript/packages/mechanisms/stellar/src/exact/server/scheme.ts new file mode 100644 index 0000000000..df9e6df072 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/exact/server/scheme.ts @@ -0,0 +1,150 @@ +import { DEFAULT_TOKEN_DECIMALS } from "../../constants"; +import { convertToTokenAmount, getUsdcAddress } from "../../utils"; +import type { + AssetAmount, + Network, + PaymentRequirements, + Price, + SchemeNetworkServer, + MoneyParser, +} from "@x402/core/types"; + +/** + * Stellar server implementation for the Exact payment scheme. + */ +export class ExactStellarScheme implements SchemeNetworkServer { + readonly scheme = "exact"; + private moneyParsers: MoneyParser[] = []; + + /** + * Register a custom money parser in the parser chain. + * Multiple parsers can be registered - they will be tried in registration order. + * Each parser receives a decimal amount (e.g., 1.50 for $1.50). + * If a parser returns null, the next parser in the chain will be tried. + * The default parser is always the final fallback. + * + * @param parser - Custom function to convert amount to AssetAmount (or null to skip) + * @returns The service instance for chaining + */ + registerMoneyParser(parser: MoneyParser): ExactStellarScheme { + this.moneyParsers.push(parser); + return this; + } + + /** + * Parses a price into `AssetAmount`. + * If price is already an `AssetAmount`, returns it directly. + * If price is `Money` (string | number), parses to decimal and tries custom parsers. + * If no custom parsers return a valid `AssetAmount`, falls back to default conversion, assuming USDC token contract. + * + * @param price - The `Price` to parse + * @param network - The `Network` to use + * @returns Promise that resolves to the parsed `AssetAmount` + */ + async parsePrice(price: Price, network: Network): Promise { + // Attempt 1: if already an AssetAmount, return it directly + if (typeof price === "object" && price !== null && "amount" in price) { + if (!price.asset) { + throw new Error(`Asset address must be specified for AssetAmount on network ${network}`); + } + return { + amount: price.amount, + asset: price.asset, + extra: price.extra || {}, + }; + } + + // Parse Money to decimal number + const amount = this.parseMoneyToDecimal(price); + + // Attempt 2: try each custom money parser in order + for (const parser of this.moneyParsers) { + const result = await parser(amount, network); + if (result !== null) { + return result; + } + } + + // Attempt 3: fallback to default conversion, assuming USDC token contract. + return this.defaultMoneyConversion(amount, network); + } + + /** + * Build payment requirements for this scheme/network combination + * + * @param paymentRequirements - The base payment requirements + * @param supportedKind - The supported kind configuration + * @param supportedKind.x402Version - The x402 protocol version + * @param supportedKind.scheme - The payment scheme + * @param supportedKind.network - The network identifier + * @param supportedKind.extra - Extra metadata including `areFeesSponsored` from facilitator + * @param extensionKeys - Extension keys supported by the facilitator + * @returns Enhanced payment requirements with `areFeesSponsored` in extra + */ + enhancePaymentRequirements( + paymentRequirements: PaymentRequirements, + supportedKind: { + x402Version: number; + scheme: string; + network: Network; + extra?: Record; + }, + extensionKeys: string[], + ): Promise { + // Mark unused parameters to satisfy linter + void extensionKeys; + + // Add `areFeesSponsored` from supportedKind.extra to payment requirements + // The facilitator provides `areFeesSponsored` which clients use to determine if fees are sponsored + const areFeesSponsored = supportedKind.extra?.areFeesSponsored; + return Promise.resolve({ + ...paymentRequirements, + extra: { + ...paymentRequirements.extra, + ...(typeof areFeesSponsored === "boolean" && { areFeesSponsored }), + }, + }); + } + + /** + * Parse Money (string | number) to a decimal number. + * Handles formats like "$1.50", "1.50", 1.50, etc. + * + * @param money - The money value to parse + * @returns Decimal number + */ + private parseMoneyToDecimal(money: string | number): number { + if (typeof money === "number") { + return money; + } + + // Remove $ sign and whitespace, then parse + const cleanMoney = money.replace(/^\$/, "").trim(); + const amount = parseFloat(cleanMoney); + + if (isNaN(amount)) { + throw new Error(`Invalid money format: ${money}`); + } + + return amount; + } + + /** + * Default money conversion implementation. + * Converts decimal amount to USDC on the specified network. + * + * @param amount - The decimal amount (e.g., 1.50) + * @param network - The network to use + * @returns The parsed asset amount in USDC + */ + private defaultMoneyConversion(amount: number, network: Network): AssetAmount { + // Convert decimal amount to token amount (USDC on Stellar has 7 decimals) + const tokenAmount = convertToTokenAmount(amount.toString(), DEFAULT_TOKEN_DECIMALS); + + return { + amount: tokenAmount, + asset: getUsdcAddress(network), + extra: {}, + }; + } +} diff --git a/typescript/packages/mechanisms/stellar/src/index.ts b/typescript/packages/mechanisms/stellar/src/index.ts new file mode 100644 index 0000000000..31c40bc6e5 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/index.ts @@ -0,0 +1,24 @@ +/** + * Stellar blockchain support for x402 protocol. + * + * This package provides Stellar network support for the x402 payment protocol, + * including client signing, server validation, and facilitator settlement. + * + * @module + */ + +// Exact scheme client +export { ExactStellarScheme } from "./exact"; + +// Types +export * from "./types"; + +// Constants +export * from "./constants"; + +// Signers +export * from "./signer"; + +// Utilities +export * from "./utils"; +export * from "./shared"; diff --git a/typescript/packages/mechanisms/stellar/src/shared.ts b/typescript/packages/mechanisms/stellar/src/shared.ts new file mode 100644 index 0000000000..7cbb83bc7d --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/shared.ts @@ -0,0 +1,134 @@ +import { Transaction, Address, Operation, xdr } from "@stellar/stellar-sdk"; +import { Api, assembleTransaction } from "@stellar/stellar-sdk/rpc"; + +/** + * Handles the simulation result of a Stellar transaction. + * + * @param simulation - The simulation result to handle + * @throws An error if the simulation result is of type "RESTORE" or "ERROR" + */ +export function handleSimulationResult(simulation?: Api.SimulateTransactionResponse) { + if (!simulation) { + throw new Error("Simulation result is undefined"); + } + + if (Api.isSimulationRestore(simulation)) { + throw new Error( + `Stellar simulation result has type "RESTORE" with restorePreamble: ${simulation.restorePreamble}`, + ); + } + + if (Api.isSimulationError(simulation)) { + const msg = `Stellar simulation failed${simulation.error ? ` with error message: ${simulation.error}` : ""}`; + + throw new Error(msg); + } +} + +/** + * Analysis result of transaction signers + */ +export type ContractSigners = { + /** Accounts that have already signed auth entries */ + alreadySigned: string[]; + /** Accounts that still need to sign auth entries */ + pendingSignature: string[]; +}; + +/** + * Input parameters for gathering auth entry signature status + */ +export type GatherAuthEntrySignatureStatusInput = { + /** The transaction to analyze */ + transaction: Transaction; + /** Optional simulation response to assemble with transaction before analysis */ + simulationResponse?: Api.SimulateTransactionResponse; + /** Whether to simulate/assemble the transaction with simulation data (default: true if simulationResponse was not provided) */ + simulate?: boolean; +}; + +/** + * Gathers the signature status of auth entries in a Stellar transaction. + * + * This function inspects the auth entries in the transaction's InvokeHostFunction + * operation and categorizes them based on their signature status. + * + * @param input - Input containing transaction and optional simulation data + * @param input.transaction - The transaction to analyze + * @param input.simulationResponse - Optional simulation response to assemble with transaction before analysis + * @param input.simulate - Whether to simulate/assemble the transaction with simulation data (default: true if simulationResponse was not provided) + * @returns ContractSigners with arrays of signed and pending signer addresses + * @throws Error if transaction doesn't have exactly one InvokeHostFunction operation + * + * @example + * ```ts + * const status = gatherAuthEntrySignatureStatus({ + * transaction: tx, + * simulationResponse: simResult + * }); + * console.log('Already signed:', status.alreadySigned); + * console.log('Pending:', status.pendingSignature); + * ``` + */ +export function gatherAuthEntrySignatureStatus({ + transaction, + simulationResponse, + simulate, +}: GatherAuthEntrySignatureStatusInput): ContractSigners { + // Determine if we should assemble with simulation + const shouldAssemble = simulate ?? simulationResponse !== undefined; + let assembledTx = transaction; + + // Assemble transaction with simulation if requested + if (shouldAssemble && simulationResponse) { + const assembledTxBuilder = assembleTransaction(transaction, simulationResponse); + assembledTx = assembledTxBuilder.build(); + } + + // Validate transaction structure + if (assembledTx.operations.length !== 1) { + throw new Error( + `Expected transaction with exactly one operation, got ${assembledTx.operations.length}`, + ); + } + + const operation = assembledTx.operations[0]; + if (operation.type !== "invokeHostFunction") { + throw new Error(`Expected InvokeHostFunction operation, got ${operation.type}`); + } + + const invokeOp = operation as Operation.InvokeHostFunction; + + const alreadySigned: string[] = []; + const pendingSignature: string[] = []; + + for (const entry of invokeOp.auth ?? []) { + const credentialsType = entry.credentials().switch(); + + // Skip source account credentials - these use the transaction source + if (credentialsType === xdr.SorobanCredentialsType.sorobanCredentialsSourceAccount()) { + continue; + } + + // Handle address-based credentials + if (credentialsType === xdr.SorobanCredentialsType.sorobanCredentialsAddress()) { + const addressCredentials = entry.credentials().address(); + const address = Address.fromScAddress(addressCredentials.address()).toString(); + const signature = addressCredentials.signature(); + + // Check if already signed (signature is not scvVoid) + const isSigned = signature.switch().name !== "scvVoid"; + + if (isSigned) { + alreadySigned.push(address); + } else { + pendingSignature.push(address); + } + } + } + + return { + alreadySigned: [...new Set(alreadySigned)], // Remove duplicates + pendingSignature: [...new Set(pendingSignature)], + }; +} diff --git a/typescript/packages/mechanisms/stellar/src/signer.ts b/typescript/packages/mechanisms/stellar/src/signer.ts new file mode 100644 index 0000000000..9a6498b809 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/signer.ts @@ -0,0 +1,102 @@ +import { Keypair } from "@stellar/stellar-sdk"; +import { basicNodeSigner, SignAuthEntry, SignTransaction } from "@stellar/stellar-sdk/contract"; +import { STELLAR_TESTNET_CAIP2 } from "./constants"; +import { getNetworkPassphrase } from "./utils"; +import type { Network } from "@x402/core/types"; + +/** + * Ed25519 signer for Stellar transactions and auth entries. + * + * Implements SEP-43 interface (except signMessage). + * + * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0043.md + */ +export type Ed25519Signer = { + address: string; + signAuthEntry: SignAuthEntry; + signTransaction: SignTransaction; +}; + +/** + * Facilitator signer for Stellar transactions. + * + * Alias for Ed25519Signer. Used by x402 facilitators to verify and settle payments. + * + * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0043.md + */ +export type FacilitatorStellarSigner = Ed25519Signer; + +/** + * Client signer for Stellar transactions. + * + * Used by x402 clients to sign auth entries. Supports both classic (G) and contract (C) accounts. + * signTransaction is optional for client signers. + * + * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0043.md + */ +export type ClientStellarSigner = { + address: string; + signAuthEntry: SignAuthEntry; + signTransaction?: SignTransaction; +}; + +/** + * Creates an Ed25519 signer for the given Stellar network. + * + * @param privateKey - Stellar classic (G) account private key + * @param defaultNetwork - Is the network the signTransactiopn method will default to if no network is provided. Must use the CAIP-2 format identifier. + * @returns Ed25519 signer implementing SEP-43 interface (except signMessage) + * @see https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0043.md + */ +export function createEd25519Signer( + privateKey: string, + defaultNetwork: Network = STELLAR_TESTNET_CAIP2, +): Ed25519Signer { + const kp = Keypair.fromSecret(privateKey); + const networkPassphrase = getNetworkPassphrase(defaultNetwork); + + const address = kp.publicKey(); + const { signAuthEntry, signTransaction } = basicNodeSigner(kp, networkPassphrase); + + return { + address, + signAuthEntry, + signTransaction, + }; +} + +/** + * Type guard for FacilitatorStellarSigner. + * + * Checks for required methods: address, signAuthEntry, signTransaction. + * + * @param signer - Value to check + * @returns `true` if signer is a FacilitatorStellarSigner + */ +export function isFacilitatorStellarSigner(signer: unknown): signer is FacilitatorStellarSigner { + if (typeof signer !== "object" || signer === null) return false; + const s = signer as Record; + return ( + typeof s.address === "string" && + typeof s.signAuthEntry === "function" && + typeof s.signTransaction === "function" + ); +} + +/** + * Type guard for ClientStellarSigner. + * + * Checks for required methods: address, signAuthEntry. signTransaction is optional. + * + * @param signer - Value to check + * @returns `true` if signer is a ClientStellarSigner + */ +export function isClientStellarSigner(signer: unknown): signer is ClientStellarSigner { + if (typeof signer !== "object" || signer === null) return false; + const s = signer as Record; + return ( + typeof s.address === "string" && + typeof s.signAuthEntry === "function" && + (s.signTransaction === undefined || typeof s.signTransaction === "function") + ); +} diff --git a/typescript/packages/mechanisms/stellar/src/types.ts b/typescript/packages/mechanisms/stellar/src/types.ts new file mode 100644 index 0000000000..0349610895 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/types.ts @@ -0,0 +1,9 @@ +/** + * Exact Stellar payload structure containing a base64 encoded Stellar transaction + */ +export type ExactStellarPayloadV2 = { + /** + * Base64 encoded Stellar transaction + */ + transaction: string; +}; diff --git a/typescript/packages/mechanisms/stellar/src/utils.ts b/typescript/packages/mechanisms/stellar/src/utils.ts new file mode 100644 index 0000000000..15349f561f --- /dev/null +++ b/typescript/packages/mechanisms/stellar/src/utils.ts @@ -0,0 +1,195 @@ +import { rpc } from "@stellar/stellar-sdk"; +import { + DEFAULT_TESTNET_RPC_URL, + DEFAULT_TOKEN_DECIMALS, + STELLAR_ASSET_ADDRESS_REGEX, + STELLAR_DESTINATION_ADDRESS_REGEX, + STELLAR_NETWORK_TO_PASSPHRASE, + STELLAR_PUBNET_CAIP2, + STELLAR_TESTNET_CAIP2, + USDC_PUBNET_ADDRESS, + USDC_TESTNET_ADDRESS, +} from "./constants"; +import type { Network } from "@x402/core/types"; + +export const DEFAULT_ESTIMATED_LEDGER_SECONDS = 5; +const RPC_LEDGERS_SAMPLE_SIZE = 20; + +/** + * Configuration for RPC client connections + */ +export interface RpcConfig { + /** Custom RPC URL to use instead of defaults */ + url?: string; +} + +/** + * Checks if a network is a Stellar network + * + * @param network - The CAIP-2 network identifier + * @returns `true` if the network is a Stellar network, `false` otherwise + */ +export function isStellarNetwork(network: Network): boolean { + return STELLAR_NETWORK_TO_PASSPHRASE.has(network); +} + +/** + * Validates a Stellar destination address (G-account, C-account, or M-account) + * + * @param address - Stellar destination address to validate + * @returns `true` if the address is valid, `false` otherwise + */ +export function validateStellarDestinationAddress(address: string): boolean { + return STELLAR_DESTINATION_ADDRESS_REGEX.test(address); +} + +/** + * Validates a Stellar asset/contract address (C-account only) + * + * @param address - Stellar asset address to validate + * @returns `true` if the address is valid, `false` otherwise + */ +export function validateStellarAssetAddress(address: string): boolean { + return STELLAR_ASSET_ADDRESS_REGEX.test(address); +} + +/** + * Gets the network passphrase for a given Stellar network + * + * @param network - The CAIP-2 network identifier + * @returns The network passphrase string + * @throws {Error} If the network is not a known Stellar network + */ +export function getNetworkPassphrase(network: Network): string { + const networkPassphrase = STELLAR_NETWORK_TO_PASSPHRASE.get(network); + if (!networkPassphrase) { + throw new Error(`Unknown Stellar network: ${network}`); + } + return networkPassphrase; +} + +/** + * Gets the RPC URL for a given Stellar network + * + * @param network - The CAIP-2 network identifier + * @param rpcConfig - Optional RPC configuration with custom URL + * @returns The RPC URL string + * @throws {Error} If the network is unknown or mainnet RPC URL is not provided + */ +export function getRpcUrl(network: Network, rpcConfig?: RpcConfig): string { + const customRpcUrl = rpcConfig?.url; + switch (network) { + case STELLAR_TESTNET_CAIP2: + return customRpcUrl || DEFAULT_TESTNET_RPC_URL; + case STELLAR_PUBNET_CAIP2: + if (!customRpcUrl) { + throw new Error( + "Stellar mainnet requires a non-empty rpcUrl. For a list of RPC providers, see https://developers.stellar.org/docs/data/apis/rpc/providers#publicly-accessible-apis", + ); + } + return customRpcUrl; + default: + throw new Error(`Unknown Stellar network: ${network}`); + } +} + +/** + * Creates a Soroban RPC client for the given network + * + * @param network - The CAIP-2 network identifier + * @param rpcConfig - Optional RPC configuration with custom URL + * @returns A configured Soroban RPC Server instance + * @throws {Error} If the network is not a valid Stellar network + */ +export function getRpcClient(network: Network, rpcConfig?: RpcConfig): rpc.Server { + const rpcUrl = getRpcUrl(network, rpcConfig); + return new rpc.Server(rpcUrl, { + allowHttp: network === STELLAR_TESTNET_CAIP2, // Allow HTTP for testnet + }); +} + +/** + * Fetches the estimated ledger close time (seconds per ledger) from RPC getLedgers. + * + * @param server - The Soroban RPC Server instance + * @returns Estimated seconds per ledger, or DEFAULT_ESTIMATED_LEDGER_SECONDS (5) on error + */ +export async function getEstimatedLedgerCloseTimeSeconds(server: rpc.Server): Promise { + try { + const latestLedger = await server.getLatestLedger(); + const startLedger = latestLedger.sequence; + const { ledgers } = await server.getLedgers({ + startLedger, + pagination: { limit: RPC_LEDGERS_SAMPLE_SIZE }, + }); + if (!ledgers || ledgers.length < 2) return DEFAULT_ESTIMATED_LEDGER_SECONDS; + + const oldestTs = parseInt(ledgers[0].ledgerCloseTime); + const newestTs = parseInt(ledgers[ledgers.length - 1].ledgerCloseTime); + const intervals = ledgers.length - 1; + return Math.ceil((newestTs - oldestTs) / intervals); + } catch { + return DEFAULT_ESTIMATED_LEDGER_SECONDS; + } +} + +/** + * Gets the default USDC contract address for a network + * + * @param network - The CAIP-2 network identifier + * @returns The USDC contract address for the network + * @throws {Error} If the network doesn't have a configured USDC address + */ +export function getUsdcAddress(network: Network): string { + switch (network) { + case STELLAR_PUBNET_CAIP2: + return USDC_PUBNET_ADDRESS; + case STELLAR_TESTNET_CAIP2: + return USDC_TESTNET_ADDRESS; + default: + throw new Error(`No USDC address configured for network: ${network}`); + } +} + +/** + * Converts a decimal amount to token smallest units + * + * Handles both regular decimal strings (e.g., "0.10") and scientific notation (e.g., "1e-7"). + * The result is truncated (not rounded) to the specified number of decimal places. + * + * @param decimalAmount - The decimal amount as a string + * @param decimals - Number of decimal places for the token (default: 7 for USDC) + * @returns The amount in smallest units as a string with leading zeros removed + * @throws {Error} If the amount is invalid or decimals is out of range + * + * @example + * ```ts + * convertToTokenAmount("0.1", 7) // "1000000" + * convertToTokenAmount("1.5", 7) // "15000000" + * convertToTokenAmount("1e-7", 7) // "1" + * convertToTokenAmount("1.5", 0) // "1" (truncated) + * ``` + */ +export function convertToTokenAmount( + decimalAmount: string, + decimals: number = DEFAULT_TOKEN_DECIMALS, +): string { + const amount = parseFloat(decimalAmount); + if (isNaN(amount)) { + throw new Error(`Invalid amount: ${decimalAmount}`); + } + + if (decimals < 0 || decimals > 20) { + throw new Error(`Decimals must be between 0 and 20, got ${decimals}`); + } + + // Normalize scientific notation to fixed decimal string + const normalizedDecimal = /[eE]/.test(decimalAmount) + ? amount.toFixed(Math.max(decimals, 20)) + : decimalAmount; + + const [intPart, decPart = ""] = normalizedDecimal.split("."); + const paddedDec = decPart.padEnd(decimals, "0").slice(0, decimals); + + return (intPart + paddedDec).replace(/^0+/, "") || "0"; +} diff --git a/typescript/packages/mechanisms/stellar/test/integrations/exact-stellar.test.ts b/typescript/packages/mechanisms/stellar/test/integrations/exact-stellar.test.ts new file mode 100644 index 0000000000..6cc86610be --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/integrations/exact-stellar.test.ts @@ -0,0 +1,601 @@ +import { x402Client, x402HTTPClient } from "@x402/core/client"; +import { x402Facilitator } from "@x402/core/facilitator"; +import { + HTTPAdapter, + HTTPResponseInstructions, + x402HTTPResourceServer, + x402ResourceServer, + FacilitatorClient, +} from "@x402/core/server"; +import { + AssetAmount, + Network, + PaymentPayload, + PaymentRequirements, + VerifyResponse, + SettleResponse, + SupportedResponse, +} from "@x402/core/types"; +import { beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { createEd25519Signer, Ed25519Signer, STELLAR_TESTNET_CAIP2 } from "../../src"; +import { ExactStellarScheme as ExactStellarClient } from "../../src/exact/client"; +import { ExactStellarScheme as ExactStellarFacilitator } from "../../src/exact/facilitator"; +import { ExactStellarScheme as ExactStellarServer } from "../../src/exact/server"; +import type { ExactStellarPayloadV2 } from "../../src/types"; + +// Load private keys and addresses from environment +const CLIENT_PRIVATE_KEY = process.env.CLIENT_PRIVATE_KEY; +const FACILITATOR_PRIVATE_KEY = process.env.FACILITATOR_PRIVATE_KEY; +const FACILITATOR_ADDRESS = process.env.FACILITATOR_ADDRESS; +const RESOURCE_SERVER_ADDRESS = process.env.RESOURCE_SERVER_ADDRESS; +const XLM_TESTNET_ASSET = "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"; + +async function xlmFallbackParser(amount: number, network: string): Promise { + if (network === STELLAR_TESTNET_CAIP2) { + return { + amount: Math.round(amount * 1e7).toString(), + asset: XLM_TESTNET_ASSET, + extra: {}, + }; + } + return null; +} + +if ( + !CLIENT_PRIVATE_KEY || + !FACILITATOR_PRIVATE_KEY || + !FACILITATOR_ADDRESS || + !RESOURCE_SERVER_ADDRESS +) { + throw new Error( + "CLIENT_PRIVATE_KEY, FACILITATOR_PRIVATE_KEY, FACILITATOR_ADDRESS and RESOURCE_SERVER_ADDRESS environment variables must be set for integration tests", + ); +} + +const HORIZON_TESTNET = "https://horizon-testnet.stellar.org"; +const FRIENDBOT_URL = "https://friendbot.stellar.org"; +const STELLAR_EXPERT_TESTNET_TX = "https://stellar.expert/explorer/testnet/tx"; + +function logStellarExpertTxUrl(txHash: string): void { + console.log(`Stellar Expert (testnet): ${STELLAR_EXPERT_TESTNET_TX}/${txHash}`); +} + +async function fundOneAccount(address: string): Promise { + const res = await fetch(`${HORIZON_TESTNET}/accounts/${address}`); + if (res.status === 404) { + console.log(`Account ${address} not found, funding with Friendbot\n`); + const fb = await fetch(`${FRIENDBOT_URL}?addr=${encodeURIComponent(address)}`); + if (!fb.ok) { + const body = await fb.text(); + throw new Error(`Friendbot failed for ${address}: ${fb.status} ${body}`); + } + console.log(`Account ${address} funded with Friendbot\n`); + } else if (!res.ok) { + throw new Error(`Horizon account check failed for ${address}: ${res.status}`); + } +} + +async function ensureAccountsFunded(addresses: string[]): Promise { + await Promise.all(addresses.map(fundOneAccount)); +} + +/** + * Stellar Facilitator Client wrapper + * Wraps the x402Facilitator for use with x402ResourceServer + */ +class StellarFacilitatorClient implements FacilitatorClient { + readonly scheme = "exact"; + readonly network = STELLAR_TESTNET_CAIP2; + readonly x402Version = 2; + + /** + * Creates a new StellarFacilitatorClient instance + * + * @param facilitator - The x402 facilitator to wrap + */ + constructor(private readonly facilitator: x402Facilitator) {} + + /** + * Verifies a payment payload + * + * @param paymentPayload - The payment payload to verify + * @param paymentRequirements - The payment requirements + * @returns Promise resolving to verification response + */ + verify( + paymentPayload: PaymentPayload, + paymentRequirements: PaymentRequirements, + ): Promise { + return this.facilitator.verify(paymentPayload, paymentRequirements); + } + + /** + * Settles a payment + * + * @param paymentPayload - The payment payload to settle + * @param paymentRequirements - The payment requirements + * @returns Promise resolving to settlement response + */ + settle( + paymentPayload: PaymentPayload, + paymentRequirements: PaymentRequirements, + ): Promise { + return this.facilitator.settle(paymentPayload, paymentRequirements); + } + + /** + * Gets supported payment kinds + * + * @returns Promise resolving to supported response + */ + getSupported(): Promise { + // Delegate to actual facilitator to get real supported kinds + return Promise.resolve(this.facilitator.getSupported() as SupportedResponse); + } +} + +/** + * Build Stellar payment requirements for testing + * + * @param payTo - The recipient address + * @param amount - The payment amount in smallest units + * @param network - The network identifier (defaults to Stellar Testnet) + * @returns Payment requirements object + */ +function buildStellarPaymentRequirements( + payTo: string, + amount: string, + network: Network = STELLAR_TESTNET_CAIP2, +): PaymentRequirements { + return { + scheme: "exact", + network, + asset: XLM_TESTNET_ASSET, + amount, + payTo, + maxTimeoutSeconds: 3600, + extra: { areFeesSponsored: true }, + }; +} + +/** + * Helper to check if an error is due to insufficient balance + */ +function isInsufficientBalanceError(error: unknown): boolean { + if (error instanceof Error) { + return ( + error.message.includes("resulting balance is not within the allowed range") || + error.message.includes("insufficient balance") || + error.message.includes("Error(Contract, #10)") + ); + } + return false; +} + +describe("Stellar Integration Tests", () => { + let clientAddress: string; + let clientSigner: Ed25519Signer; + let facilitatorSigner: Ed25519Signer; + beforeAll(async () => { + clientSigner = createEd25519Signer(CLIENT_PRIVATE_KEY!, STELLAR_TESTNET_CAIP2); + clientAddress = clientSigner.address; + + facilitatorSigner = createEd25519Signer(FACILITATOR_PRIVATE_KEY, STELLAR_TESTNET_CAIP2); + + await ensureAccountsFunded([FACILITATOR_ADDRESS, RESOURCE_SERVER_ADDRESS, clientAddress]); + }); + + describe("x402Client / x402ResourceServer / x402Facilitator - Stellar Flow", () => { + let client: x402Client; + let server: x402ResourceServer; + let facilitatorClient: StellarFacilitatorClient; + + beforeEach(async () => { + const stellarClient = new ExactStellarClient(clientSigner); + client = new x402Client().register(STELLAR_TESTNET_CAIP2, stellarClient); + + const stellarFacilitator = new ExactStellarFacilitator([facilitatorSigner]); + const facilitator = new x402Facilitator().register(STELLAR_TESTNET_CAIP2, stellarFacilitator); + + facilitatorClient = new StellarFacilitatorClient(facilitator); + server = new x402ResourceServer(facilitatorClient); + server.register(STELLAR_TESTNET_CAIP2, new ExactStellarServer()); + await server.initialize(); + }); + + it("server should successfully verify and settle a Stellar payment from a client", async () => { + // Server - builds PaymentRequired response + const accepts = [buildStellarPaymentRequirements(RESOURCE_SERVER_ADDRESS, "1000")]; + const resource = { + url: "https://company.co", + description: "Company Co. resource", + mimeType: "application/json", + }; + const paymentRequired = await server.createPaymentRequiredResponse(accepts, resource); + + // Client - responds with PaymentPayload response + let paymentPayload: PaymentPayload; + try { + paymentPayload = await client.createPaymentPayload(paymentRequired); + } catch (error) { + if (isInsufficientBalanceError(error)) { + throw new Error( + `Insufficient balance on testnet account ${clientAddress}. ` + + `Asset: ${XLM_TESTNET_ASSET}. Ensure the account is funded (e.g. via Friendbot).`, + ); + } + throw error; + } + + expect(paymentPayload).toBeDefined(); + expect(paymentPayload.x402Version).toBe(2); + expect(paymentPayload.accepted.scheme).toBe("exact"); + + // Verify the payload structure + const stellarPayload = paymentPayload.payload as ExactStellarPayloadV2; + expect(stellarPayload.transaction).toBeDefined(); + expect(typeof stellarPayload.transaction).toBe("string"); + expect(stellarPayload.transaction.length).toBeGreaterThan(0); + + // Server - maps payment payload to payment requirements + const accepted = server.findMatchingRequirements(accepts, paymentPayload); + expect(accepted).toBeDefined(); + + const verifyResponse = await server.verifyPayment(paymentPayload, accepted!); + + expect(verifyResponse.isValid).toBe(true); + expect(verifyResponse.payer).toBe(clientAddress); + + // Server does work here + const settleResponse = await server.settlePayment(paymentPayload, accepted!); + expect(settleResponse.success).toBe(true); + expect(settleResponse.network).toBe(STELLAR_TESTNET_CAIP2); + expect(settleResponse.transaction).toBeDefined(); + expect(settleResponse.payer).toBe(clientAddress); + logStellarExpertTxUrl(settleResponse.transaction); + }); + }); + + describe("x402HTTPClient / x402HTTPResourceServer / x402Facilitator - Stellar Flow", () => { + let client: x402HTTPClient; + let httpServer: x402HTTPResourceServer; + + const routes = { + "/api/protected": { + accepts: { + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: { amount: "1000", asset: XLM_TESTNET_ASSET }, + network: STELLAR_TESTNET_CAIP2 as Network, + }, + description: "Access to protected API", + mimeType: "application/json", + }, + }; + + const mockAdapter: HTTPAdapter = { + getHeader: () => { + return undefined; + }, + getMethod: () => "GET", + getPath: () => "/api/protected", + getUrl: () => "https://example.com/api/protected", + getAcceptHeader: () => "application/json", + getUserAgent: () => "TestClient/1.0", + }; + + beforeEach(async () => { + const stellarFacilitator = new ExactStellarFacilitator([facilitatorSigner]); + const facilitator = new x402Facilitator().register(STELLAR_TESTNET_CAIP2, stellarFacilitator); + + const facilitatorClient = new StellarFacilitatorClient(facilitator); + + const stellarClient = new ExactStellarClient(clientSigner); + const paymentClient = new x402Client().register(STELLAR_TESTNET_CAIP2, stellarClient); + client = new x402HTTPClient(paymentClient) as x402HTTPClient; + + // Create resource server and register schemes (composition pattern) + const ResourceServer = new x402ResourceServer(facilitatorClient); + ResourceServer.register(STELLAR_TESTNET_CAIP2, new ExactStellarServer()); + await ResourceServer.initialize(); // Initialize to fetch supported kinds + + httpServer = new x402HTTPResourceServer(ResourceServer, routes); + }); + + it("middleware should successfully verify and settle a Stellar payment from an http client", async () => { + // Middleware creates a PaymentRequired response + const context = { + adapter: mockAdapter, + path: "/api/protected", + method: "GET", + }; + + // No payment made, get PaymentRequired response & header + const httpProcessResult = (await httpServer.processHTTPRequest(context))!; + expect(httpProcessResult.type).toBe("payment-error"); + + const initial402Response = ( + httpProcessResult as { type: "payment-error"; response: HTTPResponseInstructions } + ).response; + + expect(initial402Response).toBeDefined(); + expect(initial402Response.status).toBe(402); + expect(initial402Response.headers).toBeDefined(); + expect(initial402Response.headers["PAYMENT-REQUIRED"]).toBeDefined(); + + // Client responds to PaymentRequired and submits a request with a PaymentPayload + const paymentRequired = client.getPaymentRequiredResponse( + name => initial402Response.headers[name], + initial402Response.body, + ); + let paymentPayload: PaymentPayload; + try { + paymentPayload = await client.createPaymentPayload(paymentRequired); + } catch (error) { + if (isInsufficientBalanceError(error)) { + throw new Error( + `Insufficient balance on testnet account ${clientAddress}. ` + + `Asset: ${XLM_TESTNET_ASSET}. Ensure the account is funded (e.g. via Friendbot).`, + ); + } + throw error; + } + + expect(paymentPayload).toBeDefined(); + expect(paymentPayload.accepted.scheme).toBe("exact"); + + const requestHeaders = await client.encodePaymentSignatureHeader(paymentPayload); + + // Middleware handles PAYMENT-SIGNATURE request + mockAdapter.getHeader = (name: string) => { + if (name === "PAYMENT-SIGNATURE") { + return requestHeaders["PAYMENT-SIGNATURE"]; + } + return undefined; + }; + + const httpProcessResult2 = await httpServer.processHTTPRequest(context); + + // No need to respond, can continue with request + expect(httpProcessResult2.type).toBe("payment-verified"); + const { + paymentPayload: verifiedPaymentPayload, + paymentRequirements: verifiedPaymentRequirements, + } = httpProcessResult2 as { + type: "payment-verified"; + paymentPayload: PaymentPayload; + paymentRequirements: PaymentRequirements; + }; + + expect(verifiedPaymentPayload).toBeDefined(); + expect(verifiedPaymentRequirements).toBeDefined(); + + const settlementResult = await httpServer.processSettlement( + verifiedPaymentPayload, + verifiedPaymentRequirements, + ); + + expect(settlementResult).toBeDefined(); + expect(settlementResult.success).toBe(true); + + if (settlementResult.success) { + expect(settlementResult.headers).toBeDefined(); + expect(settlementResult.headers["PAYMENT-RESPONSE"]).toBeDefined(); + logStellarExpertTxUrl(settlementResult.transaction); + } + }); + }); + + describe("Price Parsing Integration", () => { + let server: x402ResourceServer; + let stellarServer: ExactStellarServer; + + beforeEach(async () => { + const facilitator = new x402Facilitator().register( + STELLAR_TESTNET_CAIP2, + new ExactStellarFacilitator([facilitatorSigner]), + ); + + const facilitatorClient = new StellarFacilitatorClient(facilitator); + server = new x402ResourceServer(facilitatorClient); + + stellarServer = new ExactStellarServer(); + server.register(STELLAR_TESTNET_CAIP2, stellarServer); + await server.initialize(); + }); + + it("should parse Money formats and build payment requirements", async () => { + stellarServer.registerMoneyParser(xlmFallbackParser); + + // Test different Money formats + const testCases = [ + { input: "$1.00", expectedAmount: "10000000" }, + { input: "1.50", expectedAmount: "15000000" }, + { input: 2.5, expectedAmount: "25000000" }, + ]; + + for (const testCase of testCases) { + const requirements = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: testCase.input, + network: STELLAR_TESTNET_CAIP2 as Network, + }); + + expect(requirements).toHaveLength(1); + expect(requirements[0].amount).toBe(testCase.expectedAmount); + expect(requirements[0].asset).toBe(XLM_TESTNET_ASSET); + } + }); + + it("should handle AssetAmount pass-through", async () => { + const customAsset = { + amount: "50000000", + asset: "CUSTOMTOKENMINT111111111111111111111111111111", + extra: { foo: "bar" }, + }; + + const requirements = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: customAsset, + network: STELLAR_TESTNET_CAIP2 as Network, + }); + + expect(requirements).toHaveLength(1); + expect(requirements[0].amount).toBe("50000000"); + expect(requirements[0].asset).toBe("CUSTOMTOKENMINT111111111111111111111111111111"); + expect(requirements[0].extra?.foo).toBe("bar"); + }); + + it("should use registerMoneyParser for custom conversion", async () => { + stellarServer + .registerMoneyParser(async (amount, _network) => { + if (amount > 100) { + return { + amount: (amount * 1e7).toString(), + asset: "CUSTOMLARGETOKENMINT111111111111111111111", + extra: { token: "CUSTOM", tier: "large" }, + }; + } + return null; + }) + .registerMoneyParser(xlmFallbackParser); + + // Test large amount - should use custom parser + const largeRequirements = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: 150, // Large amount + network: STELLAR_TESTNET_CAIP2 as Network, + }); + + expect(largeRequirements[0].amount).toBe((150 * 1e7).toString()); + expect(largeRequirements[0].asset).toBe("CUSTOMLARGETOKENMINT111111111111111111111"); + expect(largeRequirements[0].extra?.token).toBe("CUSTOM"); + expect(largeRequirements[0].extra?.tier).toBe("large"); + + // Test small amount - should use default (XLM) + const smallRequirements = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: 50, // Small amount + network: STELLAR_TESTNET_CAIP2 as Network, + }); + + expect(smallRequirements[0].amount).toBe("500000000"); // 50 * 1e7 (7 decimals) + expect(smallRequirements[0].asset).toBe(XLM_TESTNET_ASSET); + }); + + it("should support multiple MoneyParser in chain", async () => { + stellarServer + .registerMoneyParser(async amount => { + if (amount > 1000) { + return { + amount: (amount * 1e7).toString(), + asset: "VIPTOKENMINT111111111111111111111111111111", + extra: { tier: "vip" }, + }; + } + return null; + }) + .registerMoneyParser(async amount => { + if (amount > 100) { + return { + amount: (amount * 1e7).toString(), + asset: "PREMIUMTOKENMINT1111111111111111111111111", + extra: { tier: "premium" }, + }; + } + return null; + }) + .registerMoneyParser(xlmFallbackParser); + // < 100 uses XLM fallback + + // VIP tier + const vipReq = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: 2000, + network: STELLAR_TESTNET_CAIP2 as Network, + }); + expect(vipReq[0].extra?.tier).toBe("vip"); + expect(vipReq[0].asset).toBe("VIPTOKENMINT111111111111111111111111111111"); + + // Premium tier + const premiumReq = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: 500, + network: STELLAR_TESTNET_CAIP2 as Network, + }); + expect(premiumReq[0].extra?.tier).toBe("premium"); + expect(premiumReq[0].asset).toBe("PREMIUMTOKENMINT1111111111111111111111111"); + + // Standard tier (default) + const standardReq = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: 50, + network: STELLAR_TESTNET_CAIP2 as Network, + }); + expect(standardReq[0].asset).toBe(XLM_TESTNET_ASSET); + }); + + it("should work with async MoneyParser (e.g., exchange rate lookup)", async () => { + const mockExchangeRate = 0.98; + + stellarServer.registerMoneyParser(async (amount, _network) => { + await new Promise(resolve => setTimeout(resolve, 10)); + + const convertedAmount = amount * mockExchangeRate; + return { + amount: Math.floor(convertedAmount * 1e7).toString(), + asset: XLM_TESTNET_ASSET, + extra: { + exchangeRate: mockExchangeRate, + originalUSD: amount, + }, + }; + }); + + const requirements = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: 100, + network: STELLAR_TESTNET_CAIP2 as Network, + }); + + // 100 * 0.98 = 98 (XLM, 7 decimals) + expect(requirements[0].amount).toBe("980000000"); + expect(requirements[0].extra?.exchangeRate).toBe(0.98); + expect(requirements[0].extra?.originalUSD).toBe(100); + }); + + it("should avoid floating-point rounding error", async () => { + stellarServer.registerMoneyParser(xlmFallbackParser); + + // Test different Money formats + const testCases = [ + { input: "$4.02", expectedAmount: "40200000" }, + { input: "4.02", expectedAmount: "40200000" }, + { input: "4.02 XLM", expectedAmount: "40200000" }, + { input: "4.02 USD", expectedAmount: "40200000" }, + { input: 4.02, expectedAmount: "40200000" }, + ]; + + for (const testCase of testCases) { + const requirements = await server.buildPaymentRequirements({ + scheme: "exact", + payTo: RESOURCE_SERVER_ADDRESS, + price: testCase.input, + network: STELLAR_TESTNET_CAIP2 as Network, + }); + + expect(requirements).toHaveLength(1); + expect(requirements[0].amount).toBe(testCase.expectedAmount); + expect(requirements[0].asset).toBe(XLM_TESTNET_ASSET); + } + }); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/client.test.ts b/typescript/packages/mechanisms/stellar/test/unit/client.test.ts new file mode 100644 index 0000000000..4467c67320 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/client.test.ts @@ -0,0 +1,262 @@ +import { nativeToScVal } from "@stellar/stellar-sdk"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { STELLAR_PUBNET_CAIP2, STELLAR_TESTNET_CAIP2 } from "../../src/constants"; +import { ExactStellarScheme } from "../../src/exact/client/scheme"; +import * as stellarUtils from "../../src/utils"; +import type { ClientStellarSigner } from "../../src/signer"; +import type { RpcConfig } from "../../src/utils"; +import type { PaymentRequirements } from "@x402/core/types"; + +const { mockAssembledTransactionBuild } = vi.hoisted(() => ({ + mockAssembledTransactionBuild: vi.fn(), +})); + +vi.mock("@stellar/stellar-sdk", async () => { + const actual = + await vi.importActual("@stellar/stellar-sdk"); + return { + ...actual, + contract: { + ...actual.contract, + AssembledTransaction: { + ...actual.contract.AssembledTransaction, + build: mockAssembledTransactionBuild, + }, + }, + }; +}); + +vi.mock("../../src/utils", async () => { + const actual = await vi.importActual("../../src/utils"); + return { + ...actual, + getEstimatedLedgerCloseTimeSeconds: vi.fn().mockResolvedValue(5), + getRpcUrl: vi.fn(), + getRpcClient: vi.fn(), + isStellarNetwork: vi.fn(), + validateStellarAssetAddress: vi.fn(), + validateStellarDestinationAddress: vi.fn(), + }; +}); + +describe("ExactStellarScheme", () => { + const mockSignerAddress = "GBBO4ZDDZTSM2IUKQYBAST3CFHNPFXECGEFTGWTA2WELR2BIWDK57UVE"; + const mockSigner: ClientStellarSigner = { + address: mockSignerAddress, + signAuthEntry: vi.fn().mockResolvedValue({ signedAuthEntry: "signed" }), + }; + + const validPaymentReq: PaymentRequirements = { + scheme: "exact", + network: STELLAR_TESTNET_CAIP2, + amount: "1000000", + payTo: "GCHEI4PQEFJOA27MNZRPQNLGURS6KASW76X5UZCUZIXCOJLKXYCXOR2W", + maxTimeoutSeconds: 60, + asset: "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA", + extra: { areFeesSponsored: true }, + }; + + const mockTransaction = { + simulation: {}, + needsNonInvokerSigningBy: vi.fn(), + signAuthEntries: vi.fn(), + simulate: vi.fn(), + built: { toXDR: vi.fn().mockReturnValue("mock-xdr") }, + }; + + const setupSuccessfulTransaction = () => { + mockTransaction.needsNonInvokerSigningBy.mockReturnValueOnce([mockSignerAddress]); + mockTransaction.needsNonInvokerSigningBy.mockReturnValueOnce([]); + }; + + const mockRpcServer = { + getLatestLedger: vi.fn().mockResolvedValue({ sequence: 100000 }), + }; + + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(stellarUtils.isStellarNetwork).mockReturnValue(true); + vi.mocked(stellarUtils.validateStellarAssetAddress).mockReturnValue(true); + vi.mocked(stellarUtils.validateStellarDestinationAddress).mockReturnValue(true); + vi.mocked(stellarUtils.getRpcUrl).mockReturnValue("https://soroban-testnet.stellar.org"); + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockRpcServer as never); + mockAssembledTransactionBuild.mockResolvedValue(mockTransaction); + }); + + describe("constructor", () => { + it("should create instance with correct scheme and accept optional rpcConfig", () => { + expect(new ExactStellarScheme(mockSigner).scheme).toBe("exact"); + expect( + new ExactStellarScheme(mockSigner, { url: "https://custom-rpc.example.com" }).scheme, + ).toBe("exact"); + }); + }); + + describe("createPaymentPayload", () => { + it.each([ + ["unsupported scheme", { scheme: "invalid" }, "Unsupported scheme: invalid"], + ["unsupported network", { network: "base-sepolia" as never }, "Unsupported Stellar network"], + ["invalid payTo", { payTo: "invalid-address" }, "Invalid Stellar destination address"], + ["invalid asset", { asset: "invalid-asset" }, "Invalid Stellar asset address"], + ["invalid amount (negative)", { amount: "-100" }, "Invalid amount"], + ["invalid amount (zero)", { amount: "0" }, "Invalid amount"], + ["invalid amount (non-integer)", { amount: "100.5" }, "Invalid amount"], + ["invalid amount (empty string)", { amount: "" }, "Invalid amount"], + ["invalid amount (non-numeric)", { amount: "abc" }, "Invalid amount"], + ])("should throw for %s", async (_, overrides, expectedError) => { + const client = new ExactStellarScheme(mockSigner); + if ("network" in overrides && overrides.network) { + vi.mocked(stellarUtils.isStellarNetwork).mockReturnValue(false); + } + if ("payTo" in overrides && overrides.payTo) { + vi.mocked(stellarUtils.validateStellarDestinationAddress).mockReturnValue(false); + } + if ("asset" in overrides && overrides.asset) { + vi.mocked(stellarUtils.validateStellarAssetAddress).mockReturnValue(false); + } + + await expect( + client.createPaymentPayload(2, { ...validPaymentReq, ...overrides } as PaymentRequirements), + ).rejects.toThrow(expectedError); + }); + + it("should work with both TESTNET and PUBNET networks", async () => { + const client = new ExactStellarScheme(mockSigner); + setupSuccessfulTransaction(); + + await expect(client.createPaymentPayload(2, validPaymentReq)).resolves.toBeDefined(); + + const pubnetReq = { + ...validPaymentReq, + network: STELLAR_PUBNET_CAIP2, + } as PaymentRequirements; + vi.mocked(stellarUtils.getRpcUrl).mockReturnValueOnce("https://mainnet-rpc.example.com"); + setupSuccessfulTransaction(); + + await expect(client.createPaymentPayload(2, pubnetReq)).resolves.toBeDefined(); + }); + + it("should accept G, C, or M addresses for payTo", async () => { + const client = new ExactStellarScheme(mockSigner); + const addresses = [ + validPaymentReq.payTo, // G address + "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA", // C address + "MA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KAAAAAAAAAAAAFKBA", // M address + ]; + + for (const address of addresses) { + setupSuccessfulTransaction(); + await expect( + client.createPaymentPayload(2, { ...validPaymentReq, payTo: address }), + ).resolves.toBeDefined(); + } + }); + + it("should use custom RPC URL from rpcConfig", async () => { + const client = new ExactStellarScheme(mockSigner, { url: "https://custom-rpc.example.com" }); + setupSuccessfulTransaction(); + vi.mocked(stellarUtils.getRpcUrl).mockReturnValue("https://custom-rpc.example.com"); + + await client.createPaymentPayload(2, validPaymentReq); + + expect(stellarUtils.getRpcUrl).toHaveBeenCalledWith( + STELLAR_TESTNET_CAIP2, + expect.objectContaining({ url: "https://custom-rpc.example.com" }), + ); + }); + + it("should throw for PUBNET without custom RPC URL", async () => { + const client = new ExactStellarScheme(mockSigner); + const pubnetReq = { + ...validPaymentReq, + network: STELLAR_PUBNET_CAIP2, + } as PaymentRequirements; + vi.mocked(stellarUtils.getRpcUrl).mockImplementation( + (network: string, rpcConfig?: RpcConfig) => { + if (network === STELLAR_PUBNET_CAIP2 && !rpcConfig?.url) { + throw new Error( + "Stellar mainnet requires a non-empty rpcUrl. For a list of RPC providers, see https://developers.stellar.org/docs/data/apis/rpc/providers#publicly-accessible-apis", + ); + } + return "https://soroban-testnet.stellar.org"; + }, + ); + + await expect(client.createPaymentPayload(2, pubnetReq)).rejects.toThrow( + /Stellar mainnet requires a non-empty rpcUrl/, + ); + }); + + it.each([ + ["wrong signer", ["DIFFERENT_ADDRESS"]], + ["multiple signers", [mockSignerAddress, "ANOTHER_ADDRESS"]], + ])("should throw if %s is needed", async (_, signers) => { + const client = new ExactStellarScheme(mockSigner); + mockTransaction.needsNonInvokerSigningBy.mockReturnValueOnce(signers); + await expect(client.createPaymentPayload(2, validPaymentReq)).rejects.toThrow( + /Expected to sign with/, + ); + }); + + it("should throw if signers still missing after signing", async () => { + const client = new ExactStellarScheme(mockSigner); + mockTransaction.needsNonInvokerSigningBy.mockReturnValueOnce([mockSignerAddress]); + mockTransaction.needsNonInvokerSigningBy.mockReturnValueOnce(["STILL_MISSING"]); + + await expect(client.createPaymentPayload(2, validPaymentReq)).rejects.toThrow( + /unexpected signer\(s\) required/, + ); + }); + + it.each([ + [ + "TESTNET", + STELLAR_TESTNET_CAIP2, + "Test SDF Network ; September 2015", + "https://soroban-testnet.stellar.org", + undefined, + ], + [ + "PUBNET", + STELLAR_PUBNET_CAIP2, + "Public Global Stellar Network ; September 2015", + "https://mainnet-rpc.example.com", + { url: "https://mainnet-rpc.example.com" }, + ], + ])( + "should build, sign, and return correct payment for %s", + async (_, network, passphrase, rpcUrl, rpcConfig) => { + const client = new ExactStellarScheme(mockSigner, rpcConfig); + setupSuccessfulTransaction(); + const req = { ...validPaymentReq, network } as PaymentRequirements; + vi.mocked(stellarUtils.getRpcUrl).mockReturnValue(rpcUrl); + + const result = await client.createPaymentPayload(2, req); + + expect(mockAssembledTransactionBuild).toHaveBeenCalledWith({ + contractId: req.asset, + method: "transfer", + args: [ + nativeToScVal(mockSignerAddress, { type: "address" }), + nativeToScVal(req.payTo, { type: "address" }), + nativeToScVal(req.amount, { type: "i128" }), + ], + networkPassphrase: passphrase, + rpcUrl, + parseResultXdr: expect.any(Function), + }); + // Expiration is calculated as currentLedger (100000) + ceil(maxTimeoutSeconds / 5) = 100012 + expect(mockTransaction.signAuthEntries).toHaveBeenCalledWith({ + address: mockSignerAddress, + signAuthEntry: mockSigner.signAuthEntry, + expiration: 100012, + }); + expect(mockTransaction.simulate).toHaveBeenCalled(); + expect(result).toEqual({ + x402Version: 2, + payload: { transaction: "mock-xdr" }, + }); + }, + ); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/constants.test.ts b/typescript/packages/mechanisms/stellar/test/unit/constants.test.ts new file mode 100644 index 0000000000..27300f91ef --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/constants.test.ts @@ -0,0 +1,98 @@ +import { describe, it, expect } from "vitest"; +import { + STELLAR_ASSET_ADDRESS_REGEX, + STELLAR_DESTINATION_ADDRESS_REGEX, +} from "../../src/constants"; + +describe("STELLAR_DESTINATION_ADDRESS_REGEX", () => { + it("should match valid G-accounts (56 characters)", () => { + const validGAccounts = [ + "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", + "G" + "A".repeat(27) + "2".repeat(28), + ]; + + validGAccounts.forEach(address => { + expect(STELLAR_DESTINATION_ADDRESS_REGEX.test(address)).toBe(true); + }); + }); + + it("should match valid C-accounts (56 characters)", () => { + const validCAccounts = [ + "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75", + "C" + "B".repeat(27) + "2".repeat(28), + ]; + + validCAccounts.forEach(address => { + expect(STELLAR_DESTINATION_ADDRESS_REGEX.test(address)).toBe(true); + }); + }); + + it("should match valid M-accounts (69 characters)", () => { + const validMAccounts = [ + "MA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KAAAAAAAAAAAAFKBA", + "M" + "C".repeat(34) + "3".repeat(34), + ]; + + validMAccounts.forEach(address => { + expect(STELLAR_DESTINATION_ADDRESS_REGEX.test(address)).toBe(true); + }); + }); + + it("should reject invalid Stellar addresses", () => { + const invalidAddresses = [ + "", // Empty string + "G", // Just prefix (too short) + "C", // Just prefix (too short) + "M", // Just prefix (too short) + "G" + "A".repeat(56), // G-account too long (57 chars) + "GA" + "2".repeat(53), // G-account too short (55 chars) + "C" + "B".repeat(56), // C-account too long (57 chars) + "CA" + "2".repeat(53), // C-account too short (55 chars) + "M" + "C".repeat(69), // M-account too long (70 chars) + "MA" + "3".repeat(66), // M-account too short (68 chars) + "XA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Invalid prefix 'X' + "GE5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Invalid second character + "gA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Lowercase prefix + "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN ", // Space character + "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN-", // Hyphen character + "0xGA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // EVM-style prefix + "ME5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KAAAAAAAAAAAAFKBA", // invalid second character in M-account + ]; + + invalidAddresses.forEach(address => { + expect(STELLAR_DESTINATION_ADDRESS_REGEX.test(address)).toBe(false); + }); + }); +}); + +describe("STELLAR_ASSET_ADDRESS_REGEX", () => { + it("should match valid C-accounts (56 characters)", () => { + const validCAccounts = [ + "CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75", + "C" + "B".repeat(27) + "2".repeat(28), + ]; + + validCAccounts.forEach(address => { + expect(STELLAR_ASSET_ADDRESS_REGEX.test(address)).toBe(true); + }); + }); + + it("should reject invalid Stellar addresses", () => { + const invalidAddresses = [ + "", // Empty string + "C", // Just prefix (too short) + "C" + "B".repeat(56), // C-account too long (57 chars) + "CA" + "2".repeat(53), // C-account too short (55 chars) + "XA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Invalid prefix 'X' + "CE5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Invalid second character + "cA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Lowercase prefix + "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // G-account + "MA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KAAAAAAAAAAAAFKBA", // M-account + "0xGA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // EVM-style prefix + ]; + + invalidAddresses.forEach(address => { + expect(STELLAR_ASSET_ADDRESS_REGEX.test(address)).toBe(false); + }); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts b/typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts new file mode 100644 index 0000000000..84d34fbdc5 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts @@ -0,0 +1,89 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { STELLAR_TESTNET_CAIP2 } from "../../src/constants"; +import { ExactStellarScheme } from "../../src/exact/facilitator/scheme"; +import { createEd25519Signer } from "../../src/signer"; +import * as stellarUtils from "../../src/utils"; + +vi.mock("../../src/utils", async () => { + const actual = await vi.importActual("../../src/utils"); + return { + ...actual, + getRpcClient: vi.fn(), + }; +}); + +describe("ExactStellarScheme - getExtra", () => { + const mockRpcClient = { + getLatestLedger: vi.fn(), + }; + let scheme: ExactStellarScheme; + + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockRpcClient as never); + }); + + it("should return areFeesSponsored", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer]); + + const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); + + expect(result).toEqual({ areFeesSponsored: true }); + expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); + }); + + it("should return consistent areFeesSponsored on each call", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer]); + + const result1 = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result1).toEqual({ areFeesSponsored: true }); + + const result2 = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result2).toEqual({ areFeesSponsored: true }); + + expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); + }); + + it("should use custom areFeesSponsored", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer], { areFeesSponsored: false }); + + const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result).toEqual({ areFeesSponsored: false }); + }); + + it("should return consistent areFeesSponsored with multiple signers", () => { + const signer1 = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + const signer2 = createEd25519Signer( + "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer1, signer2]); + + // Call getExtra multiple times to ensure consistency + for (let i = 0; i < 10; i++) { + const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result).toEqual({ areFeesSponsored: true }); + } + + expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/facilitator-settle.test.ts b/typescript/packages/mechanisms/stellar/test/unit/facilitator-settle.test.ts new file mode 100644 index 0000000000..804d81d72c --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/facilitator-settle.test.ts @@ -0,0 +1,546 @@ +import { Buffer } from "buffer"; +import { + Networks as StellarNetworks, + rpc, + Account, + SorobanDataBuilder, + TransactionBuilder, + FeeBumpTransaction, +} from "@stellar/stellar-sdk"; +import { Api } from "@stellar/stellar-sdk/rpc"; +import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { STELLAR_TESTNET_CAIP2 } from "../../src/constants"; +import { ExactStellarScheme } from "../../src/exact/facilitator/scheme"; +import { createEd25519Signer } from "../../src/signer"; +import * as stellarUtils from "../../src/utils"; +import type { FacilitatorStellarSigner } from "../../src/signer"; +import type { PaymentPayload, PaymentRequirements } from "@x402/core/types"; + +vi.mock("../../src/utils", async () => { + const actual = await vi.importActual("../../src/utils"); + return { + ...actual, + getNetworkPassphrase: vi.fn(), + getRpcUrl: vi.fn(), + getRpcClient: vi.fn(), + }; +}); + +describe("ExactStellarScheme - Settle (randomly using 1-2 facilitator signers)", () => { + const CLIENT_PUBLIC = "GBBO4ZDDZTSM2IUKQYBAST3CFHNPFXECGEFTGWTA2WELR2BIWDK57UVE"; + const FACILITATOR_SECRET_1 = "SCKB3ECHCPVM4HJPNCQWTQWJJ5XRL6UNKLTTCIH4B7TB22NKJ5GUFMIV"; + const FACILITATOR_PUBLIC_1 = "GCQAXB2D77Y4C66CTGVH25H2RMUKMQJGOWUPK7UXGG5MAQBONUEKFQ4P"; + const FACILITATOR_SECRET_2 = "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK"; + const FACILITATOR_PUBLIC_2 = "GDEDUVINLPX4AN7HYK3MZGY6YDQSNVJT657CVWHEM3QMAH4QHSGLIHVI"; + // The transaction's recipient (different from facilitator signer address) + const TRANSACTION_RECIPIENT = "GCHEI4PQEFJOA27MNZRPQNLGURS6KASW76X5UZCUZIXCOJLKXYCXOR2W"; + const ASSET = "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"; + + const validRequirements: PaymentRequirements = { + scheme: "exact", + network: STELLAR_TESTNET_CAIP2, + amount: "10000", // Extracted from transaction XDR + payTo: TRANSACTION_RECIPIENT, // Must match transaction's recipient + maxTimeoutSeconds: 60, + asset: ASSET, + extra: { + areFeesSponsored: true, + }, + }; + + const facilitatorSigner1 = createEd25519Signer(FACILITATOR_SECRET_1, STELLAR_TESTNET_CAIP2); + const facilitatorSigner2 = createEd25519Signer(FACILITATOR_SECRET_2, STELLAR_TESTNET_CAIP2); + + let facilitatorSigners: FacilitatorStellarSigner[]; + let validPayload: PaymentPayload; + let facilitator: ExactStellarScheme; + let mockSignedTxXdr: string; + let mockServer: rpc.Server; + + // Use a real transaction XDR from shared test (base64 encoded JSON with tx field) + const signedTxJson = + "eyJtZXRob2QiOiJ0cmFuc2ZlciIsInR4IjoiQUFBQUFnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQURsM0lBQUFBQUFBQUFBUUFBQUFFQUFBQUFBQUFBQUFBQUFBQnBGcEdGQUFBQUFBQUFBQUVBQUFBQUFBQUFHQUFBQUFBQUFBQUJVRVhOWHNCeW1uYVAxYTBDVUZoUzMwOENqYzZERGxyRklnbTZTRWc3THdFQUFBQUlkSEpoYm5ObVpYSUFBQUFEQUFBQUVnQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBU0FBQUFBQUFBQUFDT1JISHdJVkxnYSt4dVl2ZzFacVJsNVFKVy82L2FaRlRLTGljbGFyNEZkd0FBQUFvQUFBQUFBQUFBQUFBQUFBQUFBQ2NRQUFBQUFRQUFBQUVBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZlh4amsrOHlZOGhnQUk4ck9BQUFBRUFBQUFBRUFBQUFCQUFBQUVRQUFBQUVBQUFBQ0FBQUFEd0FBQUFwd2RXSnNhV05mYTJWNUFBQUFBQUFOQUFBQUlFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUR3QUFBQWx6YVdkdVlYUjFjbVVBQUFBQUFBQU5BQUFBUUl2bjJjU3VLbFl5TU96T0pTWnkwc0VaN3dkN1QwYmdSQ0ZxZjg1M3VXQXFVcjE1ZUpycXNqVjROUVpTQW05WXNWbHZEcEUrSFRLc3pUQUVBaTJBRkFnQUFBQUFBQUFBQVZCRnpWN0FjcHAyajlXdEFsQllVdDlQQW8zT2d3NWF4U0lKdWtoSU95OEJBQUFBQ0hSeVlXNXpabVZ5QUFBQUF3QUFBQklBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFFZ0FBQUFBQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUtBQUFBQUFBQUFBQUFBQUFBQUFBbkVBQUFBQUFBQUFBQkFBQUFBQUFBQUFJQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBQmdBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFCUUFBQUFCQUFBQUF3QUFBQUVBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFFQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUJWVk5FUXdBQUFBQkNQbjBGOHV5dnYrd1pLeUZhUHh2cGF1MjQyT2NDVkt2alFUNENCOTVXc2dBQUFBWUFBQUFBQUFBQUFFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUZWOFk1UHZNbVBJWUFBQUFBQUFMNVRFQUFBRjRBQUFCTkFBQUFBQUFBNWNPQUFBQUFBPT0iLCJzaW11bGF0aW9uUmVzdWx0Ijp7ImF1dGgiOlsiQUFBQUFRQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDlmR09UN3pKanlHQUFBQUFBQUFBQUJBQUFBQUFBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFBaDBjbUZ1YzJabGNnQUFBQU1BQUFBU0FBQUFBQUFBQUFCQzdtUmp6T1ROSW9xR0FnbFBZaW5hOHR5Q01Rc3pXbURWaUxqb0tMRFYzd0FBQUJJQUFBQUFBQUFBQUk1RWNmQWhVdUJyN0c1aStEVm1wR1hsQWxiL3I5cGtWTW91SnlWcXZnVjNBQUFBQ2dBQUFBQUFBQUFBQUFBQUFBQUFKeEFBQUFBQSJdLCJyZXR2YWwiOiJBQUFBQVE9PSJ9LCJzaW11bGF0aW9uVHJhbnNhY3Rpb25EYXRhIjoiQUFBQUFBQUFBQUlBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFCZ0FBQUFGUVJjMWV3SEthZG8vVnJRSlFXRkxmVHdLTnpvTU9Xc1VpQ2JwSVNEc3ZBUUFBQUJRQUFBQUJBQUFBQXdBQUFBRUFBQUFBUXU1a1k4emt6U0tLaGdJSlQySXAydkxjZ2pFTE0xcGcxWWk0NkNpdzFkOEFBQUFCVlZORVF3QUFBQUJDUG4wRjh1eXZ2K3daS3lGYVB4dnBhdTI0Mk9jQ1ZLdmpRVDRDQjk1V3NnQUFBQUVBQUFBQWprUng4Q0ZTNEd2c2JtTDROV2FrWmVVQ1Z2K3YybVJVeWk0bkpXcStCWGNBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFZQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBRlY4WTVQdk1tUElZQUFBQUFBQUw1VEVBQUFGNEFBQUJOQUFBQUFBQUE1Y08ifQ=="; + const { tx: mockTransactionXDR } = JSON.parse( + Buffer.from(signedTxJson, "base64").toString("utf8"), + ); + + beforeAll(async () => { + vi.mocked(stellarUtils.getNetworkPassphrase).mockReturnValue(StellarNetworks.TESTNET); + vi.mocked(stellarUtils.getRpcUrl).mockReturnValue("https://soroban-testnet.stellar.org"); + + // Build full V2 PaymentPayload with mocked transaction + validPayload = { + x402Version: 2, + resource: { + url: "https://example.com/resource", + description: "Test payment", + mimeType: "application/json", + }, + accepted: validRequirements, + payload: { + transaction: mockTransactionXDR, + }, + }; + + // Use the same XDR for signed transaction + mockSignedTxXdr = mockTransactionXDR; + }); + + beforeEach(() => { + // Random selection for 1-2 facilitators + const useTwoFacilitators = Math.random() > 0.5; + facilitatorSigners = useTwoFacilitators + ? [facilitatorSigner1, facilitatorSigner2] + : [facilitatorSigner1]; + facilitator = new ExactStellarScheme(facilitatorSigners); + + // Create a fresh mock server for each test + mockServer = { + getAccount: vi.fn().mockImplementation(async addr => new Account(addr, "100")), + sendTransaction: vi.fn().mockResolvedValue({ + status: "PENDING", + hash: "test-tx-hash-123", + } as Api.SendTransactionResponse), + getTransaction: vi + .fn() + .mockResolvedValue({ status: "SUCCESS" } as Api.GetTransactionResponse), + getLatestLedger: vi.fn().mockResolvedValue({ sequence: 100000 }), + simulateTransaction: vi.fn().mockResolvedValue({ + id: "test", + latestLedger: 123, + events: [], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse), + } as unknown as rpc.Server; + + vi.clearAllMocks(); + + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockServer); + vi.mocked(stellarUtils.getNetworkPassphrase).mockReturnValue(StellarNetworks.TESTNET); + vi.mocked(stellarUtils.getRpcUrl).mockReturnValue("https://soroban-testnet.stellar.org"); + + // Mock verify to pass for settle tests (verify is tested separately) + // The expiration check may reject the test transaction, so we mock verify for settle tests + // Note: This is reset in tests that need to test actual verify behavior + vi.spyOn(facilitator, "verify").mockImplementation(async () => ({ + isValid: true, + payer: CLIENT_PUBLIC, + })); + + // Mock signTransaction for all signers to return the mock signed XDR + vi.spyOn(facilitatorSigner1, "signTransaction").mockResolvedValue({ + signedTxXdr: mockSignedTxXdr, + error: undefined, + }); + vi.spyOn(facilitatorSigner2, "signTransaction").mockResolvedValue({ + signedTxXdr: mockSignedTxXdr, + error: undefined, + }); + }); + + describe("settlement failures", () => { + it("should return error when verify fails", async () => { + vi.spyOn(facilitator, "verify").mockRestore(); + // Use requirements with wrong amount to make verify fail + const invalidRequirements = { + ...validRequirements, + amount: "9999", // Wrong amount (transaction has 10000) + }; + + const result = await facilitator.settle(validPayload, invalidRequirements); + + expect(result.success).toBe(false); + expect(result.errorReason).toBe("invalid_exact_stellar_payload_wrong_amount"); + expect(result.payer).toBe(CLIENT_PUBLIC); + expect(result.network).toBe(STELLAR_TESTNET_CAIP2); + expect(result.transaction).toBe(""); + expect(mockServer.sendTransaction).not.toHaveBeenCalled(); + }); + + it("should return error when signing fails", async () => { + vi.spyOn(facilitatorSigner1, "signTransaction").mockResolvedValue({ + signedTxXdr: "", + error: { code: 1, message: "Signing failed" }, + }); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result).toEqual({ + success: false, + errorReason: "settle_exact_stellar_transaction_signing_failed", + payer: CLIENT_PUBLIC, + network: STELLAR_TESTNET_CAIP2, + transaction: "", + }); + }); + + it("should return error when transaction submission returns non-PENDING status", async () => { + vi.mocked(mockServer.sendTransaction).mockResolvedValue({ + status: "TRY_AGAIN_LATER", + hash: "", + } as Api.SendTransactionResponse); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result).toEqual({ + success: false, + errorReason: "settle_exact_stellar_transaction_submission_failed", + payer: CLIENT_PUBLIC, + network: STELLAR_TESTNET_CAIP2, + transaction: "", + }); + }); + + it("should return error when transaction confirmation fails", async () => { + vi.mocked(mockServer.sendTransaction).mockResolvedValue({ + status: "PENDING", + hash: "test-tx-hash-123", + } as Api.SendTransactionResponse); + vi.mocked(mockServer.getTransaction).mockResolvedValue({ + status: "FAILED", + } as Api.GetTransactionResponse); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result).toEqual({ + success: false, + errorReason: "settle_exact_stellar_transaction_failed", + payer: CLIENT_PUBLIC, + network: STELLAR_TESTNET_CAIP2, + transaction: "test-tx-hash-123", + }); + }); + + it("should return error when transaction confirmation times out", async () => { + vi.mocked(mockServer.sendTransaction).mockResolvedValue({ + status: "PENDING", + hash: "test-tx-hash-123", + } as Api.SendTransactionResponse); + vi.mocked(mockServer.getTransaction).mockResolvedValue({ + status: "NOT_FOUND", + } as Api.GetTransactionResponse); + + const result = await facilitator.settle(validPayload, { + ...validRequirements, + maxTimeoutSeconds: 1, + }); + + expect(result).toEqual({ + success: false, + errorReason: "settle_exact_stellar_transaction_failed", + payer: CLIENT_PUBLIC, + network: STELLAR_TESTNET_CAIP2, + transaction: "test-tx-hash-123", + }); + }); + + it("should handle unexpected errors during account fetch", async () => { + vi.mocked(mockServer.getAccount).mockRejectedValue(new Error("Network error")); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result).toEqual({ + success: false, + errorReason: "unexpected_settle_error", + payer: CLIENT_PUBLIC, + network: STELLAR_TESTNET_CAIP2, + transaction: "", + }); + }); + }); + + describe("successful settlement", () => { + it("should successfully settle valid payment", async () => { + vi.mocked(mockServer.sendTransaction).mockResolvedValue({ + status: "PENDING", + hash: "test-tx-hash-123", + } as Api.SendTransactionResponse); + vi.mocked(mockServer.getTransaction).mockResolvedValue({ + status: "SUCCESS", + } as Api.GetTransactionResponse); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result).toEqual({ + success: true, + transaction: "test-tx-hash-123", + payer: CLIENT_PUBLIC, + network: STELLAR_TESTNET_CAIP2, + }); + + // Verify getAccount was called with one of the facilitator addresses + expect(mockServer.getAccount).toHaveBeenCalledTimes(1); + const calledWithAddress = vi.mocked(mockServer.getAccount).mock.calls[0][0]; + expect(facilitator.signingAddresses).toContain(calledWithAddress); + expect(mockServer.sendTransaction).toHaveBeenCalled(); + expect(mockServer.getTransaction).toHaveBeenCalledWith("test-tx-hash-123"); + }); + + it("should poll until transaction succeeds", async () => { + let callCount = 0; + vi.mocked(mockServer.getTransaction).mockImplementation(async () => { + callCount++; + if (callCount < 3) { + return { status: "NOT_FOUND" } as Api.GetTransactionResponse; + } + return { status: "SUCCESS" } as Api.GetTransactionResponse; + }); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result.success).toBe(true); + expect(mockServer.getTransaction).toHaveBeenCalledTimes(3); + }); + + it("should continue polling on errors", async () => { + let callCount = 0; + vi.mocked(mockServer.getTransaction).mockImplementation(async () => { + callCount++; + if (callCount === 1) { + throw new Error("Temporary network error"); + } + return { status: "SUCCESS" } as Api.GetTransactionResponse; + }); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result.success).toBe(true); + expect(mockServer.getTransaction).toHaveBeenCalledTimes(2); + }); + }); + + describe("multi-signer tests", () => { + const multiSigners: FacilitatorStellarSigner[] = [facilitatorSigner1, facilitatorSigner2]; + + it("should use custom selectSigner callback", async () => { + const customFacilitator = new ExactStellarScheme(multiSigners, { + selectSigner: addrs => addrs[1], + }); + + vi.spyOn(customFacilitator, "verify").mockResolvedValue({ + isValid: true, + payer: CLIENT_PUBLIC, + }); + + const result = await customFacilitator.settle(validPayload, validRequirements); + + expect(result.success).toBe(true); + expect(mockServer.getAccount).toHaveBeenCalledWith(FACILITATOR_PUBLIC_2); + expect(facilitatorSigner2.signTransaction).toHaveBeenCalled(); + expect(facilitatorSigner1.signTransaction).not.toHaveBeenCalled(); + }); + + it("should use round-robin by default with multiple signers", async () => { + const roundRobinFacilitator = new ExactStellarScheme(multiSigners); + + vi.spyOn(roundRobinFacilitator, "verify").mockResolvedValue({ + isValid: true, + payer: CLIENT_PUBLIC, + }); + + const calledAddresses: string[] = []; + + for (let i = 0; i < 4; i++) { + await roundRobinFacilitator.settle(validPayload, validRequirements); + const callArgs = vi.mocked(mockServer.getAccount).mock.calls[i]; + calledAddresses.push(callArgs[0]); + } + + // Verify round-robin pattern: [addr1, addr2, addr1, addr2] + expect(calledAddresses).toEqual([ + FACILITATOR_PUBLIC_1, + FACILITATOR_PUBLIC_2, + FACILITATOR_PUBLIC_1, + FACILITATOR_PUBLIC_2, + ]); + }); + }); +}); + +describe("ExactStellarScheme - Settle with feeBumpSigner", () => { + const CLIENT_PUBLIC = "GBBO4ZDDZTSM2IUKQYBAST3CFHNPFXECGEFTGWTA2WELR2BIWDK57UVE"; + const FACILITATOR_SECRET_1 = "SCKB3ECHCPVM4HJPNCQWTQWJJ5XRL6UNKLTTCIH4B7TB22NKJ5GUFMIV"; + const FACILITATOR_SECRET_2 = "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK"; + // A separate keypair for the fee bump signer + const FEE_BUMP_SECRET = "SACGSSH2Y7Q6P6BK3BBKGH5Z2RDSQQGD2XHOCDYQN7N6BU37HE2OLKMD"; + const FEE_BUMP_PUBLIC = "GDBNQWJ67SGPPEZ2GALX5W5YGT2NACBJQDK64T6WXDGJNAA4IPWIULMV"; + const TRANSACTION_RECIPIENT = "GCHEI4PQEFJOA27MNZRPQNLGURS6KASW76X5UZCUZIXCOJLKXYCXOR2W"; + const ASSET = "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"; + + const validRequirements: PaymentRequirements = { + scheme: "exact", + network: STELLAR_TESTNET_CAIP2, + amount: "10000", + payTo: TRANSACTION_RECIPIENT, + maxTimeoutSeconds: 60, + asset: ASSET, + extra: { + areFeesSponsored: true, + }, + }; + + const facilitatorSigner1 = createEd25519Signer(FACILITATOR_SECRET_1, STELLAR_TESTNET_CAIP2); + const facilitatorSigner2 = createEd25519Signer(FACILITATOR_SECRET_2, STELLAR_TESTNET_CAIP2); + const feeBumpSigner = createEd25519Signer(FEE_BUMP_SECRET, STELLAR_TESTNET_CAIP2); + + let validPayload: PaymentPayload; + let mockSignedTxXdr: string; + let mockServer: rpc.Server; + + const signedTxJson = + "eyJtZXRob2QiOiJ0cmFuc2ZlciIsInR4IjoiQUFBQUFnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQURsM0lBQUFBQUFBQUFBUUFBQUFFQUFBQUFBQUFBQUFBQUFBQnBGcEdGQUFBQUFBQUFBQUVBQUFBQUFBQUFHQUFBQUFBQUFBQUJVRVhOWHNCeW1uYVAxYTBDVUZoUzMwOENqYzZERGxyRklnbTZTRWc3THdFQUFBQUlkSEpoYm5ObVpYSUFBQUFEQUFBQUVnQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBU0FBQUFBQUFBQUFDT1JISHdJVkxnYSt4dVl2ZzFacVJsNVFKVy82L2FaRlRLTGljbGFyNEZkd0FBQUFvQUFBQUFBQUFBQUFBQUFBQUFBQ2NRQUFBQUFRQUFBQUVBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZlh4amsrOHlZOGhnQUk4ck9BQUFBRUFBQUFBRUFBQUFCQUFBQUVRQUFBQUVBQUFBQ0FBQUFEd0FBQUFwd2RXSnNhV05mYTJWNUFBQUFBQUFOQUFBQUlFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUR3QUFBQWx6YVdkdVlYUjFjbVVBQUFBQUFBQU5BQUFBUUl2bjJjU3VLbFl5TU96T0pTWnkwc0VaN3dkN1QwYmdSQ0ZxZjg1M3VXQXFVcjE1ZUpycXNqVjROUVpTQW05WXNWbHZEcEUrSFRLc3pUQUVBaTJBRkFnQUFBQUFBQUFBQVZCRnpWN0FjcHAyajlXdEFsQllVdDlQQW8zT2d3NWF4U0lKdWtoSU95OEJBQUFBQ0hSeVlXNXpabVZ5QUFBQUF3QUFBQklBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFFZ0FBQUFBQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUtBQUFBQUFBQUFBQUFBQUFBQUFBbkVBQUFBQUFBQUFBQkFBQUFBQUFBQUFJQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBQmdBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFCUUFBQUFCQUFBQUF3QUFBQUVBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFFQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUJWVk5FUXdBQUFBQkNQbjBGOHV5dnYrd1pLeUZhUHh2cGF1MjQyT2NDVkt2alFUNENCOTVXc2dBQUFBWUFBQUFBQUFBQUFFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUZWOFk1UHZNbVBJWUFBQUFBQUFMNVRFQUFBRjRBQUFCTkFBQUFBQUFBNWNPQUFBQUFBPT0iLCJzaW11bGF0aW9uUmVzdWx0Ijp7ImF1dGgiOlsiQUFBQUFRQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDlmR09UN3pKanlHQUFBQUFBQUFBQUJBQUFBQUFBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFBaDBjbUZ1YzJabGNnQUFBQU1BQUFBU0FBQUFBQUFBQUFCQzdtUmp6T1ROSW9xR0FnbFBZaW5hOHR5Q01Rc3pXbURWaUxqb0tMRFYzd0FBQUJJQUFBQUFBQUFBQUk1RWNmQWhVdUJyN0c1aStEVm1wR1hsQWxiL3I5cGtWTW91SnlWcXZnVjNBQUFBQ2dBQUFBQUFBQUFBQUFBQUFBQUFKeEFBQUFBQSJdLCJyZXR2YWwiOiJBQUFBQVE9PSJ9LCJzaW11bGF0aW9uVHJhbnNhY3Rpb25EYXRhIjoiQUFBQUFBQUFBQUlBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFCZ0FBQUFGUVJjMWV3SEthZG8vVnJRSlFXRkxmVHdLTnpvTU9Xc1VpQ2JwSVNEc3ZBUUFBQUJRQUFBQUJBQUFBQXdBQUFBRUFBQUFBUXU1a1k4emt6U0tLaGdJSlQySXAydkxjZ2pFTE0xcGcxWWk0NkNpdzFkOEFBQUFCVlZORVF3QUFBQUJDUG4wRjh1eXZ2K3daS3lGYVB4dnBhdTI0Mk9jQ1ZLdmpRVDRDQjk1V3NnQUFBQUVBQUFBQWprUng4Q0ZTNEd2c2JtTDROV2FrWmVVQ1Z2K3YybVJVeWk0bkpXcStCWGNBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFZQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBRlY4WTVQdk1tUElZQUFBQUFBQUw1VEVBQUFGNEFBQUJOQUFBQUFBQUE1Y08ifQ=="; + const { tx: mockTransactionXDR } = JSON.parse( + Buffer.from(signedTxJson, "base64").toString("utf8"), + ); + + beforeAll(async () => { + vi.mocked(stellarUtils.getNetworkPassphrase).mockReturnValue(StellarNetworks.TESTNET); + vi.mocked(stellarUtils.getRpcUrl).mockReturnValue("https://soroban-testnet.stellar.org"); + + validPayload = { + x402Version: 2, + resource: { + url: "https://example.com/resource", + description: "Test payment", + mimeType: "application/json", + }, + accepted: validRequirements, + payload: { + transaction: mockTransactionXDR, + }, + }; + + mockSignedTxXdr = mockTransactionXDR; + }); + + beforeEach(() => { + mockServer = { + getAccount: vi.fn().mockImplementation(async addr => new Account(addr, "100")), + sendTransaction: vi.fn().mockResolvedValue({ + status: "PENDING", + hash: "test-tx-hash-fee-bump", + } as Api.SendTransactionResponse), + getTransaction: vi + .fn() + .mockResolvedValue({ status: "SUCCESS" } as Api.GetTransactionResponse), + getLatestLedger: vi.fn().mockResolvedValue({ sequence: 100000 }), + simulateTransaction: vi.fn().mockResolvedValue({ + id: "test", + latestLedger: 123, + events: [], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse), + } as unknown as rpc.Server; + + vi.clearAllMocks(); + + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockServer); + vi.mocked(stellarUtils.getNetworkPassphrase).mockReturnValue(StellarNetworks.TESTNET); + vi.mocked(stellarUtils.getRpcUrl).mockReturnValue("https://soroban-testnet.stellar.org"); + + // Mock signTransaction for all signers to return the mock signed XDR + vi.spyOn(facilitatorSigner1, "signTransaction").mockResolvedValue({ + signedTxXdr: mockSignedTxXdr, + error: undefined, + }); + vi.spyOn(facilitatorSigner2, "signTransaction").mockResolvedValue({ + signedTxXdr: mockSignedTxXdr, + error: undefined, + }); + }); + + it("should wrap inner tx in FeeBumpTransaction when feeBumpSigner is set", async () => { + // Mock the fee bump signer to return a properly signed fee bump XDR + const feeBumpSignSpy = vi + .spyOn(feeBumpSigner, "signTransaction") + .mockImplementation(async (txXdr, opts) => { + // Verify the input is a fee bump transaction + const parsed = TransactionBuilder.fromXDR( + txXdr, + opts?.networkPassphrase ?? StellarNetworks.TESTNET, + ); + expect(parsed).toBeInstanceOf(FeeBumpTransaction); + const fbTx = parsed as FeeBumpTransaction; + expect(fbTx.feeSource).toBe(FEE_BUMP_PUBLIC); + // Return the same XDR (mock β€” no real signature needed for send mock) + return { signedTxXdr: txXdr, error: undefined }; + }); + + const facilitator = new ExactStellarScheme([facilitatorSigner1], { feeBumpSigner }); + vi.spyOn(facilitator, "verify").mockResolvedValue({ isValid: true, payer: CLIENT_PUBLIC }); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result.success).toBe(true); + expect(result.transaction).toBe("test-tx-hash-fee-bump"); + // Inner tx signer called first + expect(facilitatorSigner1.signTransaction).toHaveBeenCalledTimes(1); + // Fee bump signer called second + expect(feeBumpSignSpy).toHaveBeenCalledTimes(1); + // The submitted transaction should be a FeeBumpTransaction + const submitCall = vi.mocked(mockServer.sendTransaction).mock.calls[0][0]; + expect(submitCall).toBeInstanceOf(FeeBumpTransaction); + }); + + it("should return error when fee bump signing fails", async () => { + vi.spyOn(feeBumpSigner, "signTransaction").mockResolvedValue({ + signedTxXdr: "", + error: { code: 1, message: "Fee bump signing failed" }, + }); + + const facilitator = new ExactStellarScheme([facilitatorSigner1], { feeBumpSigner }); + vi.spyOn(facilitator, "verify").mockResolvedValue({ isValid: true, payer: CLIENT_PUBLIC }); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result.success).toBe(false); + expect(result.errorReason).toBe("settle_exact_stellar_fee_bump_signing_failed"); + expect(result.payer).toBe(CLIENT_PUBLIC); + // Inner tx signing should have succeeded + expect(facilitatorSigner1.signTransaction).toHaveBeenCalledTimes(1); + // Transaction should not have been submitted + expect(mockServer.sendTransaction).not.toHaveBeenCalled(); + }); + + it("should not use fee bump when feeBumpSigner is not set", async () => { + const facilitator = new ExactStellarScheme([facilitatorSigner1]); + vi.spyOn(facilitator, "verify").mockResolvedValue({ isValid: true, payer: CLIENT_PUBLIC }); + + const result = await facilitator.settle(validPayload, validRequirements); + + expect(result.success).toBe(true); + // The submitted transaction should be a regular Transaction, not FeeBumpTransaction + const submitCall = vi.mocked(mockServer.sendTransaction).mock.calls[0][0]; + expect(submitCall).not.toBeInstanceOf(FeeBumpTransaction); + }); + + it("should use round-robin signer for inner tx while fee bump signer pays fees", async () => { + vi.spyOn(feeBumpSigner, "signTransaction").mockImplementation(async txXdr => { + return { signedTxXdr: txXdr, error: undefined }; + }); + + const facilitator = new ExactStellarScheme([facilitatorSigner1, facilitatorSigner2], { + feeBumpSigner, + }); + vi.spyOn(facilitator, "verify").mockResolvedValue({ isValid: true, payer: CLIENT_PUBLIC }); + + // First settle β€” should use signer1 for inner tx + await facilitator.settle(validPayload, validRequirements); + expect(mockServer.getAccount).toHaveBeenLastCalledWith(facilitatorSigner1.address); + + // Second settle β€” should use signer2 for inner tx (round robin) + await facilitator.settle(validPayload, validRequirements); + expect(mockServer.getAccount).toHaveBeenLastCalledWith(facilitatorSigner2.address); + + // Fee bump signer should have been called for both settlements + expect(feeBumpSigner.signTransaction).toHaveBeenCalledTimes(2); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/facilitator-verify.test.ts b/typescript/packages/mechanisms/stellar/test/unit/facilitator-verify.test.ts new file mode 100644 index 0000000000..9bd84a89f1 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/facilitator-verify.test.ts @@ -0,0 +1,1037 @@ +import { Buffer } from "buffer"; +import { + Address, + Networks as StellarNetworks, + SorobanDataBuilder, + rpc, + Transaction, + TransactionBuilder, + Operation, + Account, + xdr, + Keypair, + Asset, +} from "@stellar/stellar-sdk"; +import { Api } from "@stellar/stellar-sdk/rpc"; +import { beforeEach, beforeAll, describe, expect, it, vi } from "vitest"; +import { STELLAR_TESTNET_CAIP2 } from "../../src/constants"; +import { + ExactStellarScheme, + invalidVerifyResponse, + validVerifyResponse, +} from "../../src/exact/facilitator/scheme"; +import { createEd25519Signer } from "../../src/signer"; +import * as stellarUtils from "../../src/utils"; +import type { FacilitatorStellarSigner } from "../../src/signer"; +import type { PaymentPayload, PaymentRequirements } from "@x402/core/types"; + +/** + * Creates a mock transfer event for testing event validation. + * Follows CAP-46-06 format: Topic: ["transfer", from, to, ...], Data: amount + * @see https://github.com/stellar/stellar-protocol/blob/master/core/cap-0046-06.md + * + * @param params - The parameters object + * @param params.from - The sender address + * @param params.to - The recipient address + * @param params.amount - The transfer amount as bigint + * @param params.fnName - The function name (defaults to "transfer") + * @returns A DiagnosticEvent XDR object + */ +function createMockContractEvent({ + from, + to, + amount, + fnName = "transfer", + contractId, +}: { + from: string; + to: string; + amount: bigint; + fnName?: string; + contractId?: xdr.Hash | null; +}): xdr.DiagnosticEvent { + // symbol for the function name + const transferSymbol = xdr.ScVal.scvSymbol(fnName); + + const fromKeypair = Keypair.fromPublicKey(from); + const fromScAddress = xdr.ScVal.scvAddress( + xdr.ScAddress.scAddressTypeAccount( + xdr.PublicKey.publicKeyTypeEd25519(fromKeypair.rawPublicKey()), + ), + ); + + const toKeypair = Keypair.fromPublicKey(to); + const toScAddress = xdr.ScVal.scvAddress( + xdr.ScAddress.scAddressTypeAccount( + xdr.PublicKey.publicKeyTypeEd25519(toKeypair.rawPublicKey()), + ), + ); + + const amountScVal = xdr.ScVal.scvI128( + new xdr.Int128Parts({ + lo: xdr.Uint64.fromString(amount.toString()), + hi: xdr.Int64.fromString("0"), + }), + ); + + const contractEventV0 = new xdr.ContractEventV0({ + topics: [transferSymbol, fromScAddress, toScAddress], + data: amountScVal, + }); + return createMockDiagnosticEvent( + contractEventV0, + xdr.ContractEventType.contract(), + contractId ?? null, + ); +} + +/** + * Creates a mock system diagnostic event (should be ignored by event validator). + */ +function createMockSystemEvent(): xdr.DiagnosticEvent { + return createMockDiagnosticEvent( + new xdr.ContractEventV0({ topics: [], data: xdr.ScVal.scvVoid() }), + xdr.ContractEventType.system(), + ); +} + +/** + * Creates a mock diagnostic event from a ContractEventV0 and event type. + * This helper function constructs the proper XDR structure for testing + * contract event validation in the facilitator verification process. + * + * @param v0 - The ContractEventV0 containing the event data + * @param eventType - The contract event type (contract or system) + * @param contractId - Optional contract ID (null = event has no contract; omit for backward compat) + * @returns A properly formatted DiagnosticEvent for testing + */ +function createMockDiagnosticEvent( + v0: xdr.ContractEventV0, + eventType: ReturnType = xdr.ContractEventType.contract(), + contractId: xdr.Hash | null = null, +): xdr.DiagnosticEvent { + const eventBodyXdr = xdr.ContractEventBody.toXDR( + xdr.ContractEventBody.fromXDR( + Buffer.concat([Buffer.from([0, 0, 0, 0]), xdr.ContractEventV0.toXDR(v0)]), + ), + ); + const contractEvent = new xdr.ContractEvent({ + ext: xdr.ExtensionPoint.fromXDR(Buffer.from([0, 0, 0, 0])), + contractId, + type: eventType, + body: xdr.ContractEventBody.fromXDR(eventBodyXdr), + }); + return new xdr.DiagnosticEvent({ + inSuccessfulContractCall: true, + event: contractEvent, + }); +} + +vi.mock("../../src/utils", async () => { + const actual = await vi.importActual("../../src/utils"); + return { + ...actual, + getEstimatedLedgerCloseTimeSeconds: vi.fn().mockResolvedValue(5), + getNetworkPassphrase: vi.fn(), + getRpcClient: vi.fn(), + }; +}); + +describe("ExactStellarScheme#Verify (randomly using 1-2 facilitator signers)", () => { + const mockServer = { + simulateTransaction: vi.fn(), + getLatestLedger: vi.fn(), + } as unknown as rpc.Server; + + const CLIENT_PUBLIC = "GBBO4ZDDZTSM2IUKQYBAST3CFHNPFXECGEFTGWTA2WELR2BIWDK57UVE"; + const FACILITATOR_PUBLIC = "GCQAXB2D77Y4C66CTGVH25H2RMUKMQJGOWUPK7UXGG5MAQBONUEKFQ4P"; + const TRANSACTION_RECIPIENT = "GCHEI4PQEFJOA27MNZRPQNLGURS6KASW76X5UZCUZIXCOJLKXYCXOR2W"; + const ASSET = "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"; + const networkPassphrase = StellarNetworks.TESTNET; + const account = new Account(CLIENT_PUBLIC, "100"); + + const facilitatorSigner1 = createEd25519Signer( + "SCKB3ECHCPVM4HJPNCQWTQWJJ5XRL6UNKLTTCIH4B7TB22NKJ5GUFMIV", + STELLAR_TESTNET_CAIP2, + ); + const facilitatorSigner2 = createEd25519Signer( + "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK", + STELLAR_TESTNET_CAIP2, + ); + + let stellarPayload: { transaction: string }; + let baseTransaction: Transaction; + let baseSorobanData: xdr.SorobanTransactionData | undefined; + let baseOperation: Operation.InvokeHostFunction; + let baseFunc: xdr.HostFunction; + let baseInvokeContractArgs: xdr.InvokeContractArgs; + let facilitatorSigners: FacilitatorStellarSigner[]; + let facilitator: ExactStellarScheme; + let validPayload: PaymentPayload; + let validRequirements: PaymentRequirements; + + // Use a real transaction XDR from shared test (base64 encoded JSON with tx field) + const signedTxJson = + "eyJtZXRob2QiOiJ0cmFuc2ZlciIsInR4IjoiQUFBQUFnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQURsM0lBQUFBQUFBQUFBUUFBQUFFQUFBQUFBQUFBQUFBQUFBQnBGcEdGQUFBQUFBQUFBQUVBQUFBQUFBQUFHQUFBQUFBQUFBQUJVRVhOWHNCeW1uYVAxYTBDVUZoUzMwOENqYzZERGxyRklnbTZTRWc3THdFQUFBQUlkSEpoYm5ObVpYSUFBQUFEQUFBQUVnQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBU0FBQUFBQUFBQUFDT1JISHdJVkxnYSt4dVl2ZzFacVJsNVFKVy82L2FaRlRLTGljbGFyNEZkd0FBQUFvQUFBQUFBQUFBQUFBQUFBQUFBQ2NRQUFBQUFRQUFBQUVBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZlh4amsrOHlZOGhnQUk4ck9BQUFBRUFBQUFBRUFBQUFCQUFBQUVRQUFBQUVBQUFBQ0FBQUFEd0FBQUFwd2RXSnNhV05mYTJWNUFBQUFBQUFOQUFBQUlFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUR3QUFBQWx6YVdkdVlYUjFjbVVBQUFBQUFBQU5BQUFBUUl2bjJjU3VLbFl5TU96T0pTWnkwc0VaN3dkN1QwYmdSQ0ZxZjg1M3VXQXFVcjE1ZUpycXNqVjROUVpTQW05WXNWbHZEcEUrSFRLc3pUQUVBaTJBRkFnQUFBQUFBQUFBQVZCRnpWN0FjcHAyajlXdEFsQllVdDlQQW8zT2d3NWF4U0lKdWtoSU95OEJBQUFBQ0hSeVlXNXpabVZ5QUFBQUF3QUFBQklBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFFZ0FBQUFBQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUtBQUFBQUFBQUFBQUFBQUFBQUFBbkVBQUFBQUFBQUFBQkFBQUFBQUFBQUFJQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBQmdBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFCUUFBQUFCQUFBQUF3QUFBQUVBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFFQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUJWVk5FUXdBQUFBQkNQbjBGOHV5dnYrd1pLeUZhUHh2cGF1MjQyT2NDVkt2alFUNENCOTVXc2dBQUFBWUFBQUFBQUFBQUFFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUZWOFk1UHZNbVBJWUFBQUFBQUFMNVRFQUFBRjRBQUFCTkFBQUFBQUFBNWNPQUFBQUFBPT0iLCJzaW11bGF0aW9uUmVzdWx0Ijp7ImF1dGgiOlsiQUFBQUFRQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDlmR09UN3pKanlHQUFBQUFBQUFBQUJBQUFBQUFBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFBaDBjbUZ1YzJabGNnQUFBQU1BQUFBU0FBQUFBQUFBQUFCQzdtUmp6T1ROSW9xR0FnbFBZaW5hOHR5Q01Rc3pXbURWaUxqb0tMRFYzd0FBQUJJQUFBQUFBQUFBQUk1RWNmQWhVdUJyN0c1aStEVm1wR1hsQWxiL3I5cGtWTW91SnlWcXZnVjNBQUFBQ2dBQUFBQUFBQUFBQUFBQUFBQUFKeEFBQUFBQSJdLCJyZXR2YWwiOiJBQUFBQVE9PSJ9LCJzaW11bGF0aW9uVHJhbnNhY3Rpb25EYXRhIjoiQUFBQUFBQUFBQUlBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFCZ0FBQUFGUVJjMWV3SEthZG8vVnJRSlFXRkxmVHdLTnpvTU9Xc1VpQ2JwSVNEc3ZBUUFBQUJRQUFBQUJBQUFBQXdBQUFBRUFBQUFBUXU1a1k4emt6U0tLaGdJSlQySXAydkxjZ2pFTE0xcGcxWWk0NkNpdzFkOEFBQUFCVlZORVF3QUFBQUJDUG4wRjh1eXZ2K3daS3lGYVB4dnBhdTI0Mk9jQ1ZLdmpRVDRDQjk1V3NnQUFBQUVBQUFBQWprUng4Q0ZTNEd2c2JtTDROV2FrWmVVQ1Z2K3YybVJVeWk0bkpXcStCWGNBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFZQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBRlY4WTVQdk1tUElZQUFBQUFBQUw1VEVBQUFGNEFBQUJOQUFBQUFBQUE1Y08ifQ=="; + const txSignatureExpiration = 2345678; + const { tx: baseTransactionXDR } = JSON.parse( + Buffer.from(signedTxJson, "base64").toString("utf8"), + ); + + beforeAll(async () => { + // Set up mocks + vi.mocked(stellarUtils.getNetworkPassphrase).mockReturnValue(StellarNetworks.TESTNET); + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockServer); + vi.mocked(mockServer.getLatestLedger).mockResolvedValue({ + sequence: txSignatureExpiration - 10, + } as Api.GetLatestLedgerResponse); + + // Create valid requirements (V2 format) + // Note: Values must match the transaction XDR from shared test + validRequirements = { + scheme: "exact", + network: STELLAR_TESTNET_CAIP2, + amount: "10000", // Extracted from transaction XDR + payTo: TRANSACTION_RECIPIENT, // Must match transaction's recipient + maxTimeoutSeconds: 60, + asset: ASSET, + extra: { + maxLedgerOffset: 12, + }, + }; + + // Build full V2 PaymentPayload with mocked transaction + validPayload = { + x402Version: 2, + resource: { + url: "https://example.com/resource", + description: "Test payment", + mimeType: "application/json", + }, + accepted: validRequirements, + payload: { + transaction: baseTransactionXDR, + }, + }; + + stellarPayload = validPayload.payload as { transaction: string }; + const txEnvelope = xdr.TransactionEnvelope.fromXDR(stellarPayload.transaction, "base64"); + baseTransaction = new Transaction(stellarPayload.transaction, networkPassphrase); + baseSorobanData = txEnvelope.v1()?.tx()?.ext()?.sorobanData() || undefined; + baseOperation = baseTransaction.operations[0] as Operation.InvokeHostFunction; + baseFunc = baseOperation.func; + baseInvokeContractArgs = baseFunc.invokeContract(); + }); + + /** + * Builds a modified transaction and wraps it in a PaymentPayload. + */ + function buildStellarPayloadFromOp( + operation: xdr.Operation, + options?: { includeSorobanData?: boolean }, + ): PaymentPayload { + const modifiedTx = new TransactionBuilder(account, { + fee: baseTransaction.fee, + networkPassphrase, + ledgerbounds: baseTransaction.ledgerBounds, + ...(options?.includeSorobanData !== false && + baseSorobanData && { sorobanData: baseSorobanData }), + }) + .addOperation(operation) + .setTimeout(validRequirements.maxTimeoutSeconds) + .build(); + return { + ...validPayload, + payload: { transaction: modifiedTx.toXDR() }, + }; + } + + beforeEach(() => { + // Random selection for 1-2 facilitators + const useTwoFacilitators = Math.random() > 0.5; + facilitatorSigners = useTwoFacilitators + ? [facilitatorSigner1, facilitatorSigner2] + : [facilitatorSigner1]; + + // Use a high max fee for tests to avoid fee validation errors in tests that check other validations + facilitator = new ExactStellarScheme(facilitatorSigners, { + areFeesSponsored: true, + maxTransactionFeeStroops: 1_000_000, + }); + + const expectedAssetHash = new Address(ASSET).toScAddress().contractId(); + const defaultTransferEvent = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: TRANSACTION_RECIPIENT, + amount: BigInt(validRequirements.amount), + contractId: expectedAssetHash, + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValue({ + id: "test", + latestLedger: 123, + events: [defaultTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + }); + + describe("validation errors", () => { + it("should reject invalid x402 version, scheme, and network mismatch", async () => { + let result = await facilitator.verify( + { ...validPayload, x402Version: 9 }, // ❌ unsupported x402 version + validRequirements, + ); + expect(result).toEqual(invalidVerifyResponse("invalid_x402_version")); + + result = await facilitator.verify( + { + ...validPayload, + accepted: { ...validPayload.accepted, scheme: "invalid" }, // ❌ wrong scheme + }, + validRequirements, + ); + expect(result).toEqual(invalidVerifyResponse("unsupported_scheme")); + + result = await facilitator.verify( + { + ...validPayload, + accepted: { ...validPayload.accepted, network: "foo:bar" }, // ❌ wrong network + }, + validRequirements, + ); + expect(result).toEqual(invalidVerifyResponse("network_mismatch")); + }); + + it("should reject transactions with fees exceeding the maximum", async () => { + const lowMaxFeeFacilitator = new ExactStellarScheme(facilitatorSigners, { + areFeesSponsored: true, + maxTransactionFeeStroops: 1000, // 1000 stroops max + }); + + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockServer as rpc.Server); + vi.mocked(stellarUtils.getNetworkPassphrase).mockReturnValue(StellarNetworks.TESTNET); + + const result = await lowMaxFeeFacilitator.verify(validPayload, validRequirements); + expect(result).toEqual( + invalidVerifyResponse("invalid_exact_stellar_payload_fee_exceeds_maximum"), + ); + }); + + it("should reject transactions with fees below simulation minimum", async () => { + const expectedAssetHashForFeeTest = new Address(ASSET).toScAddress().contractId(); + const mockTransferEventForFeeTest = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: TRANSACTION_RECIPIENT, + amount: BigInt("10000"), + contractId: expectedAssetHashForFeeTest, + }); + + const originalSimulate = vi.mocked(stellarUtils.getRpcClient).getMockImplementation(); + const mockServerWithHighMinFee = { + ...mockServer, + simulateTransaction: vi.fn().mockResolvedValue({ + id: "test", + latestLedger: 123, + events: [mockTransferEventForFeeTest], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "999999999", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse), + }; + + vi.mocked(stellarUtils.getRpcClient).mockReturnValue( + mockServerWithHighMinFee as unknown as rpc.Server, + ); + vi.mocked(stellarUtils.getNetworkPassphrase).mockReturnValue(StellarNetworks.TESTNET); + + try { + const result = await facilitator.verify(validPayload, validRequirements); + expect(result).toEqual( + invalidVerifyResponse("invalid_exact_stellar_payload_fee_below_minimum", CLIENT_PUBLIC), + ); + } finally { + vi.mocked(stellarUtils.getRpcClient).mockImplementation(originalSimulate!); + } + }); + + describe("mismatching networks", () => { + it("should reject mismatching requirement<>payload networks", async () => { + const requirements: PaymentRequirements = { + ...validRequirements, + network: "eip155:84532" as never, // ❌ requirements network != payload accepted + }; + const result = await facilitator.verify(validPayload, requirements); + expect(result).toEqual(invalidVerifyResponse("network_mismatch")); + }); + + it("should reject when network is not a Stellar network", async () => { + const wrongNetwork = "eip155:84532" as never; // ❌ non-Stellar network + const requirements: PaymentRequirements = { + ...validRequirements, + network: wrongNetwork, + }; + const payload: PaymentPayload = { + ...validPayload, + accepted: { ...validPayload.accepted, network: wrongNetwork }, + }; + const result = await facilitator.verify(payload, requirements); + expect(result).toEqual(invalidVerifyResponse("invalid_network")); + }); + }); + + it("should reject malformed transaction XDR", async () => { + const payload = { + ...validPayload, + payload: { transaction: "AAAA" }, // ❌ Invalid XDR + }; + const result = await facilitator.verify(payload, validRequirements); + expect(result).toEqual(invalidVerifyResponse("invalid_exact_stellar_payload_malformed")); + }); + + it("should reject wrong operation count", async () => { + expect(baseSorobanData).toBeDefined(); + + const parsedOperation = Operation.invokeHostFunction(baseOperation); + const modifiedTx = new TransactionBuilder(account, { + fee: baseTransaction.fee, + networkPassphrase, + ledgerbounds: baseTransaction.ledgerBounds, + sorobanData: baseSorobanData, + }) + .addOperation(parsedOperation) + .addOperation(parsedOperation) // ❌ Multiple operations are forbidden + .setTimeout(validRequirements.maxTimeoutSeconds) + .build(); + + const modifiedStellarPayload: PaymentPayload = { + ...validPayload, + payload: { transaction: modifiedTx.toXDR() }, + }; + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_wrong_operation"); + }); + + it("should reject wrong operation type", async () => { + const paymentOp = Operation.payment({ + // ❌ operation of unsupported type (MUST be invokeHostFunction) + destination: CLIENT_PUBLIC, + asset: Asset.native(), + amount: "1", + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(paymentOp, { + includeSorobanData: false, + }); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_wrong_operation"); + }); + + it("should reject wrong contract function name", async () => { + const wrongFuncArgs = new xdr.InvokeContractArgs({ + contractAddress: baseInvokeContractArgs.contractAddress(), + functionName: "mint", // ❌ function name MUST be "transfer" + args: baseInvokeContractArgs.args(), + }); + const modifiedFunc = xdr.HostFunction.hostFunctionTypeInvokeContract(wrongFuncArgs); + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + func: modifiedFunc, + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_wrong_function_name"); + }); + + it("should reject wrong asset, recipient, or amount", async () => { + let result = await facilitator.verify(validPayload, { + ...validRequirements, + asset: "CDNVQW44C3HALYNVQ4SOBXY5EWYTGVYXX6JPESOLQDABJI5FC5LTRRUE", // ❌ wrong asset + }); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_wrong_asset"); + + result = await facilitator.verify(validPayload, { + ...validRequirements, + payTo: "GAHPYWLK6YRN7CVYZOO4H3VDRZ7PVF5UJGLZCSPAEIKJE2XSWF5LAGER", // ❌ wrong recipient + }); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_wrong_recipient"); + expect(result.payer).toBe(CLIENT_PUBLIC); + + result = await facilitator.verify(validPayload, { + ...validRequirements, + amount: "10001", // ❌ wrong amount + }); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_wrong_amount"); + expect(result.payer).toBe(CLIENT_PUBLIC); + }); + + describe("Authorization entries and facilitator safety", () => { + it("should reject when facilitator is the payer (from address)", async () => { + const facilitatorAddress = facilitatorSigner1.address; + + if (!baseSorobanData || !baseOperation.auth?.length) { + throw new Error("Missing sorobanData or auth in test transaction"); + } + + const originalArgs = baseInvokeContractArgs.args(); + const facilitatorKeypair = Keypair.fromPublicKey(facilitatorAddress); + const facilitatorScAddress = xdr.ScVal.scvAddress( + xdr.ScAddress.scAddressTypeAccount( + xdr.PublicKey.publicKeyTypeEd25519(facilitatorKeypair.rawPublicKey()), + ), + ); + + const modifiedInvokeContractArgs = new xdr.InvokeContractArgs({ + contractAddress: baseInvokeContractArgs.contractAddress(), + functionName: baseInvokeContractArgs.functionName(), + args: [ + facilitatorScAddress, // ❌ facilitator CANNOT be the payer + originalArgs[1], + originalArgs[2], + ], + }); + const modifiedFunc = xdr.HostFunction.hostFunctionTypeInvokeContract( + modifiedInvokeContractArgs, + ); + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + func: modifiedFunc, + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_facilitator_is_payer"); + }); + + it("should reject empty auth entries array", async () => { + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + auth: [], // ❌ Empty auth array + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_no_auth_entries"); + }); + + it("should reject missing payer signature", async () => { + if (!baseSorobanData || !baseOperation.auth || baseOperation.auth.length === 0) { + throw new Error("Missing sorobanData or auth in test transaction"); + } + + const originalAuth = baseOperation.auth[0]; + const originalCreds = originalAuth.credentials().address(); + + const unsignedCreds = new xdr.SorobanAddressCredentials({ + address: originalCreds.address(), + nonce: originalCreds.nonce(), + signatureExpirationLedger: originalCreds.signatureExpirationLedger(), + signature: xdr.ScVal.scvVoid(), // ❌ payer signature is missing + }); + + const authWithoutSignature = new xdr.SorobanAuthorizationEntry({ + credentials: xdr.SorobanCredentials.sorobanCredentialsAddress(unsignedCreds), + rootInvocation: originalAuth.rootInvocation(), + }); + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + auth: [authWithoutSignature], + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_missing_payer_signature"); + expect(result.payer).toBe(CLIENT_PUBLIC); + }); + + it("should reject unexpected pending signatures", async () => { + if (!baseSorobanData || !baseOperation.auth || baseOperation.auth.length === 0) { + throw new Error("Missing sorobanData or auth in test transaction"); + } + + const originalAuth = baseOperation.auth[0]; + const originalCreds = originalAuth.credentials().address(); + + const otherKeypair = Keypair.random(); + const otherAddressScVal = xdr.ScAddress.scAddressTypeAccount( + xdr.PublicKey.publicKeyTypeEd25519(otherKeypair.rawPublicKey()), + ); + + const pendingCreds = new xdr.SorobanAddressCredentials({ + address: otherAddressScVal, + nonce: originalCreds.nonce(), + signatureExpirationLedger: originalCreds.signatureExpirationLedger(), + signature: xdr.ScVal.scvVoid(), + }); + + const pendingAuth = new xdr.SorobanAuthorizationEntry({ + credentials: xdr.SorobanCredentials.sorobanCredentialsAddress(pendingCreds), + rootInvocation: originalAuth.rootInvocation(), + }); + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + auth: [originalAuth, pendingAuth], // ❌ unexpected pending signature(s) + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe( + "invalid_exact_stellar_payload_unexpected_pending_signatures", + ); + expect(result.payer).toBe(CLIENT_PUBLIC); + }); + + it("should reject expiration ledger too far in the future", async () => { + if (!baseSorobanData || !baseOperation.auth || baseOperation.auth.length === 0) { + throw new Error("Missing sorobanData or auth in test transaction"); + } + + const originalAuth = baseOperation.auth[0]; + const originalCreds = originalAuth.credentials().address(); + const farFuture = (txSignatureExpiration + 10_000).toString(); + + const farFutureCreds = new xdr.SorobanAddressCredentials({ + address: originalCreds.address(), + nonce: originalCreds.nonce(), + signatureExpirationLedger: Number(farFuture), // ❌ Signature expiration too far + signature: originalCreds.signature(), + }); + + const authWithFarExpiration = new xdr.SorobanAuthorizationEntry({ + credentials: xdr.SorobanCredentials.sorobanCredentialsAddress(farFutureCreds), + rootInvocation: originalAuth.rootInvocation(), + }); + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + auth: [authWithFarExpiration], + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_signature_expiration_too_far"); + expect(result.payer).toBe(CLIENT_PUBLIC); + }); + + describe("credential type validation", () => { + it("should reject auth entries with non-sorobanCredentialsAddress credentials", async () => { + if (!baseSorobanData) { + throw new Error("Missing sorobanData in test transaction"); + } + + const sourceAccountAuth = xdr.SorobanAuthorizationEntry.fromXDR( + xdr.SorobanAuthorizationEntry.toXDR( + new xdr.SorobanAuthorizationEntry({ + credentials: xdr.SorobanCredentials.sorobanCredentialsSourceAccount(), // ❌ not sorobanCredentialsAddress + rootInvocation: baseOperation.auth![0].rootInvocation(), + }), + ), + ); + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + auth: [sourceAccountAuth], + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe( + "invalid_exact_stellar_payload_unsupported_credential_type", + ); + }); + }); + + describe("sub-invocation validation", () => { + it("should reject auth entries with sub-invocations", async () => { + if (!baseSorobanData || !baseOperation.auth || baseOperation.auth.length === 0) { + throw new Error("Missing sorobanData or auth in test transaction"); + } + + const originalAuth = baseOperation.auth[0]; + const originalRootInvocation = originalAuth.rootInvocation(); + + const subInvocation = new xdr.SorobanAuthorizedInvocation({ + function: originalRootInvocation.function(), + subInvocations: [], + }); + + const rootWithSubInvocations = new xdr.SorobanAuthorizedInvocation({ + function: originalRootInvocation.function(), + subInvocations: [subInvocation], // ❌ sub-invocations not allowed + }); + + const authWithSubInvocations = new xdr.SorobanAuthorizationEntry({ + credentials: originalAuth.credentials(), + rootInvocation: rootWithSubInvocations, + }); + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + auth: [authWithSubInvocations], + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_has_subinvocations"); + }); + }); + + describe("facilitator in auth entries validation", () => { + it("should reject when facilitator address is in auth entries", async () => { + if (!baseSorobanData || !baseOperation.auth || baseOperation.auth.length === 0) { + throw new Error("Missing sorobanData or auth in test transaction"); + } + + const facilitatorAddress = facilitatorSigner1.address; + const originalAuth = baseOperation.auth[0]; + const originalAddressCredentials = originalAuth.credentials().address(); + + const facilitatorKeypair = Keypair.fromPublicKey(facilitatorAddress); + const facilitatorAddressScVal = xdr.ScAddress.scAddressTypeAccount( + xdr.PublicKey.publicKeyTypeEd25519(facilitatorKeypair.rawPublicKey()), + ); + + const facilitatorCredentials = new xdr.SorobanAddressCredentials({ + address: facilitatorAddressScVal, // ❌ facilitator address in auth entry + nonce: originalAddressCredentials.nonce(), + signatureExpirationLedger: originalAddressCredentials.signatureExpirationLedger(), + signature: originalAddressCredentials.signature(), + }); + + const authWithFacilitator = new xdr.SorobanAuthorizationEntry({ + credentials: xdr.SorobanCredentials.sorobanCredentialsAddress(facilitatorCredentials), + rootInvocation: originalAuth.rootInvocation(), + }); + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + auth: [authWithFacilitator], + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_facilitator_in_auth"); + }); + }); + + describe("should reject when source is unauthorized", () => { + it("should reject operation.source == facilitatorAccount", async () => { + const facilitatorAddress = facilitatorSigner1.address; + + if (!baseSorobanData) { + throw new Error("Missing sorobanData in test transaction"); + } + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + source: facilitatorAddress, // ❌ operation source is facilitator + }); + const modifiedStellarPayload = buildStellarPayloadFromOp(modifiedOperation); + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_unsafe_tx_or_op_source"); + }); + + it("should reject transaction.source == facilitatorAccount", async () => { + const facilitatorAddress = facilitatorSigner1.address; + + if (!baseSorobanData) { + throw new Error("Missing sorobanData in test transaction"); + } + + const modifiedOperation = Operation.invokeHostFunction({ + ...baseOperation, + }); + const facilitatorAccount = new Account(facilitatorAddress, "100"); // ❌ transaction source is facilitator + const modifiedTx = new TransactionBuilder(facilitatorAccount, { + fee: baseTransaction.fee, + networkPassphrase, + ledgerbounds: baseTransaction.ledgerBounds, + sorobanData: baseSorobanData, + }) + .addOperation(modifiedOperation) + .setTimeout(validRequirements.maxTimeoutSeconds) + .build(); + + const modifiedStellarPayload: PaymentPayload = { + ...validPayload, + payload: { + transaction: modifiedTx.toXDR(), + }, + }; + + const result = await facilitator.verify(modifiedStellarPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_unsafe_tx_or_op_source"); + }); + }); + }); + + it("should reject simulation failure", async () => { + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + error: "Simulation failed", // ❌ Simulation error + events: [], + id: "test", + latestLedger: 123, + _parsed: true, + } as Api.SimulateTransactionErrorResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_simulation_failed"); + expect(result.payer).toBe(CLIENT_PUBLIC); + }); + + // Event-based balance change validation + describe("simulation event validation", () => { + const expectedAssetHash = () => new Address(ASSET).toScAddress().contractId(); + + it("should reject when simulation shows multiple transfer events", async () => { + const mockTransferEvent1 = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: TRANSACTION_RECIPIENT, + amount: BigInt(10000), + contractId: expectedAssetHash(), + }); + const mockTransferEvent2 = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: "GAHPYWLK6YRN7CVYZOO4H3VDRZ7PVF5UJGLZCSPAEIKJE2XSWF5LAGER", + amount: BigInt(5000), + contractId: expectedAssetHash(), + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [mockTransferEvent1, mockTransferEvent2], // ❌ multiple transfer events + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_multiple_transfers"); + }); + + it("should reject when transfer event has wrong from address", async () => { + const mockTransferEvent = createMockContractEvent({ + from: "GAHPYWLK6YRN7CVYZOO4H3VDRZ7PVF5UJGLZCSPAEIKJE2XSWF5LAGER", // ❌ wrong `from` address + to: FACILITATOR_PUBLIC, + amount: BigInt(10000), + contractId: expectedAssetHash(), + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [mockTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_event_wrong_from"); + }); + + it("should reject when transfer event has wrong to address", async () => { + const mockTransferEvent = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: "GAHPYWLK6YRN7CVYZOO4H3VDRZ7PVF5UJGLZCSPAEIKJE2XSWF5LAGER", // ❌ wrong `to` address + amount: BigInt(10000), + contractId: expectedAssetHash(), + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [mockTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_event_wrong_to"); + }); + + it("should reject when transfer event has wrong amount", async () => { + const mockTransferEvent = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: TRANSACTION_RECIPIENT, + amount: BigInt(5000), // ❌ wrong `amount` (expected 10000) + contractId: expectedAssetHash(), + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [mockTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_event_wrong_amount"); + }); + + it("should reject when transfer event has null contractId", async () => { + const mockTransferEvent = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: TRANSACTION_RECIPIENT, + amount: BigInt(10000), + contractId: null, + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [mockTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe( + "invalid_exact_stellar_payload_event_missing_contract_id", + ); + }); + + it("should reject when transfer event has wrong asset (contract address)", async () => { + const wrongAsset = "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC"; + const mockTransferEvent = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: TRANSACTION_RECIPIENT, + amount: BigInt(10000), + contractId: new Address(wrongAsset).toScAddress().contractId(), + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [mockTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_event_wrong_asset"); + }); + + it("should reject when no transfer events are present", async () => { + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [], // ❌ no transfer events + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_no_transfer_events"); + }); + + it("should reject when a contract event is not a transfer", async () => { + const mockNonTransferEvent = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: FACILITATOR_PUBLIC, + amount: BigInt(10000), + fnName: "mint", // ❌ event is not "transfer" + }); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [mockNonTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_stellar_payload_event_not_transfer"); + }); + + it("should ignore non-contract events and still accept valid transfer", async () => { + const mockTransferEvent = createMockContractEvent({ + from: CLIENT_PUBLIC, + to: TRANSACTION_RECIPIENT, + amount: BigInt(10000), + contractId: expectedAssetHash(), + }); + const nonContractEvent = createMockSystemEvent(); + + vi.mocked(mockServer.simulateTransaction).mockResolvedValueOnce({ + id: "test", + latestLedger: 123, + events: [nonContractEvent, mockTransferEvent], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + cost: { cpuInsns: "0", memBytes: "0" }, + results: [], + } as Api.SimulateTransactionSuccessResponse); + + const result = await facilitator.verify(validPayload, validRequirements); + expect(result.isValid).toBe(true); + }); + }); + }); + + describe("πŸŽ‰ Successful verification", () => { + it("should verify valid payment", async () => { + const result = await facilitator.verify(validPayload, validRequirements); + expect(result).toEqual(validVerifyResponse(CLIENT_PUBLIC)); + expect(stellarUtils.getRpcClient).toHaveBeenCalledWith(STELLAR_TESTNET_CAIP2, undefined); + expect(mockServer.simulateTransaction).toHaveBeenCalled(); + }); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/server.test.ts b/typescript/packages/mechanisms/stellar/test/unit/server.test.ts new file mode 100644 index 0000000000..3cc2814864 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/server.test.ts @@ -0,0 +1,156 @@ +import { describe, it, expect } from "vitest"; +import { + USDC_PUBNET_ADDRESS, + USDC_TESTNET_ADDRESS, + STELLAR_PUBNET_CAIP2, + STELLAR_TESTNET_CAIP2, +} from "../../src/constants"; +import { ExactStellarScheme } from "../../src/exact/server/scheme"; + +describe("ExactStellarScheme", () => { + const server = new ExactStellarScheme(); + + describe("parsePrice", () => { + describe("Stellar Pubnet network", () => { + const network = STELLAR_PUBNET_CAIP2; + + it("should parse dollar string prices", async () => { + const result = await server.parsePrice("$0.10", network); + expect(result.amount).toBe("1000000"); // 0.10 USDC = 1000000 smallest units (7 decimals) + expect(result.asset).toBe(USDC_PUBNET_ADDRESS); + expect(result.extra).toEqual({}); + }); + + it("should parse simple number string prices", async () => { + const result = await server.parsePrice("0.10", network); + expect(result.amount).toBe("1000000"); + expect(result.asset).toBe(USDC_PUBNET_ADDRESS); + }); + + it("should parse number prices", async () => { + const result = await server.parsePrice(0.1, network); + expect(result.amount).toBe("1000000"); + expect(result.asset).toBe(USDC_PUBNET_ADDRESS); + }); + + it("should handle larger amounts", async () => { + const result = await server.parsePrice("100.50", network); + expect(result.amount).toBe("1005000000"); // 100.50 USDC + }); + + it("should handle whole numbers", async () => { + const result = await server.parsePrice("1", network); + expect(result.amount).toBe("10000000"); // 1 USDC (7 decimals) + }); + + it("should avoid floating-point rounding error", async () => { + const result = await server.parsePrice("$4.02", network); + expect(result.amount).toBe("40200000"); // 4.02 USDC + }); + }); + + describe("Stellar Testnet network", () => { + const network = STELLAR_TESTNET_CAIP2; + + it("should use Testnet USDC address", async () => { + const result = await server.parsePrice("1.00", network); + expect(result.asset).toBe(USDC_TESTNET_ADDRESS); + expect(result.amount).toBe("10000000"); + }); + }); + + describe("pre-parsed price objects", () => { + it("should handle pre-parsed price objects with asset", async () => { + const result = await server.parsePrice( + { + amount: "123456", + asset: "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA", + extra: { foo: "bar" }, + }, + STELLAR_PUBNET_CAIP2, + ); + expect(result.amount).toBe("123456"); + expect(result.asset).toBe("CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"); + expect(result.extra).toEqual({ foo: "bar" }); + }); + + it("should throw for price objects without asset", async () => { + await expect( + async () => await server.parsePrice({ amount: "123456" } as never, STELLAR_PUBNET_CAIP2), + ).rejects.toThrow("Asset address must be specified"); + }); + }); + + describe("error cases", () => { + it("should throw for invalid money formats", async () => { + await expect( + async () => await server.parsePrice("not-a-price!", STELLAR_PUBNET_CAIP2), + ).rejects.toThrow("Invalid money format"); + }); + + it("should throw for invalid amounts", async () => { + await expect( + async () => await server.parsePrice("abc", STELLAR_PUBNET_CAIP2), + ).rejects.toThrow("Invalid money format"); + }); + }); + }); + + describe("enhancePaymentRequirements", () => { + it("should add areFeesSponsored from facilitator to payment requirements", async () => { + const requirements = { + scheme: "exact", + network: STELLAR_PUBNET_CAIP2, + asset: USDC_PUBNET_ADDRESS, + amount: "1000000", + payTo: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5", + maxTimeoutSeconds: 3600, + extra: {}, + }; + + const result = await server.enhancePaymentRequirements( + requirements as never, + { + x402Version: 2, + scheme: "exact", + network: STELLAR_PUBNET_CAIP2, + extra: { areFeesSponsored: true }, + }, + [], + ); + + expect(result).toEqual({ + ...requirements, + extra: { areFeesSponsored: true }, + }); + }); + + it("should preserve existing extra fields", async () => { + const requirements = { + scheme: "exact", + network: STELLAR_TESTNET_CAIP2, + asset: USDC_TESTNET_ADDRESS, + amount: "1000000", + payTo: "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5", + maxTimeoutSeconds: 3600, + extra: { custom: "value" }, + }; + + const result = await server.enhancePaymentRequirements( + requirements as never, + { + x402Version: 2, + scheme: "exact", + network: STELLAR_TESTNET_CAIP2, + extra: { areFeesSponsored: true }, + }, + [], + ); + + expect(result.extra).toEqual({ + areFeesSponsored: true, + custom: "value", + }); + }); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/shared.test.ts b/typescript/packages/mechanisms/stellar/test/unit/shared.test.ts new file mode 100644 index 0000000000..9f73c83b51 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/shared.test.ts @@ -0,0 +1,137 @@ +import { + SorobanDataBuilder, + xdr, + Networks as StellarNetworks, + Transaction, +} from "@stellar/stellar-sdk"; +import { AssembledTransaction } from "@stellar/stellar-sdk/contract"; +import { Api } from "@stellar/stellar-sdk/rpc"; +import { describe, it, expect, vi } from "vitest"; +import { STELLAR_TESTNET_CAIP2 } from "../../src/constants"; +import { ExactStellarScheme } from "../../src/exact/client/scheme"; +import { gatherAuthEntrySignatureStatus, handleSimulationResult } from "../../src/shared"; +import { createEd25519Signer } from "../../src/signer"; +import type { PaymentRequirements } from "@x402/core/types"; + +describe("Stellar Shared Utilities", () => { + describe("handleSimulationResult", () => { + it("should throw error when simulation is undefined", () => { + expect(() => handleSimulationResult(undefined)).toThrow("Simulation result is undefined"); + }); + + it("should throw error when simulation has type RESTORE", () => { + const mockRestoreSimulation: Api.SimulateTransactionResponse = { + id: "test-id", + latestLedger: 12345, + events: [], + _parsed: true, + result: { + auth: [], + retval: xdr.ScVal.scvVoid(), + }, + restorePreamble: { + minResourceFee: "100", + transactionData: new SorobanDataBuilder(), + }, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + } as Api.SimulateTransactionRestoreResponse; + + expect(() => handleSimulationResult(mockRestoreSimulation)).toThrow( + /Stellar simulation result has type "RESTORE"/, + ); + }); + + it("should throw error when simulation has type ERROR", () => { + const mockErrorSimulation: Api.SimulateTransactionResponse = { + id: "test-id", + latestLedger: 12345, + _parsed: true, + error: "Transaction simulation failed: insufficient balance", + } as Api.SimulateTransactionErrorResponse; + + expect(() => handleSimulationResult(mockErrorSimulation)).toThrow( + /Stellar simulation failed with error message: Transaction simulation failed: insufficient balance/, + ); + }); + + it("should handle simulation with empty error message", () => { + const mockErrorSimulation: Api.SimulateTransactionResponse = { + id: "test-id", + latestLedger: 12345, + _parsed: true, + error: "", + } as Api.SimulateTransactionErrorResponse; + + expect(() => handleSimulationResult(mockErrorSimulation)).toThrow( + /Stellar simulation failed/, + ); + }); + + it("should not throw error when simulation is successful", () => { + const mockSuccessSimulation: Api.SimulateTransactionResponse = { + id: "test-id", + latestLedger: 12345, + events: [], + _parsed: true, + transactionData: new SorobanDataBuilder(), + minResourceFee: "100", + } as Api.SimulateTransactionSuccessResponse; + + expect(() => handleSimulationResult(mockSuccessSimulation)).not.toThrow(); + }); + }); + + describe("gatherAuthEntrySignatureStatus", () => { + const CLIENT_SECRET = "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK"; + const CLIENT_PUBLIC = "GBBO4ZDDZTSM2IUKQYBAST3CFHNPFXECGEFTGWTA2WELR2BIWDK57UVE"; + + // paymenrRequirements is used to create a valid payload for the test + const paymentRequirements: PaymentRequirements = { + scheme: "exact", + network: STELLAR_TESTNET_CAIP2, + asset: "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA", + amount: "1000000", + payTo: "GCHEI4PQEFJOA27MNZRPQNLGURS6KASW76X5UZCUZIXCOJLKXYCXOR2W", + maxTimeoutSeconds: 60, + extra: { + areFeesSponsored: true, + }, + }; + + it("should identify signed accounts and no pending signatures", async () => { + const signer = createEd25519Signer(CLIENT_SECRET, STELLAR_TESTNET_CAIP2); + const signedTxJson = + "eyJtZXRob2QiOiJ0cmFuc2ZlciIsInR4IjoiQUFBQUFnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQURsM0lBQUFBQUFBQUFBUUFBQUFFQUFBQUFBQUFBQUFBQUFBQnBGcEdGQUFBQUFBQUFBQUVBQUFBQUFBQUFHQUFBQUFBQUFBQUJVRVhOWHNCeW1uYVAxYTBDVUZoUzMwOENqYzZERGxyRklnbTZTRWc3THdFQUFBQUlkSEpoYm5ObVpYSUFBQUFEQUFBQUVnQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBU0FBQUFBQUFBQUFDT1JISHdJVkxnYSt4dVl2ZzFacVJsNVFKVy82L2FaRlRLTGljbGFyNEZkd0FBQUFvQUFBQUFBQUFBQUFBQUFBQUFBQ2NRQUFBQUFRQUFBQUVBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZlh4amsrOHlZOGhnQUk4ck9BQUFBRUFBQUFBRUFBQUFCQUFBQUVRQUFBQUVBQUFBQ0FBQUFEd0FBQUFwd2RXSnNhV05mYTJWNUFBQUFBQUFOQUFBQUlFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUR3QUFBQWx6YVdkdVlYUjFjbVVBQUFBQUFBQU5BQUFBUUl2bjJjU3VLbFl5TU96T0pTWnkwc0VaN3dkN1QwYmdSQ0ZxZjg1M3VXQXFVcjE1ZUpycXNqVjROUVpTQW05WXNWbHZEcEUrSFRLc3pUQUVBaTJBRkFnQUFBQUFBQUFBQVZCRnpWN0FjcHAyajlXdEFsQllVdDlQQW8zT2d3NWF4U0lKdWtoSU95OEJBQUFBQ0hSeVlXNXpabVZ5QUFBQUF3QUFBQklBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFFZ0FBQUFBQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUtBQUFBQUFBQUFBQUFBQUFBQUFBbkVBQUFBQUFBQUFBQkFBQUFBQUFBQUFJQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBQmdBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFCUUFBQUFCQUFBQUF3QUFBQUVBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFFQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUJWVk5FUXdBQUFBQkNQbjBGOHV5dnYrd1pLeUZhUHh2cGF1MjQyT2NDVkt2alFUNENCOTVXc2dBQUFBWUFBQUFBQUFBQUFFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUZWOFk1UHZNbVBJWUFBQUFBQUFMNVRFQUFBRjRBQUFCTkFBQUFBQUFBNWNPQUFBQUFBPT0iLCJzaW11bGF0aW9uUmVzdWx0Ijp7ImF1dGgiOlsiQUFBQUFRQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDlmR09UN3pKanlHQUFBQUFBQUFBQUJBQUFBQUFBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFBaDBjbUZ1YzJabGNnQUFBQU1BQUFBU0FBQUFBQUFBQUFCQzdtUmp6T1ROSW9xR0FnbFBZaW5hOHR5Q01Rc3pXbURWaUxqb0tMRFYzd0FBQUJJQUFBQUFBQUFBQUk1RWNmQWhVdUJyN0c1aStEVm1wR1hsQWxiL3I5cGtWTW91SnlWcXZnVjNBQUFBQ2dBQUFBQUFBQUFBQUFBQUFBQUFKeEFBQUFBQSJdLCJyZXR2YWwiOiJBQUFBQVE9PSJ9LCJzaW11bGF0aW9uVHJhbnNhY3Rpb25EYXRhIjoiQUFBQUFBQUFBQUlBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFCZ0FBQUFGUVJjMWV3SEthZG8vVnJRSlFXRkxmVHdLTnpvTU9Xc1VpQ2JwSVNEc3ZBUUFBQUJRQUFBQUJBQUFBQXdBQUFBRUFBQUFBUXU1a1k4emt6U0tLaGdJSlQySXAydkxjZ2pFTE0xcGcxWWk0NkNpdzFkOEFBQUFCVlZORVF3QUFBQUJDUG4wRjh1eXZ2K3daS3lGYVB4dnBhdTI0Mk9jQ1ZLdmpRVDRDQjk1V3NnQUFBQUVBQUFBQWprUng4Q0ZTNEd2c2JtTDROV2FrWmVVQ1Z2K3YybVJVeWk0bkpXcStCWGNBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFZQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBRlY4WTVQdk1tUElZQUFBQUFBQUw1VEVBQUFGNEFBQUJOQUFBQUFBQUE1Y08ifQ=="; + const { tx: transactionXDR } = JSON.parse( + Buffer.from(signedTxJson, "base64").toString("utf8"), + ); + + let needsSigning: string[] = [CLIENT_PUBLIC]; + vi.spyOn(AssembledTransaction, "build").mockResolvedValue({ + simulation: {} as Api.SimulateTransactionSuccessResponse, + needsNonInvokerSigningBy: vi.fn(() => { + const result = needsSigning; + needsSigning = []; + return result; + }), + signAuthEntries: vi.fn().mockResolvedValue(undefined), + simulate: vi.fn().mockResolvedValue(undefined), + built: { toXDR: () => transactionXDR }, + } as unknown as AssembledTransaction); + + const scheme = new ExactStellarScheme(signer); + const payload = await scheme.createPaymentPayload(1, paymentRequirements); + + if (!("transaction" in payload.payload)) { + throw new Error("Expected Stellar payload with transaction property"); + } + + const tx = new Transaction(payload.payload.transaction as string, StellarNetworks.TESTNET); + const status = gatherAuthEntrySignatureStatus({ transaction: tx }); + + expect(status.alreadySigned).toContain(CLIENT_PUBLIC); + expect(status.pendingSignature).toHaveLength(0); + }); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/signer.test.ts b/typescript/packages/mechanisms/stellar/test/unit/signer.test.ts new file mode 100644 index 0000000000..3ebe6d6038 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/signer.test.ts @@ -0,0 +1,148 @@ +import { Keypair, Networks as StellarNetworks } from "@stellar/stellar-sdk"; +import { AssembledTransaction } from "@stellar/stellar-sdk/contract"; +import { describe, expect, it } from "vitest"; +import { DEFAULT_TESTNET_RPC_URL, STELLAR_TESTNET_CAIP2 } from "../../src/constants"; +import { + createEd25519Signer, + isClientStellarSigner, + isFacilitatorStellarSigner, +} from "../../src/signer"; + +describe("Stellar Ed25519 Signer", () => { + const validSecret = "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK"; + const validPublicKey = "GBBO4ZDDZTSM2IUKQYBAST3CFHNPFXECGEFTGWTA2WELR2BIWDK57UVE"; + + describe("createEd25519Signer", () => { + it("should create signer with all required methods", async () => { + const signer = createEd25519Signer(validSecret, STELLAR_TESTNET_CAIP2); + + expect(signer.address).toBe(validPublicKey); + expect(signer.signAuthEntry).toBeInstanceOf(Function); + expect(signer.signTransaction).toBeInstanceOf(Function); + }); + + it("should create different signers for different keys", async () => { + const secret1 = "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK"; + const secret2 = "SBFCBBFETW6U5HSOADUUXTQMUEXK7DIQLLATM6OVKKBQNG3I3EWIYJAW"; + + const signer1 = createEd25519Signer(secret1, STELLAR_TESTNET_CAIP2); + const signer2 = createEd25519Signer(secret2, STELLAR_TESTNET_CAIP2); + + expect(signer1.address).not.toBe(signer2.address); + }); + + it("should throw for invalid secret key format", () => { + expect(() => createEd25519Signer("INVALID_SECRET_KEY", STELLAR_TESTNET_CAIP2)).toThrow(); + }); + + it("should throw for empty string", () => { + expect(() => createEd25519Signer("", STELLAR_TESTNET_CAIP2)).toThrow(); + }); + + it("should throw for public key instead of secret", () => { + expect(() => createEd25519Signer(validPublicKey, STELLAR_TESTNET_CAIP2)).toThrow(); + }); + + it("should throw for invalid network", () => { + expect(() => createEd25519Signer(validSecret, "invalid:network")).toThrow( + "Unknown Stellar network: invalid:network", + ); + }); + + it("should create a signer that can sign auth entries", async () => { + const unsignedTxXDR = + "eyJtZXRob2QiOiJ0cmFuc2ZlciIsInR4IjoiQUFBQUFnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQURsM0lBQUFBQUFBQUFBUUFBQUFFQUFBQUFBQUFBQUFBQUFBQnBGcEdGQUFBQUFBQUFBQUVBQUFBQUFBQUFHQUFBQUFBQUFBQUJVRVhOWHNCeW1uYVAxYTBDVUZoUzMwOENqYzZERGxyRklnbTZTRWc3THdFQUFBQUlkSEpoYm5ObVpYSUFBQUFEQUFBQUVnQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBU0FBQUFBQUFBQUFDT1JISHdJVkxnYSt4dVl2ZzFacVJsNVFKVy82L2FaRlRLTGljbGFyNEZkd0FBQUFvQUFBQUFBQUFBQUFBQUFBQUFBQ2NRQUFBQUFRQUFBQUVBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZlh4amsrOHlZOGhnQUFBQUFBQUFBQVFBQUFBQUFBQUFCVUVYTlhzQnltbmFQMWEwQ1VGaFMzMDhDamM2RERsckZJZ202U0VnN0x3RUFBQUFJZEhKaGJuTm1aWElBQUFBREFBQUFFZ0FBQUFBQUFBQUFRdTVrWTh6a3pTS0toZ0lKVDJJcDJ2TGNnakVMTTFwZzFZaTQ2Q2l3MWQ4QUFBQVNBQUFBQUFBQUFBQ09SSEh3SVZMZ2EreHVZdmcxWnFSbDVRSlcvNi9hWkZUS0xpY2xhcjRGZHdBQUFBb0FBQUFBQUFBQUFBQUFBQUFBQUNjUUFBQUFBQUFBQUFFQUFBQUFBQUFBQWdBQUFBQUFBQUFBUXU1a1k4emt6U0tLaGdJSlQySXAydkxjZ2pFTE0xcGcxWWk0NkNpdzFkOEFBQUFHQUFBQUFWQkZ6VjdBY3BwMmo5V3RBbEJZVXQ5UEFvM09ndzVheFNJSnVraElPeThCQUFBQUZBQUFBQUVBQUFBREFBQUFBUUFBQUFCQzdtUmp6T1ROSW9xR0FnbFBZaW5hOHR5Q01Rc3pXbURWaUxqb0tMRFYzd0FBQUFGVlUwUkRBQUFBQUVJK2ZRWHk3SysvN0JrcklWby9HK2xxN2JqWTV3SlVxK05CUGdJSDNsYXlBQUFBQVFBQUFBQ09SSEh3SVZMZ2EreHVZdmcxWnFSbDVRSlcvNi9hWkZUS0xpY2xhcjRGZHdBQUFBRlZVMFJEQUFBQUFFSStmUVh5N0srLzdCa3JJVm8vRytscTdialk1d0pVcStOQlBnSUgzbGF5QUFBQUJnQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBVlh4amsrOHlZOGhnQUFBQUFBQXZsTVFBQUFYZ0FBQUUwQUFBQUFBQURsdzRBQUFBQSIsInNpbXVsYXRpb25SZXN1bHQiOnsiYXV0aCI6WyJBQUFBQVFBQUFBQUFBQUFBUXU1a1k4emt6U0tLaGdJSlQySXAydkxjZ2pFTE0xcGcxWWk0NkNpdzFkOWZHT1Q3ekpqeUdBQUFBQUFBQUFBQkFBQUFBQUFBQUFGUVJjMWV3SEthZG8vVnJRSlFXRkxmVHdLTnpvTU9Xc1VpQ2JwSVNEc3ZBUUFBQUFoMGNtRnVjMlpsY2dBQUFBTUFBQUFTQUFBQUFBQUFBQUJDN21SanpPVE5Jb3FHQWdsUFlpbmE4dHlDTVFzeldtRFZpTGpvS0xEVjN3QUFBQklBQUFBQUFBQUFBSTVFY2ZBaFV1QnI3RzVpK0RWbXBHWGxBbGIvcjlwa1ZNb3VKeVZxdmdWM0FBQUFDZ0FBQUFBQUFBQUFBQUFBQUFBQUp4QUFBQUFBIl0sInJldHZhbCI6IkFBQUFBUT09In0sInNpbXVsYXRpb25UcmFuc2FjdGlvbkRhdGEiOiJBQUFBQUFBQUFBSUFBQUFBQUFBQUFFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUJnQUFBQUZRUmMxZXdIS2Fkby9WclFKUVdGTGZUd0tOem9NT1dzVWlDYnBJU0RzdkFRQUFBQlFBQUFBQkFBQUFBd0FBQUFFQUFBQUFRdTVrWTh6a3pTS0toZ0lKVDJJcDJ2TGNnakVMTTFwZzFZaTQ2Q2l3MWQ4QUFBQUJWVk5FUXdBQUFBQkNQbjBGOHV5dnYrd1pLeUZhUHh2cGF1MjQyT2NDVkt2alFUNENCOTVXc2dBQUFBRUFBQUFBamtSeDhDRlM0R3ZzYm1MNE5XYWtaZVVDVnYrdjJtUlV5aTRuSldxK0JYY0FBQUFCVlZORVF3QUFBQUJDUG4wRjh1eXZ2K3daS3lGYVB4dnBhdTI0Mk9jQ1ZLdmpRVDRDQjk1V3NnQUFBQVlBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFGVjhZNVB2TW1QSVlBQUFBQUFBTDVURUFBQUY0QUFBQk5BQUFBQUFBQTVjTyJ9"; + const expectedSignedTxXDR = + "eyJtZXRob2QiOiJ0cmFuc2ZlciIsInR4IjoiQUFBQUFnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQURsM0lBQUFBQUFBQUFBUUFBQUFFQUFBQUFBQUFBQUFBQUFBQnBGcEdGQUFBQUFBQUFBQUVBQUFBQUFBQUFHQUFBQUFBQUFBQUJVRVhOWHNCeW1uYVAxYTBDVUZoUzMwOENqYzZERGxyRklnbTZTRWc3THdFQUFBQUlkSEpoYm5ObVpYSUFBQUFEQUFBQUVnQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBU0FBQUFBQUFBQUFDT1JISHdJVkxnYSt4dVl2ZzFacVJsNVFKVy82L2FaRlRLTGljbGFyNEZkd0FBQUFvQUFBQUFBQUFBQUFBQUFBQUFBQ2NRQUFBQUFRQUFBQUVBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZlh4amsrOHlZOGhnQUk4ck9BQUFBRUFBQUFBRUFBQUFCQUFBQUVRQUFBQUVBQUFBQ0FBQUFEd0FBQUFwd2RXSnNhV05mYTJWNUFBQUFBQUFOQUFBQUlFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUR3QUFBQWx6YVdkdVlYUjFjbVVBQUFBQUFBQU5BQUFBUUl2bjJjU3VLbFl5TU96T0pTWnkwc0VaN3dkN1QwYmdSQ0ZxZjg1M3VXQXFVcjE1ZUpycXNqVjROUVpTQW05WXNWbHZEcEUrSFRLc3pUQUVBaTJBRkFnQUFBQUFBQUFBQVZCRnpWN0FjcHAyajlXdEFsQllVdDlQQW8zT2d3NWF4U0lKdWtoSU95OEJBQUFBQ0hSeVlXNXpabVZ5QUFBQUF3QUFBQklBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFFZ0FBQUFBQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUtBQUFBQUFBQUFBQUFBQUFBQUFBbkVBQUFBQUFBQUFBQkFBQUFBQUFBQUFJQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBQmdBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFCUUFBQUFCQUFBQUF3QUFBQUVBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDhBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFFQUFBQUFqa1J4OENGUzRHdnNibUw0Tldha1plVUNWdit2Mm1SVXlpNG5KV3ErQlhjQUFBQUJWVk5FUXdBQUFBQkNQbjBGOHV5dnYrd1pLeUZhUHh2cGF1MjQyT2NDVkt2alFUNENCOTVXc2dBQUFBWUFBQUFBQUFBQUFFTHVaR1BNNU0waWlvWUNDVTlpS2RyeTNJSXhDek5hWU5XSXVPZ29zTlhmQUFBQUZWOFk1UHZNbVBJWUFBQUFBQUFMNVRFQUFBRjRBQUFCTkFBQUFBQUFBNWNPQUFBQUFBPT0iLCJzaW11bGF0aW9uUmVzdWx0Ijp7ImF1dGgiOlsiQUFBQUFRQUFBQUFBQUFBQVF1NWtZOHprelNLS2hnSUpUMklwMnZMY2dqRUxNMXBnMVlpNDZDaXcxZDlmR09UN3pKanlHQUFBQUFBQUFBQUJBQUFBQUFBQUFBRlFSYzFld0hLYWRvL1ZyUUpRV0ZMZlR3S056b01PV3NVaUNicElTRHN2QVFBQUFBaDBjbUZ1YzJabGNnQUFBQU1BQUFBU0FBQUFBQUFBQUFCQzdtUmp6T1ROSW9xR0FnbFBZaW5hOHR5Q01Rc3pXbURWaUxqb0tMRFYzd0FBQUJJQUFBQUFBQUFBQUk1RWNmQWhVdUJyN0c1aStEVm1wR1hsQWxiL3I5cGtWTW91SnlWcXZnVjNBQUFBQ2dBQUFBQUFBQUFBQUFBQUFBQUFKeEFBQUFBQSJdLCJyZXR2YWwiOiJBQUFBQVE9PSJ9LCJzaW11bGF0aW9uVHJhbnNhY3Rpb25EYXRhIjoiQUFBQUFBQUFBQUlBQUFBQUFBQUFBRUx1WkdQTTVNMGlpb1lDQ1U5aUtkcnkzSUl4Q3pOYVlOV0l1T2dvc05YZkFBQUFCZ0FBQUFGUVJjMWV3SEthZG8vVnJRSlFXRkxmVHdLTnpvTU9Xc1VpQ2JwSVNEc3ZBUUFBQUJRQUFBQUJBQUFBQXdBQUFBRUFBQUFBUXU1a1k4emt6U0tLaGdJSlQySXAydkxjZ2pFTE0xcGcxWWk0NkNpdzFkOEFBQUFCVlZORVF3QUFBQUJDUG4wRjh1eXZ2K3daS3lGYVB4dnBhdTI0Mk9jQ1ZLdmpRVDRDQjk1V3NnQUFBQUVBQUFBQWprUng4Q0ZTNEd2c2JtTDROV2FrWmVVQ1Z2K3YybVJVeWk0bkpXcStCWGNBQUFBQlZWTkVRd0FBQUFCQ1BuMEY4dXl2dit3Wkt5RmFQeHZwYXUyNDJPY0NWS3ZqUVQ0Q0I5NVdzZ0FBQUFZQUFBQUFBQUFBQUVMdVpHUE01TTBpaW9ZQ0NVOWlLZHJ5M0lJeEN6TmFZTldJdU9nb3NOWGZBQUFBRlY4WTVQdk1tUElZQUFBQUFBQUw1VEVBQUFGNEFBQUJOQUFBQUFBQUE1Y08ifQ=="; + + const signer = createEd25519Signer(validSecret, STELLAR_TESTNET_CAIP2); + expect(signer.address).toBe(validPublicKey); + + // parse the unsigned tx XDR into AssembledTransaction + const { method, tx, simulationResult, simulationTransactionData } = JSON.parse( + Buffer.from(unsignedTxXDR, "base64").toString("utf8"), + ); + const recoveredTx = AssembledTransaction.fromJSON( + { + contractId: "CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA", + networkPassphrase: StellarNetworks.TESTNET, + rpcUrl: DEFAULT_TESTNET_RPC_URL, + method, + parseResultXdr: result => result, + }, + { tx, simulationResult, simulationTransactionData }, + ); + + // ensure the tx is the same + const recoveredTxXDR = Buffer.from(recoveredTx.toJSON()).toString("base64"); + expect(recoveredTxXDR).toBe(unsignedTxXDR); + + // ensure the Tx is missing the signer we have + let missingSigners = recoveredTx.needsNonInvokerSigningBy(); + expect(missingSigners).toEqual([validPublicKey]); + + // ensure the tx is signed successfully + await recoveredTx.signAuthEntries({ + address: validPublicKey, + signAuthEntry: signer.signAuthEntry, + expiration: 2345678, + }); + missingSigners = recoveredTx.needsNonInvokerSigningBy(); + expect(missingSigners).toHaveLength(0); + + // ensure the result of the signed tx is the same as the expected signed tx + const signedTxXDR = Buffer.from(recoveredTx.toJSON()).toString("base64"); + expect(signedTxXDR).toBe(expectedSignedTxXDR); + }); + }); + + describe("is*StellarSigner", () => { + it("should return true for both when signer has all methods", () => { + const signer = createEd25519Signer(validSecret, STELLAR_TESTNET_CAIP2); + expect(isFacilitatorStellarSigner(signer)).toBe(true); + expect(isClientStellarSigner(signer)).toBe(true); + }); + + it("should return true for client but false for facilitator when signTransaction missing", () => { + const mockSigner = { + address: validPublicKey, + signAuthEntry: async () => ({ signedAuthEntry: "" }), + }; + expect(isFacilitatorStellarSigner(mockSigner)).toBe(false); + expect(isClientStellarSigner(mockSigner)).toBe(true); + }); + + it("should return false for invalid types", () => { + // false for null + expect(isFacilitatorStellarSigner(null)).toBe(false); + expect(isClientStellarSigner(null)).toBe(false); + // false for undefined + expect(isFacilitatorStellarSigner(undefined)).toBe(false); + expect(isClientStellarSigner(undefined)).toBe(false); + // false for string + expect(isFacilitatorStellarSigner("string")).toBe(false); + expect(isClientStellarSigner("string")).toBe(false); + // false for number + expect(isFacilitatorStellarSigner(123)).toBe(false); + expect(isClientStellarSigner(123)).toBe(false); + // false for empty object + expect(isFacilitatorStellarSigner({})).toBe(false); + expect(isClientStellarSigner({})).toBe(false); + // false for object incomplete object + expect(isFacilitatorStellarSigner({ address: "" })).toBe(false); + expect(isClientStellarSigner({ address: "" })).toBe(false); + // false for similar object with non-string address + const invalidSigner = { + address: 123, + signAuthEntry: () => {}, + signTransaction: () => {}, + }; + expect(isFacilitatorStellarSigner(invalidSigner)).toBe(false); + expect(isClientStellarSigner(invalidSigner)).toBe(false); + // false for Stellar keypair + const keypair = Keypair.fromSecret(validSecret); + expect(isFacilitatorStellarSigner(keypair)).toBe(false); + expect(isClientStellarSigner(keypair)).toBe(false); + }); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/utils.test.ts b/typescript/packages/mechanisms/stellar/test/unit/utils.test.ts new file mode 100644 index 0000000000..9662e63514 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/utils.test.ts @@ -0,0 +1,397 @@ +import { rpc } from "@stellar/stellar-sdk"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { STELLAR_PUBNET_CAIP2, STELLAR_TESTNET_CAIP2 } from "../../src"; +import { + convertToTokenAmount, + DEFAULT_ESTIMATED_LEDGER_SECONDS, + getEstimatedLedgerCloseTimeSeconds, + getNetworkPassphrase, + getRpcClient, + getRpcUrl, + getUsdcAddress, + isStellarNetwork, + RpcConfig, + validateStellarAssetAddress, + validateStellarDestinationAddress, +} from "../../src/utils"; + +// Mock the Stellar SDK +vi.mock("@stellar/stellar-sdk", () => ({ + rpc: { + Server: vi.fn(), + }, +})); + +describe("Stellar RPC Helper Functions", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe("validateStellarDestinationAddress", () => { + it("should return true for valid addresses", () => { + expect( + validateStellarDestinationAddress( + "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", + ), + ).toBe(true); + }); + + it("should return false for invalid addresses", () => { + expect(validateStellarDestinationAddress("")).toBe(false); + expect(validateStellarDestinationAddress("invalid")).toBe(false); + }); + }); + + describe("validateStellarAssetAddress", () => { + it("should return true for valid C-accounts", () => { + expect( + validateStellarAssetAddress("CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75"), + ).toBe(true); + }); + + it("should return false for invalid addresses", () => { + expect(validateStellarAssetAddress("")).toBe(false); + expect(validateStellarAssetAddress("invalid")).toBe(false); + }); + }); + + describe("isStellarNetwork", () => { + it("should return true for Stellar pubnet", () => { + expect(isStellarNetwork(STELLAR_PUBNET_CAIP2)).toBe(true); + }); + + it("should return true for Stellar testnet", () => { + expect(isStellarNetwork(STELLAR_TESTNET_CAIP2)).toBe(true); + }); + + it("should return false for invalid networks", () => { + expect(isStellarNetwork("invalid-network" as any)).toBe(false); + expect(isStellarNetwork("" as any)).toBe(false); + }); + + it("should return false for non-Stellar CAIP-2 networks", () => { + expect(isStellarNetwork("eip155:1" as any)).toBe(false); + expect(isStellarNetwork("eip155:8453" as any)).toBe(false); + expect(isStellarNetwork("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" as any)).toBe(false); + }); + }); + + describe("getNetworkPassphrase", () => { + it("should return the correct passphrase for stellar (mainnet)", () => { + const result = getNetworkPassphrase(STELLAR_PUBNET_CAIP2); + expect(result).toBe("Public Global Stellar Network ; September 2015"); + }); + + it("should return the correct passphrase for stellar testnet", () => { + const result = getNetworkPassphrase(STELLAR_TESTNET_CAIP2); + expect(result).toBe("Test SDF Network ; September 2015"); + }); + + it("should throw error for unknown network", () => { + expect(() => getNetworkPassphrase("invalid-network" as any)).toThrow( + "Unknown Stellar network: invalid-network", + ); + }); + }); + + describe("getRpcUrl", () => { + describe(STELLAR_TESTNET_CAIP2, () => { + it("should return default testnet URL when no config provided", () => { + const result = getRpcUrl(STELLAR_TESTNET_CAIP2); + expect(result).toBe("https://soroban-testnet.stellar.org"); + }); + + it("should return custom URL when provided in rpcConfig", () => { + const customUrl = "https://custom-stellar-testnet-rpc.example.com"; + const rpcConfig: RpcConfig = { url: customUrl }; + const result = getRpcUrl(STELLAR_TESTNET_CAIP2, rpcConfig); + expect(result).toBe(customUrl); + }); + }); + + describe("stellar mainnet", () => { + it("should throw error when no config provided for mainnet", () => { + expect(() => getRpcUrl(STELLAR_PUBNET_CAIP2)).toThrow( + "Stellar mainnet requires a non-empty rpcUrl. For a list of RPC providers, see https://developers.stellar.org/docs/data/apis/rpc/providers#publicly-accessible-apis", + ); + }); + + it("should throw error when rpcConfig provided without url for mainnet", () => { + const rpcConfig: RpcConfig = {}; + expect(() => getRpcUrl(STELLAR_PUBNET_CAIP2, rpcConfig)).toThrow( + "Stellar mainnet requires a non-empty rpcUrl. For a list of RPC providers, see https://developers.stellar.org/docs/data/apis/rpc/providers#publicly-accessible-apis", + ); + }); + + it("should return custom URL when provided in rpcConfig for mainnet", () => { + const customUrl = "https://custom-stellar-mainnet-rpc.example.com"; + const config: RpcConfig = { url: customUrl }; + const result = getRpcUrl(STELLAR_PUBNET_CAIP2, config); + expect(result).toBe(customUrl); + }); + }); + + describe("invalid networks", () => { + it("should throw error for unknown network", () => { + expect(() => getRpcUrl("invalid-network" as any)).toThrow( + "Unknown Stellar network: invalid-network", + ); + }); + }); + }); + + describe("getRpcClient", () => { + describe(STELLAR_TESTNET_CAIP2, () => { + it("should create RPC client with default testnet URL when no config provided", () => { + const mockServer = { mock: "testnet-server" }; + vi.mocked(rpc.Server).mockReturnValue(mockServer as any); + + const result = getRpcClient(STELLAR_TESTNET_CAIP2); + + expect(rpc.Server).toHaveBeenCalledWith("https://soroban-testnet.stellar.org", { + allowHttp: true, + }); + expect(result).toBe(mockServer); + }); + + it("should create RPC client with custom URL when provided in rpcConfig", () => { + const customUrl = "https://custom-testnet-rpc.com"; + const mockServer = { mock: "testnet-server-custom" }; + vi.mocked(rpc.Server).mockReturnValue(mockServer as any); + + const rpcConfig: RpcConfig = { url: customUrl }; + const result = getRpcClient(STELLAR_TESTNET_CAIP2, rpcConfig); + + expect(rpc.Server).toHaveBeenCalledWith(customUrl, { + allowHttp: true, + }); + expect(result).toBe(mockServer); + }); + + it("should allow HTTP for testnet", () => { + const mockServer = { mock: "testnet-server" }; + vi.mocked(rpc.Server).mockReturnValue(mockServer as any); + + getRpcClient(STELLAR_TESTNET_CAIP2); + + expect(rpc.Server).toHaveBeenCalledWith(expect.any(String), { + allowHttp: true, + }); + }); + }); + + describe("stellar mainnet", () => { + it("should throw error when no config provided for mainnet", () => { + expect(() => getRpcClient(STELLAR_PUBNET_CAIP2)).toThrow( + "Stellar mainnet requires a non-empty rpcUrl. For a list of RPC providers, see https://developers.stellar.org/docs/data/apis/rpc/providers#publicly-accessible-apis", + ); + }); + + it("should create RPC client with custom URL for mainnet", () => { + const customUrl = "https://custom-mainnet-rpc.com"; + const mockServer = { mock: "mainnet-server" }; + vi.mocked(rpc.Server).mockReturnValue(mockServer as any); + + const rpcConfig: RpcConfig = { url: customUrl }; + const result = getRpcClient(STELLAR_PUBNET_CAIP2, rpcConfig); + + expect(rpc.Server).toHaveBeenCalledWith(customUrl, { + allowHttp: false, + }); + expect(result).toBe(mockServer); + }); + + it("should not allow HTTP for mainnet", () => { + const customUrl = "https://custom-mainnet-rpc.com"; + const mockServer = { mock: "mainnet-server" }; + vi.mocked(rpc.Server).mockReturnValue(mockServer as any); + + const rpcConfig: RpcConfig = { url: customUrl }; + getRpcClient(STELLAR_PUBNET_CAIP2, rpcConfig); + expect(rpc.Server).toHaveBeenCalledWith(expect.any(String), { + allowHttp: false, + }); + }); + }); + + describe("invalid networks", () => { + it("should throw error for unknown network", () => { + expect(() => getRpcClient("invalid-network" as any)).toThrow( + "Unknown Stellar network: invalid-network", + ); + }); + + it("should throw error for non-Stellar network", () => { + expect(() => getRpcClient("base" as any)).toThrow("Unknown Stellar network: base"); + }); + }); + }); + + describe("getEstimatedLedgerCloseTimeSeconds", () => { + it("should compute seconds per ledger from RPC getLedgers response", async () => { + const baseTs = 1734032457; + const ledgers = [100, 101, 102, 103, 104, 105].map((seq, i) => ({ + sequence: seq, + ledgerCloseTime: String(baseTs + i * 3), + })); + const mockGetLedgers = vi.fn().mockResolvedValue({ ledgers }); + const mockServer = { + getLatestLedger: vi.fn().mockResolvedValue({ sequence: 105 }), + getLedgers: mockGetLedgers, + } as unknown as rpc.Server; + + const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + + expect(result).toBe(3); + expect(mockGetLedgers).toHaveBeenCalledWith( + expect.objectContaining({ + pagination: { limit: 20 }, + }), + ); + const callArg = mockGetLedgers.mock.calls[0][0]; + expect(callArg.startLedger).toBeGreaterThanOrEqual(1); + expect(callArg.startLedger).toBeLessThanOrEqual(105); + }); + + it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when getLatestLedger throws", async () => { + const mockGetLedgers = vi.fn(); + const mockServer = { + getLatestLedger: vi.fn().mockRejectedValue(new Error("RPC error")), + getLedgers: mockGetLedgers, + } as unknown as rpc.Server; + + const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + + expect(result).toBe(DEFAULT_ESTIMATED_LEDGER_SECONDS); + expect(mockGetLedgers).not.toHaveBeenCalled(); + }); + + it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when getLedgers throws", async () => { + const mockServer = { + getLatestLedger: vi.fn().mockResolvedValue({ sequence: 100 }), + getLedgers: vi.fn().mockRejectedValue(new Error("Network error")), + } as unknown as rpc.Server; + + const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + + expect(result).toBe(DEFAULT_ESTIMATED_LEDGER_SECONDS); + }); + + it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when getLedgers returns fewer than 2 records", async () => { + const mockServer = { + getLatestLedger: vi.fn().mockResolvedValue({ sequence: 100 }), + getLedgers: vi.fn().mockResolvedValue({ + ledgers: [{ sequence: 100, ledgerCloseTime: "1734032457" }], + }), + } as unknown as rpc.Server; + + const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + + expect(result).toBe(DEFAULT_ESTIMATED_LEDGER_SECONDS); + }); + }); + + describe("getUsdcAddress", () => { + it("should return USDC address for mainnet", () => { + const result = getUsdcAddress(STELLAR_PUBNET_CAIP2); + expect(result).toBe("CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75"); + }); + + it("should return USDC address for testnet", () => { + const result = getUsdcAddress(STELLAR_TESTNET_CAIP2); + expect(result).toBe("CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA"); + }); + + it("should throw error for unknown network", () => { + expect(() => getUsdcAddress("invalid-network" as any)).toThrow( + "No USDC address configured for network: invalid-network", + ); + }); + }); + + describe("convertToTokenAmount", () => { + describe("with default 7 decimals", () => { + it("should convert decimal amount correctly", () => { + expect(convertToTokenAmount("0.1")).toBe("1000000"); + expect(convertToTokenAmount("1.5")).toBe("15000000"); + expect(convertToTokenAmount("0.1234567")).toBe("1234567"); + }); + + it("should convert integer amount correctly", () => { + expect(convertToTokenAmount("1")).toBe("10000000"); + expect(convertToTokenAmount("10")).toBe("100000000"); + expect(convertToTokenAmount("0")).toBe("0"); + }); + + it("should handle amounts with trailing zeros", () => { + expect(convertToTokenAmount("1.0")).toBe("10000000"); + expect(convertToTokenAmount("0.1000000")).toBe("1000000"); + }); + + it("should handle very small amounts", () => { + expect(convertToTokenAmount("0.0000001")).toBe("1"); + expect(convertToTokenAmount("0.00000001")).toBe("0"); + }); + + it("should truncate excess decimal places", () => { + expect(convertToTokenAmount("1.12345678")).toBe("11234567"); + }); + }); + + describe("with custom decimals", () => { + it("should convert with 6 decimals", () => { + expect(convertToTokenAmount("1.5", 6)).toBe("1500000"); + expect(convertToTokenAmount("0.1", 6)).toBe("100000"); + }); + + it("should convert with 18 decimals", () => { + expect(convertToTokenAmount("1.0", 18)).toBe("1000000000000000000"); + expect(convertToTokenAmount("0.5", 18)).toBe("500000000000000000"); + }); + + it("should convert with 0 decimals", () => { + expect(convertToTokenAmount("1.5", 0)).toBe("1"); + expect(convertToTokenAmount("2.9", 0)).toBe("2"); + }); + }); + + describe("special cases", () => { + it("should handle negative numbers", () => { + expect(convertToTokenAmount("-1.5")).toBe("-15000000"); + }); + + it("should handle scientific notation input", () => { + // Scientific notation should be correctly converted + // 1e-7 = 0.0000001, which with 7 decimals = 1 + expect(convertToTokenAmount("1e-7")).toBe("1"); + expect(convertToTokenAmount("1e-6")).toBe("10"); + expect(convertToTokenAmount("1.5e-6")).toBe("15"); + }); + + it("should handle very large numbers", () => { + expect(convertToTokenAmount("999999999.9999999")).toBe("9999999999999999"); + }); + }); + + describe("error cases", () => { + it("should throw error for invalid amount", () => { + expect(() => convertToTokenAmount("invalid")).toThrow("Invalid amount: invalid"); + expect(() => convertToTokenAmount("abc")).toThrow("Invalid amount: abc"); + expect(() => convertToTokenAmount("")).toThrow("Invalid amount: "); + }); + + it("should throw error for NaN", () => { + expect(() => convertToTokenAmount("NaN")).toThrow("Invalid amount: NaN"); + }); + + it("should throw error for invalid decimals", () => { + expect(() => convertToTokenAmount("1.5", -1)).toThrow( + "Decimals must be between 0 and 20, got -1", + ); + expect(() => convertToTokenAmount("1.5", 21)).toThrow( + "Decimals must be between 0 and 20, got 21", + ); + }); + }); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/tsconfig.json b/typescript/packages/mechanisms/stellar/tsconfig.json new file mode 100644 index 0000000000..19ba0fba3a --- /dev/null +++ b/typescript/packages/mechanisms/stellar/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "lib": ["ES2020"], + "allowJs": false, + "checkJs": false + }, + "include": ["src", "test"] +} diff --git a/typescript/packages/mechanisms/stellar/tsup.config.ts b/typescript/packages/mechanisms/stellar/tsup.config.ts new file mode 100644 index 0000000000..1143bfeaf5 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/tsup.config.ts @@ -0,0 +1,30 @@ +import { defineConfig } from "tsup"; + +const baseConfig = { + entry: { + index: "src/index.ts", + "exact/client/index": "src/exact/client/index.ts", + "exact/server/index": "src/exact/server/index.ts", + "exact/facilitator/index": "src/exact/facilitator/index.ts", + }, + dts: { + resolve: true, + }, + sourcemap: true, + target: "es2020", +}; + +export default defineConfig([ + { + ...baseConfig, + format: "esm", + outDir: "dist/esm", + clean: true, + }, + { + ...baseConfig, + format: "cjs", + outDir: "dist/cjs", + clean: false, + }, +]); diff --git a/typescript/packages/mechanisms/stellar/vitest.config.ts b/typescript/packages/mechanisms/stellar/vitest.config.ts new file mode 100644 index 0000000000..1d5c581d9c --- /dev/null +++ b/typescript/packages/mechanisms/stellar/vitest.config.ts @@ -0,0 +1,15 @@ +import { loadEnv } from "vite"; +import tsconfigPaths from "vite-tsconfig-paths"; +import { defineConfig } from "vitest/config"; + +export default defineConfig(({ mode }) => ({ + test: { + env: loadEnv(mode, process.cwd(), ""), + exclude: [ + "**/node_modules/**", + "**/dist/**", + "**/test/integrations/**", // Exclude integration tests from default run + ], + }, + plugins: [tsconfigPaths({ projects: ["."] })], +})); diff --git a/typescript/packages/mechanisms/stellar/vitest.integration.config.ts b/typescript/packages/mechanisms/stellar/vitest.integration.config.ts new file mode 100644 index 0000000000..a0e4a65874 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/vitest.integration.config.ts @@ -0,0 +1,13 @@ +import { loadEnv } from "vite"; +import tsconfigPaths from "vite-tsconfig-paths"; +import { defineConfig } from "vitest/config"; + +export default defineConfig(({ mode }) => ({ + test: { + env: loadEnv(mode, process.cwd(), ""), + include: ["test/integrations/**/*.test.ts"], // Only include integration tests + testTimeout: 20000, + hookTimeout: 20000, + }, + plugins: [tsconfigPaths({ projects: ["."] })], +})); diff --git a/typescript/packages/mechanisms/svm/README.md b/typescript/packages/mechanisms/svm/README.md index 5c9b975f0f..e026809d7a 100644 --- a/typescript/packages/mechanisms/svm/README.md +++ b/typescript/packages/mechanisms/svm/README.md @@ -196,5 +196,5 @@ pnpm format - `@x402/core` - Core protocol types and client - `@x402/fetch` - HTTP wrapper with automatic payment handling - `@x402/evm` - EVM/Ethereum implementation +- `@x402/stellar` - Stellar implementation - `@solana/web3.js` - Solana JavaScript SDK (peer dependency) - diff --git a/typescript/pnpm-lock.yaml b/typescript/pnpm-lock.yaml index 57092af693..9af67e6ebc 100644 --- a/typescript/pnpm-lock.yaml +++ b/typescript/pnpm-lock.yaml @@ -16,16 +16,16 @@ importers: version: 0.5.2 '@changesets/cli': specifier: ^2.28.1 - version: 2.29.8(@types/node@22.19.7) + version: 2.29.8(@types/node@22.18.0) tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) turbo: specifier: ^2.5.0 - version: 2.8.1 + version: 2.5.6 typescript: specifier: ^5.8.3 - version: 5.9.3 + version: 5.9.2 packages/core: dependencies: @@ -35,49 +35,49 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/extensions: dependencies: @@ -92,62 +92,62 @@ importers: version: 8.17.1 siwe: specifier: ^2.3.2 - version: 2.3.2(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + version: 2.3.2(ethers@6.16.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) tweetnacl: specifier: ^1.0.3 version: 1.0.3 viem: specifier: ^2.43.5 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/http/axios: dependencies: @@ -156,56 +156,56 @@ importers: version: link:../../core axios: specifier: ^1.7.9 - version: 1.13.4 + version: 1.11.0 zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/http/express: dependencies: @@ -220,62 +220,62 @@ importers: version: link:../paywall viem: specifier: ^2.39.3 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/express': specifier: ^5.0.1 - version: 5.0.6 + version: 5.0.3 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) express: specifier: ^4.18.2 - version: 4.22.1 + version: 4.21.2 prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/http/fetch: dependencies: @@ -284,56 +284,56 @@ importers: version: link:../../core viem: specifier: ^2.39.3 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/http/hono: dependencies: @@ -352,52 +352,52 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) hono: specifier: ^4.7.1 - version: 4.11.7 + version: 4.10.7 prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/http/next: dependencies: @@ -412,56 +412,56 @@ importers: version: link:../paywall next: specifier: ^16.0.10 - version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 16.0.10(@babel/core@7.28.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/http/paywall: dependencies: @@ -470,31 +470,31 @@ importers: version: 1.2.6 '@solana-program/compute-budget': specifier: ^0.8.0 - version: 0.8.0(@solana/kit@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.8.0(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)) '@solana-program/token': specifier: ^0.5.1 - version: 0.5.1(@solana/kit@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.5.1(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)) '@solana-program/token-2022': specifier: ^0.4.2 - version: 0.4.2(@solana/kit@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + version: 0.4.2(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)) '@solana/kit': specifier: ^6.1.0 - version: 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@solana/transaction-confirmation': specifier: ^2.1.1 - version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + version: 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(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.20(react@19.2.4) + version: 5.90.11(react@19.2.1) '@wagmi/connectors': specifier: ^5.8.1 - version: 5.11.2(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) + version: 5.9.9(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(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.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) '@wagmi/core': specifier: ^2.17.1 - version: 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + version: 2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) '@wallet-standard/app': specifier: ^1.1.0 version: 1.1.0 @@ -509,35 +509,35 @@ importers: version: link:../../core viem: specifier: ^2.39.3 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) wagmi: specifier: ^2.17.1 - version: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) + version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@craftamap/esbuild-plugin-html': specifier: ^0.9.0 - version: 0.9.0(bufferutil@4.1.0)(esbuild@0.25.12)(utf-8-validate@5.0.10) + version: 0.9.0(bufferutil@4.0.9)(esbuild@0.25.9)(utf-8-validate@5.0.10) '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@types/react': specifier: ^19 - version: 19.2.10 + version: 19.1.12 '@types/react-dom': specifier: ^19 - version: 19.2.3(@types/react@19.2.10) + version: 19.1.9(@types/react@19.1.12) '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@x402/evm': specifier: workspace:~ version: link:../../mechanisms/evm @@ -549,46 +549,46 @@ importers: version: 6.0.3 esbuild: specifier: ^0.25.4 - version: 0.25.12 + version: 0.25.9 eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 react: specifier: ^19.0.0 - version: 19.2.4 + version: 19.2.1 react-dom: specifier: ^19.0.0 - version: 19.2.4(react@19.2.4) + version: 19.2.1(react@19.2.1) tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/legacy/x402: dependencies: @@ -597,19 +597,19 @@ importers: version: 1.2.6 '@solana-program/compute-budget': specifier: ^0.11.0 - version: 0.11.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.11.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.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.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.9.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.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.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + version: 0.6.1(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)) '@solana/kit': specifier: ^5.0.0 - version: 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/transaction-confirmation': specifier: ^5.0.0 - version: 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/wallet-standard-features': specifier: ^1.3.0 version: 1.3.0 @@ -624,62 +624,62 @@ importers: version: 1.1.0 viem: specifier: ^2.21.26 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) wagmi: specifier: ^2.15.6 - version: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) + version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@coinbase/onchainkit': specifier: ^0.38.14 - version: 0.38.19(@farcaster/miniapp-sdk@0.2.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + version: 0.38.19(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) '@craftamap/esbuild-plugin-html': specifier: ^0.9.0 - version: 0.9.0(bufferutil@4.1.0)(esbuild@0.25.12)(utf-8-validate@5.0.10) + version: 0.9.0(bufferutil@4.0.9)(esbuild@0.25.9)(utf-8-validate@5.0.10) '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@types/react': specifier: ^19 - version: 19.2.10 + version: 19.1.12 '@types/react-dom': specifier: ^19 - version: 19.2.3(@types/react@19.2.10) + version: 19.1.9(@types/react@19.1.12) '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@wagmi/connectors': specifier: ^5.8.1 - version: 5.11.2(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) + version: 5.9.9(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(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.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) '@wagmi/core': specifier: ^2.17.1 - version: 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + version: 2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) buffer: specifier: ^6.0.3 version: 6.0.3 esbuild: specifier: ^0.25.4 - version: 0.25.12 + version: 0.25.9 eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 @@ -691,31 +691,31 @@ importers: version: 19.2.1(react@19.2.1) tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/legacy/x402-axios: dependencies: axios: specifier: ^1.7.9 - version: 1.13.4 + version: 1.11.0 viem: specifier: ^2.21.26 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) x402: specifier: workspace:^ version: link:../x402 @@ -725,64 +725,64 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/legacy/x402-express: dependencies: '@coinbase/cdp-sdk': specifier: ^1.22.0 - version: 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 1.36.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@solana/kit': specifier: ^5.0.0 - version: 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) express: specifier: ^4.18.2 - version: 4.22.1 + version: 4.21.2 viem: specifier: ^2.21.26 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) x402: specifier: workspace:^ version: link:../x402 @@ -792,58 +792,58 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/express': specifier: ^5.0.1 - version: 5.0.6 + version: 5.0.3 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/legacy/x402-fetch: dependencies: viem: specifier: ^2.21.26 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) x402: specifier: workspace:^ version: link:../x402 @@ -853,64 +853,64 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/legacy/x402-hono: dependencies: '@coinbase/cdp-sdk': specifier: ^1.22.0 - version: 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 1.36.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@solana/kit': specifier: ^5.0.0 - version: 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) hono: specifier: ^4.7.1 - version: 4.11.7 + version: 4.10.7 viem: specifier: ^2.21.26 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) x402: specifier: workspace:^ version: link:../x402 @@ -920,64 +920,64 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/legacy/x402-next: dependencies: '@coinbase/cdp-sdk': specifier: ^1.22.0 - version: 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 1.36.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@solana/kit': specifier: ^5.0.0 - version: 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) next: specifier: '>=15.5.9 || >=16.0.10' - version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 16.0.10(@babel/core@7.28.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) viem: specifier: ^2.21.26 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) x402: specifier: workspace:^ version: link:../x402 @@ -987,55 +987,55 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/mcp: dependencies: '@modelcontextprotocol/sdk': specifier: ^1.12.1 - version: 1.25.3(hono@4.11.7)(zod@3.25.76) + version: 1.26.0(zod@3.25.76) '@x402/core': specifier: workspace:~ version: link:../core @@ -1045,58 +1045,58 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@x402/evm': specifier: workspace:~ version: link:../mechanisms/evm eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) express: specifier: ^4.21.2 - version: 4.22.1 + version: 4.21.2 prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 viem: specifier: ^2.27.2 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/mechanisms/aptos: dependencies: @@ -1109,49 +1109,49 @@ importers: devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/mechanisms/evm: dependencies: @@ -1163,123 +1163,178 @@ importers: version: link:../../extensions viem: specifier: ^2.39.3 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zod: specifier: ^3.24.2 version: 3.25.76 devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 + '@types/node': + specifier: ^22.13.4 + version: 22.18.0 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.24.0 + version: 9.34.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsup: + specifier: ^8.4.0 + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) + tsx: + specifier: ^4.19.2 + version: 4.20.5 + typescript: + specifier: ^5.7.3 + version: 5.9.2 + vite: + specifier: ^6.2.6 + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) + vitest: + specifier: ^3.0.5 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) + + packages/mechanisms/stellar: + dependencies: + '@stellar/stellar-sdk': + specifier: ^14.4.2 + version: 14.5.0 + '@x402/core': + specifier: workspace:* + version: link:../../core + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.34.0 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) packages/mechanisms/svm: dependencies: '@solana-program/compute-budget': specifier: ^0.11.0 - version: 0.11.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.11.0(@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.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.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) + version: 0.9.0(@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.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.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + version: 0.6.1(@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)) '@solana/kit': specifier: '>=5.1.0' - version: 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@x402/core': specifier: workspace:~ version: link:../../core devDependencies: '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@scure/base': specifier: ^1.2.6 version: 1.2.6 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tsup: specifier: ^8.4.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1) tsx: specifier: ^4.19.2 - version: 4.21.0 + version: 4.20.5 typescript: specifier: ^5.7.3 - version: 5.9.3 + version: 5.9.2 vite: specifier: ^6.2.6 - version: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + version: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + version: 5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)) vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) site: dependencies: @@ -1288,16 +1343,16 @@ importers: version: 5.2.1(got@11.8.6) '@coinbase/cdp-sdk': specifier: ^1.22.0 - version: 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 1.36.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@heroicons/react': specifier: ^2.2.0 - version: 2.2.0(react@19.2.4) + version: 2.2.0(react@19.2.3) '@scure/base': specifier: ^1.2.6 version: 1.2.6 '@solana/kit': specifier: ^6.1.0 - version: 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@vercel/functions': specifier: ^2.2.8 version: 2.2.13 @@ -1324,93 +1379,100 @@ importers: version: link:../packages/mechanisms/svm lottie-react: specifier: ^2.4.1 - version: 2.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 2.4.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) motion: specifier: ^11.18.0 - version: 11.18.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 11.18.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) next: specifier: ^16.0.10 - version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 16.0.10(@babel/core@7.28.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: specifier: ^19.2.3 - version: 19.2.4 + version: 19.2.3 react-dom: specifier: ^19.2.3 - version: 19.2.4(react@19.2.4) + version: 19.2.3(react@19.2.3) viem: specifier: ^2.21.26 - version: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) wagmi: specifier: ^2.15.6 - version: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) + version: 2.16.9(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) x402-legacy: specifier: npm:x402@0.1.2 - version: x402@0.1.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + version: x402@0.1.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) devDependencies: '@eslint/eslintrc': specifier: ^3 - version: 3.3.3 + version: 3.3.1 '@eslint/js': specifier: ^9.24.0 - version: 9.39.2 + version: 9.34.0 '@svgr/webpack': specifier: ^8.1.0 - version: 8.1.0(typescript@5.9.3) + version: 8.1.0(typescript@5.9.2) '@tailwindcss/postcss': specifier: ^4.0.0 - version: 4.1.18 + version: 4.1.17 '@types/node': specifier: ^22.13.4 - version: 22.19.7 + version: 22.18.0 '@types/react': specifier: ^19 - version: 19.2.10 + version: 19.1.12 '@types/react-dom': specifier: ^19 - version: 19.2.3(@types/react@19.2.10) + version: 19.1.9(@types/react@19.1.12) '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 - version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) '@typescript-eslint/parser': specifier: ^8.29.1 - version: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint: specifier: ^9.24.0 - version: 9.39.2(jiti@2.6.1) + version: 9.34.0(jiti@2.6.1) eslint-config-next: specifier: 16.0.6 - version: 16.0.6(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 16.0.6(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) eslint-plugin-import: specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + version: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-jsdoc: specifier: ^50.6.9 - version: 50.8.0(eslint@9.39.2(jiti@2.6.1)) + version: 50.8.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2) + version: 5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2) prettier: specifier: 3.5.2 version: 3.5.2 tailwindcss: specifier: ^4.0.0 - version: 4.1.18 + version: 4.1.17 typescript: specifier: ^5 - version: 5.9.3 + version: 5.9.2 packages: + '@acemir/cssom@0.9.30': + resolution: {integrity: sha512-9CnlMCI0LmCIq0olalQqdWrJHPzm0/tw3gzOA9zJSgvFX7Xau3D24mAGa4BtwxwY69nsuJW6kQqqCzf/mEcQgg==} + '@adraffy/ens-normalize@1.10.1': resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} - '@adraffy/ens-normalize@1.11.1': - resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} + '@adraffy/ens-normalize@1.11.0': + resolution: {integrity: sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==} '@alloc/quick-lru@5.2.0': 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'} + '@aptos-labs/aptos-cli@1.1.1': resolution: {integrity: sha512-sB7CokCM6s76SLJmccysbnFR+MDik6udKfj2+9ZsmTLV0/t73veIeCDKbvWJmbW267ibx4HiGbPI7L+1+yjEbQ==} hasBin: true @@ -1428,44 +1490,50 @@ packages: '@asamuzakjp/css-color@4.1.1': resolution: {integrity: sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==} - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + '@asamuzakjp/dom-selector@6.7.6': + resolution: {integrity: sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + '@babel/compat-data@7.28.0': + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} engines: {node: '>=6.9.0'} - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + '@babel/core@7.28.3': + resolution: {integrity: sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.0': - resolution: {integrity: sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==} + '@babel/generator@7.28.3': + resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.27.3': resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.28.6': - resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} + '@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 - '@babel/helper-create-regexp-features-plugin@7.28.5': - resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} + '@babel/helper-create-regexp-features-plugin@7.27.1': + resolution: {integrity: sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.6.6': - resolution: {integrity: sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==} + '@babel/helper-define-polyfill-provider@0.6.5': + resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1473,16 +1541,16 @@ packages: resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-member-expression-to-functions@7.28.5': - resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1491,8 +1559,8 @@ packages: resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} '@babel/helper-remap-async-to-generator@7.27.1': @@ -1501,8 +1569,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.28.6': - resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1515,29 +1583,29 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.28.6': - resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==} + '@babel/helper-wrap-function@7.28.3': + resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.28.6': - resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + '@babel/helpers@7.28.3': + resolution: {integrity: sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.0': - resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} + '@babel/parser@7.28.3': + resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': - resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1': + resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1560,8 +1628,8 @@ packages: peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6': - resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==} + '@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 @@ -1572,26 +1640,26 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-assertions@7.28.6': - resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==} + '@babel/plugin-syntax-import-assertions@7.27.1': + resolution: {integrity: sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.28.6': - resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.28.6': - resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.28.6': - resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1608,14 +1676,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.29.0': - resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} + '@babel/plugin-transform-async-generator-functions@7.28.0': + resolution: {integrity: sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.28.6': - resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==} + '@babel/plugin-transform-async-to-generator@7.27.1': + resolution: {integrity: sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1626,44 +1694,44 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.28.6': - resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==} + '@babel/plugin-transform-block-scoping@7.28.0': + resolution: {integrity: sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.28.6': - resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==} + '@babel/plugin-transform-class-properties@7.27.1': + resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.28.6': - resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==} + '@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.6': - resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==} + '@babel/plugin-transform-classes@7.28.3': + resolution: {integrity: sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.28.6': - resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==} + '@babel/plugin-transform-computed-properties@7.27.1': + resolution: {integrity: sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.28.5': - resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} + '@babel/plugin-transform-destructuring@7.28.0': + resolution: {integrity: sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.28.6': - resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==} + '@babel/plugin-transform-dotall-regex@7.27.1': + resolution: {integrity: sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1674,8 +1742,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0': - resolution: {integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==} + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1686,14 +1754,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-explicit-resource-management@7.28.6': - resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==} + '@babel/plugin-transform-explicit-resource-management@7.28.0': + resolution: {integrity: sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-exponentiation-operator@7.28.6': - resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==} + '@babel/plugin-transform-exponentiation-operator@7.27.1': + resolution: {integrity: sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1716,8 +1784,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-json-strings@7.28.6': - resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==} + '@babel/plugin-transform-json-strings@7.27.1': + resolution: {integrity: sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1728,8 +1796,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-logical-assignment-operators@7.28.6': - resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==} + '@babel/plugin-transform-logical-assignment-operators@7.27.1': + resolution: {integrity: sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1746,14 +1814,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-commonjs@7.28.6': - resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.29.0': - resolution: {integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==} + '@babel/plugin-transform-modules-systemjs@7.27.1': + resolution: {integrity: sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1764,8 +1832,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': - resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1776,20 +1844,20 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-nullish-coalescing-operator@7.28.6': - resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==} + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1': + resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-numeric-separator@7.28.6': - resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==} + '@babel/plugin-transform-numeric-separator@7.27.1': + resolution: {integrity: sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.28.6': - resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} + '@babel/plugin-transform-object-rest-spread@7.28.0': + resolution: {integrity: sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1800,14 +1868,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-catch-binding@7.28.6': - resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==} + '@babel/plugin-transform-optional-catch-binding@7.27.1': + resolution: {integrity: sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-chaining@7.28.6': - resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==} + '@babel/plugin-transform-optional-chaining@7.27.1': + resolution: {integrity: sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1818,14 +1886,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.28.6': - resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==} + '@babel/plugin-transform-private-methods@7.27.1': + resolution: {integrity: sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-property-in-object@7.28.6': - resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==} + '@babel/plugin-transform-private-property-in-object@7.27.1': + resolution: {integrity: sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1854,8 +1922,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx@7.28.6': - resolution: {integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==} + '@babel/plugin-transform-react-jsx@7.27.1': + resolution: {integrity: sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1866,14 +1934,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.29.0': - resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} + '@babel/plugin-transform-regenerator@7.28.3': + resolution: {integrity: sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regexp-modifiers@7.28.6': - resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==} + '@babel/plugin-transform-regexp-modifiers@7.27.1': + resolution: {integrity: sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1890,8 +1958,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-spread@7.28.6': - resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==} + '@babel/plugin-transform-spread@7.27.1': + resolution: {integrity: sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1914,8 +1982,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typescript@7.28.6': - resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==} + '@babel/plugin-transform-typescript@7.28.0': + resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1926,8 +1994,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-property-regex@7.28.6': - resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==} + '@babel/plugin-transform-unicode-property-regex@7.27.1': + resolution: {integrity: sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1938,14 +2006,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-sets-regex@7.28.6': - resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==} + '@babel/plugin-transform-unicode-sets-regex@7.27.1': + resolution: {integrity: sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.29.0': - resolution: {integrity: sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==} + '@babel/preset-env@7.28.3': + resolution: {integrity: sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1955,32 +2023,32 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/preset-react@7.28.5': - resolution: {integrity: sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==} + '@babel/preset-react@7.27.1': + resolution: {integrity: sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/preset-typescript@7.28.5': - resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==} + '@babel/preset-typescript@7.27.1': + resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.28.6': - resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + '@babel/runtime@7.28.3': + resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==} engines: {node: '>=6.9.0'} - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + '@babel/traverse@7.28.3': + resolution: {integrity: sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + '@babel/types@7.28.2': + resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} engines: {node: '>=6.9.0'} '@base-org/account@1.1.1': @@ -2050,8 +2118,8 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@coinbase/cdp-sdk@1.44.0': - resolution: {integrity: sha512-0I5O1DzbchR91GAYQAU8lxx6q9DBvN0no9IBwrTKLHW8t5bABMg8dzQ/jrGRd6lr/QFJJW4L0ZSLGae5jsxGWw==} + '@coinbase/cdp-sdk@1.36.1': + resolution: {integrity: sha512-eL8PfuPMXdEKQ6v/AwlDbTpiLhmnwZPAxzJ2m90qL8oEQuYenALX8JqNKg0LBQ/sPM6c2vx109YvFx49g5vSYQ==} '@coinbase/onchainkit@0.38.19': resolution: {integrity: sha512-4uiujoTO5/8/dpWVZoTlBC7z0Y1N5fgBYDR6pKN/r6a8pX83ObUuOSGhSzJ8Xbu8NpPU6TXX+VuzLiwiLg/irg==} @@ -2095,24 +2163,28 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-syntax-patches-for-csstree@1.0.26': - resolution: {integrity: sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA==} + '@csstools/css-syntax-patches-for-csstree@1.0.22': + resolution: {integrity: sha512-qBcx6zYlhleiFfdtzkRgwNC7VVoAwfK76Vmsw5t+PbvtdknO9StgRk7ROvq9so1iqbdW4uLIDAsXRsTfUrIoOw==} + engines: {node: '>=18'} '@csstools/css-tokenizer@3.0.4': resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} - '@ecies/ciphers@0.2.5': - resolution: {integrity: sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==} + '@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.8.1': - resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} + '@emnapi/core@1.5.0': + resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==} + + '@emnapi/runtime@1.5.0': + resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} - '@emnapi/runtime@1.8.1': - resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + '@emnapi/runtime@1.7.1': + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} @@ -2121,354 +2193,198 @@ packages: resolution: {integrity: sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==} engines: {node: '>=18'} - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + '@esbuild/aix-ppc64@0.25.9': + resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + '@esbuild/android-arm64@0.25.9': + resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + '@esbuild/android-arm@0.25.9': + resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + '@esbuild/android-x64@0.25.9': + resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + '@esbuild/darwin-arm64@0.25.9': + resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + '@esbuild/darwin-x64@0.25.9': + resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + '@esbuild/freebsd-arm64@0.25.9': + resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + '@esbuild/freebsd-x64@0.25.9': + resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + '@esbuild/linux-arm64@0.25.9': + resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + '@esbuild/linux-arm@0.25.9': + resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + '@esbuild/linux-ia32@0.25.9': + resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + '@esbuild/linux-loong64@0.25.9': + resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + '@esbuild/linux-mips64el@0.25.9': + resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + '@esbuild/linux-ppc64@0.25.9': + resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + '@esbuild/linux-riscv64@0.25.9': + resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + '@esbuild/linux-s390x@0.25.9': + resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + '@esbuild/linux-x64@0.25.9': + resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + '@esbuild/netbsd-arm64@0.25.9': + resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + '@esbuild/netbsd-x64@0.25.9': + resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + '@esbuild/openbsd-arm64@0.25.9': + resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + '@esbuild/openbsd-x64@0.25.9': + resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + '@esbuild/openharmony-arm64@0.25.9': + resolution: {integrity: sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + '@esbuild/sunos-x64@0.25.9': + resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + '@esbuild/win32-arm64@0.25.9': + resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + '@esbuild/win32-ia32@0.25.9': + resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + '@esbuild/win32-x64@0.25.9': + resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + '@eslint-community/eslint-utils@4.8.0': + resolution: {integrity: sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + '@eslint/config-helpers@0.3.1': + resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.3': - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.2': - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + '@eslint/js@9.34.0': + resolution: {integrity: sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ethereumjs/common@3.2.0': @@ -2487,20 +2403,29 @@ packages: resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} engines: {node: '>=14'} - '@farcaster/frame-sdk@0.1.13': - resolution: {integrity: sha512-x4r6rz2vsReCaE0SThFx2rL9BTc9BW5UKcv2ednOFSSzejHSlxxd0SHH27Insrv4w56r6OAg+5YFGPwh3LZ/WA==} + '@exodus/bytes@1.8.0': + resolution: {integrity: sha512-8JPn18Bcp8Uo1T82gR8lh2guEOa5KKU/IEKvvdp0sgmi7coPBWf1Doi1EXsGZb2ehc8ym/StJCjffYV+ne7sXQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@exodus/crypto': ^1.0.0-rc.4 + peerDependenciesMeta: + '@exodus/crypto': + optional: true + + '@farcaster/frame-sdk@0.1.9': + resolution: {integrity: sha512-r5cAKgHn4w8Q1jaCi84uKqItfNRd6h8Lk0YyQaz5kMoEIeJ4C0gXPpyqKPYP2TVDFuvaexg2KvzCO2CQdygWyQ==} engines: {node: '>=22.11.0'} - '@farcaster/miniapp-core@0.5.0': - resolution: {integrity: sha512-3d4rMjKrSv6z2eUHczAP00p3+0zRaoSNUgQUyLM2BLpoi43cXmXmSP5E/tX0xE5//vkBKPLRzXE+nKoMyNL5kQ==} + '@farcaster/miniapp-core@0.3.8': + resolution: {integrity: sha512-LaRG1L3lxHqo5pP/E2CX9hNqusR0C8hX3QTV2+hzmQJz6IGvmSpH6Q9ivlLyDfbdqokiMFo5Y3Z1EX1zBHMEQQ==} - '@farcaster/miniapp-sdk@0.2.2': - resolution: {integrity: sha512-Z1POThw2yZL255BxZ+18hx+w6rzK47XzovSHpnKSmPFBqfIOPV5J3DuuhNe7vSQeQuMwZnYeUz8TvzxHqvvhPw==} + '@farcaster/miniapp-sdk@0.1.9': + resolution: {integrity: sha512-hn0dlIy0JP2Hx6PgKcn9bjYwyPS/SQgYJ/a0qjzG8ZsDfUdjsMPf3yI/jicBipTml/UUoKcbqXM68fsrsbNMKA==} - '@farcaster/miniapp-wagmi-connector@1.1.0': - resolution: {integrity: sha512-gf0nDx9nNJ6hJXbFBCgiTitb0eEqBvCU/njcyTXf7ebZhT0pzOrarOod2dkeisU5Py+WWjFyOVcqmeo4G3IvDA==} + '@farcaster/miniapp-wagmi-connector@1.0.0': + resolution: {integrity: sha512-vMRZbekUUctnAUvBFhNoEsJlujRRdxop94fDy5LrKiRR9ax0wtp8gCvLYO+LpaP2PtGs0HFpRwlHNDJWvBR8bg==} peerDependencies: - '@farcaster/miniapp-sdk': ^0.2.0 + '@farcaster/miniapp-sdk': ^0.1.0 '@wagmi/core': ^2.14.1 viem: ^2.21.55 @@ -2509,11 +2434,6 @@ packages: 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: @@ -2534,6 +2454,12 @@ packages: peerDependencies: react: '>= 16 || ^19.0.0-rc' + '@hono/node-server@1.19.1': + resolution: {integrity: sha512-h44e5s+ByUriaRIbeS/C74O8v90m0A95luyYQGMF7KEn96KkYMXO7bZAwombzTpjQTU4e0TkU8U1WBIXlwuwtA==} + engines: {node: '>=18.14.1'} + peerDependencies: + hono: ^4 + '@hono/node-server@1.19.9': resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} engines: {node: '>=18.14.1'} @@ -2702,6 +2628,10 @@ packages: '@types/node': optional: true + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -2715,14 +2645,14 @@ packages: '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@jridgewell/trace-mapping@0.3.30': + resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} - '@lit-labs/ssr-dom-shim@1.5.1': - resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==} + '@lit-labs/ssr-dom-shim@1.4.0': + resolution: {integrity: sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==} - '@lit/reactive-element@2.1.2': - resolution: {integrity: sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==} + '@lit/reactive-element@2.1.1': + resolution: {integrity: sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==} '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -2775,6 +2705,15 @@ packages: '@metamask/sdk-analytics@0.0.5': resolution: {integrity: sha512-fDah+keS1RjSUlC8GmYXvx6Y26s3Ax1U9hGpWb6GSY5SAdmTSIqp2CvYy6yW0WgLhnYhW+6xERuD0eVqV63QIQ==} + '@metamask/sdk-communication-layer@0.32.0': + resolution: {integrity: sha512-dmj/KFjMi1fsdZGIOtbhxdg3amxhKL/A5BqSU4uh/SyDKPub/OT+x5pX8bGjpTL1WPWY/Q0OIlvFyX3VWnT06Q==} + peerDependencies: + cross-fetch: ^4.0.0 + eciesjs: '*' + eventemitter2: ^6.4.9 + readable-stream: ^3.6.2 + socket.io-client: ^4.5.1 + '@metamask/sdk-communication-layer@0.33.1': resolution: {integrity: sha512-0bI9hkysxcfbZ/lk0T2+aKVo1j0ynQVTuB3sJ5ssPWlz+Z3VwveCkP1O7EVu1tsVVCb0YV5WxK9zmURu2FIiaA==} peerDependencies: @@ -2784,9 +2723,15 @@ 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==} @@ -2794,8 +2739,8 @@ packages: resolution: {integrity: sha512-fLgJnDOXFmuVlB38rUN5SmU7hAFQcCjrg3Vrxz67KTY7YHFnSNEKvX4avmEBdOI0yTCxZjwMCFEqsC8k2+Wd3g==} engines: {node: '>=16.0.0'} - '@metamask/utils@11.9.0': - resolution: {integrity: sha512-wRnoSDD9jTWOge/+reFviJQANhS+uy8Y+OEwRanp5mQeGTjBFmK1r2cTOnei2UCZRV1crXHzeJVSFEoDDcgRbA==} + '@metamask/utils@11.7.0': + resolution: {integrity: sha512-IamqpZF8Lr4WeXJ84fD+Sy+v1Zo05SYuMPHHBrZWpzVbnHAmXQpL4ckn9s5dfA+zylp3WGypaBPb6SBZdOhuNQ==} engines: {node: ^18.18 || ^20.14 || >=22} '@metamask/utils@5.0.2': @@ -2810,8 +2755,8 @@ packages: resolution: {integrity: sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g==} engines: {node: '>=16.0.0'} - '@modelcontextprotocol/sdk@1.25.3': - resolution: {integrity: sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==} + '@modelcontextprotocol/sdk@1.26.0': + resolution: {integrity: sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==} engines: {node: '>=18'} peerDependencies: '@cfworker/json-schema': ^4.1.1 @@ -2823,56 +2768,56 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@next/env@16.1.6': - resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==} + '@next/env@16.0.10': + resolution: {integrity: sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==} '@next/eslint-plugin-next@16.0.6': resolution: {integrity: sha512-9INsBF3/4XL0/tON8AGsh0svnTtDMLwv3iREGWnWkewGdOnd790tguzq9rX8xwrVthPyvaBHhw1ww0GZz0jO5Q==} - '@next/swc-darwin-arm64@16.1.6': - resolution: {integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==} + '@next/swc-darwin-arm64@16.0.10': + resolution: {integrity: sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@16.1.6': - resolution: {integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==} + '@next/swc-darwin-x64@16.0.10': + resolution: {integrity: sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@16.1.6': - resolution: {integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==} + '@next/swc-linux-arm64-gnu@16.0.10': + resolution: {integrity: sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@16.1.6': - resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==} + '@next/swc-linux-arm64-musl@16.0.10': + resolution: {integrity: sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@16.1.6': - resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==} + '@next/swc-linux-x64-gnu@16.0.10': + resolution: {integrity: sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@16.1.6': - resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==} + '@next/swc-linux-x64-musl@16.0.10': + resolution: {integrity: sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@16.1.6': - resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==} + '@next/swc-win32-arm64-msvc@16.0.10': + resolution: {integrity: sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@16.1.6': - resolution: {integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==} + '@next/swc-win32-x64-msvc@16.0.10': + resolution: {integrity: sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2947,6 +2892,10 @@ packages: resolution: {integrity: sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ==} deprecated: 'The package is now available as "qr": npm install qr' + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@pkgr/core@0.2.9': resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -2980,128 +2929,108 @@ packages: '@reown/appkit@1.7.8': resolution: {integrity: sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA==} - '@rollup/rollup-android-arm-eabi@4.57.1': - resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + '@rollup/rollup-android-arm-eabi@4.50.0': + resolution: {integrity: sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.57.1': - resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + '@rollup/rollup-android-arm64@4.50.0': + resolution: {integrity: sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.57.1': - resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + '@rollup/rollup-darwin-arm64@4.50.0': + resolution: {integrity: sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.57.1': - resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + '@rollup/rollup-darwin-x64@4.50.0': + resolution: {integrity: sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.57.1': - resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + '@rollup/rollup-freebsd-arm64@4.50.0': + resolution: {integrity: sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.57.1': - resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + '@rollup/rollup-freebsd-x64@4.50.0': + resolution: {integrity: sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': - resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': + resolution: {integrity: sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.57.1': - resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + '@rollup/rollup-linux-arm-musleabihf@4.50.0': + resolution: {integrity: sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.57.1': - resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + '@rollup/rollup-linux-arm64-gnu@4.50.0': + resolution: {integrity: sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.57.1': - resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + '@rollup/rollup-linux-arm64-musl@4.50.0': + resolution: {integrity: sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.57.1': - resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} - cpu: [loong64] - os: [linux] - - '@rollup/rollup-linux-loong64-musl@4.57.1': - resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': + resolution: {integrity: sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.57.1': - resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-ppc64-musl@4.57.1': - resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + '@rollup/rollup-linux-ppc64-gnu@4.50.0': + resolution: {integrity: sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.57.1': - resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + '@rollup/rollup-linux-riscv64-gnu@4.50.0': + resolution: {integrity: sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.57.1': - resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + '@rollup/rollup-linux-riscv64-musl@4.50.0': + resolution: {integrity: sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.57.1': - resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + '@rollup/rollup-linux-s390x-gnu@4.50.0': + resolution: {integrity: sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.57.1': - resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + '@rollup/rollup-linux-x64-gnu@4.50.0': + resolution: {integrity: sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.57.1': - resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + '@rollup/rollup-linux-x64-musl@4.50.0': + resolution: {integrity: sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==} cpu: [x64] os: [linux] - '@rollup/rollup-openbsd-x64@4.57.1': - resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.57.1': - resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + '@rollup/rollup-openharmony-arm64@4.50.0': + resolution: {integrity: sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.57.1': - resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + '@rollup/rollup-win32-arm64-msvc@4.50.0': + resolution: {integrity: sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.57.1': - resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + '@rollup/rollup-win32-ia32-msvc@4.50.0': + resolution: {integrity: sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.57.1': - resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.57.1': - resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + '@rollup/rollup-win32-x64-msvc@4.50.0': + resolution: {integrity: sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==} cpu: [x64] os: [win32] @@ -3159,11 +3088,6 @@ packages: peerDependencies: '@solana/kit': ^2.1.0 - '@solana-program/system@0.10.0': - resolution: {integrity: sha512-Go+LOEZmqmNlfr+Gjy5ZWAdY5HbYzk2RBewD9QinEU/bBSzpFfzqDRT55JjFRBGJUvMgf3C2vfXEGT4i8DSI4g==} - peerDependencies: - '@solana/kit': ^5.0 - '@solana-program/token-2022@0.4.2': resolution: {integrity: sha512-zIpR5t4s9qEU3hZKupzIBxJ6nUV5/UVyIT400tu9vT1HMs5JHxaTTsb5GUhYjiiTvNwU0MQavbwc4Dl29L0Xvw==} peerDependencies: @@ -3186,14 +3110,17 @@ packages: peerDependencies: '@solana/kit': ^5.0 - '@solana/accounts@5.5.1': - resolution: {integrity: sha512-TfOY9xixg5rizABuLVuZ9XI2x2tmWUC/OoN556xwfDlhBHBjKfszicYYOyD6nbFmwTGYarCmyGIdteXxTXIdhQ==} + '@solana/accounts@5.0.0': + resolution: {integrity: sha512-0JzBdEobgp8NBdhhu+GgwNDh7e8KkHDsSTVZAnNQgvT3taOz0Mwv5E48MuEeDhW6DLFwWVAx/FO3pvibG/NGwA==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/accounts@5.1.0': + resolution: {integrity: sha512-Q1KzykCrl/YjLUH2RXF8vPq65U/ehAV2SHZicPbZ0jvgQUU6X1+Eca+0ilxA9xH8srYn3YTVDyEs/LYdfbY/2A==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/accounts@6.1.0': resolution: {integrity: sha512-0jhmhSSS71ClLtBQIDrLlhkiNER4M9RIXTl1eJ1yJoFlE608JaKHTjNWsdVKdke7uBD6exdjNZkIVmouQPHMcA==} @@ -3210,14 +3137,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/addresses@5.5.1': - resolution: {integrity: sha512-5xoah3Q9G30HQghu/9BiHLb5pzlPKRC3zydQDmE3O9H//WfayxTFppsUDCL6FjYUHqj/wzK6CWHySglc2RkpdA==} + '@solana/addresses@5.0.0': + resolution: {integrity: sha512-bVk+khc1ZZQHMri25csosM/ikuyPcB/CZidDM/ZMBX0CoJErpHJnmcID5mYOmv4/UHbqo2OANuEaGcFO0Q37sw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/addresses@5.1.0': + resolution: {integrity: sha512-X84qSZLgve9YeYsyxGI49WnfEre53tdFu4x9/4oULBgoj8d0A+P9VGLYzmRJ0YFYKRcZG7U4u3MQpI5uLZ1AsQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/addresses@6.1.0': resolution: {integrity: sha512-QT04Vie4iICaalQQRJFMGj/P56IxXiwFtVuZHu1qjZUNmuGTOvX6G98b27RaGtLzpJ3NIku/6OtKxLUBqAKAyQ==} @@ -3234,14 +3164,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/assertions@5.5.1': - resolution: {integrity: sha512-YTCSWAlGwSlVPnWtWLm3ukz81wH4j2YaCveK+TjpvUU88hTy6fmUqxi0+hvAMAe4zKXpJyj3Az7BrLJRxbIm4Q==} + '@solana/assertions@5.0.0': + resolution: {integrity: sha512-2kIykk90kYciQW6bp+KaE6jRd1Y2CgHPeJxxlc5chQnjhoG6eiD8VXvocs6AvqPTht0p/SoEj9jH5tT4oG/bcg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/assertions@5.1.0': + resolution: {integrity: sha512-5But2wyxuvGXMIOnD0jBMQ9yq1QQF2LSK3IbIRSkAkXbD3DS6O2tRvKUHNhogd+BpkPyCGOQHBycezgnxmStlg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/assertions@6.1.0': resolution: {integrity: sha512-pLgxB2xxTk2QfTaWpnRpSMYgaPkKYDQgptRvbwmuDQnOW1Zopg+42MT2UrDGd3UFMML1uOFPxIwKM6m51H0uXw==} @@ -3252,24 +3185,36 @@ packages: typescript: optional: true + '@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/codecs-core@2.0.0-rc.1': + resolution: {integrity: sha512-bauxqMfSs8EHD0JKESaNmNuNvkvHSuN3bbWAF5RjOfDu2PugxHrvRebmYauvSumZ3cTfQ4HJJX6PG5rN852qyQ==} + peerDependencies: + typescript: '>=5' + '@solana/codecs-core@2.3.0': resolution: {integrity: sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/codecs-core@5.5.1': - resolution: {integrity: sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw==} + '@solana/codecs-core@5.0.0': + resolution: {integrity: sha512-rCG2d8OaamVF2/J//YyCgDqNJpUytVVltw9C8mJtEz5c6Se/LR6BFuG8g4xeJswq/ab4RFk5/HFdgbvNjKgQjA==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/codecs-core@5.1.0': + resolution: {integrity: sha512-vDwi03mxWeWCS5Il6BCdNdifYdOoHVz97YOmbWGIt45b77Ivu5NUYeSD2+ccl6fSw8eYQ6QaqqKXMjbSfsXv4g==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/codecs-core@6.1.0': resolution: {integrity: sha512-5rNnDOOm2GRFMJbd9imYCPNvGOrQ+TZ53NCkFFWbbB7f+L9KkLeuuAsDMFN1lCziJFlymvN785YtDnMeWj2W+g==} @@ -3280,20 +3225,28 @@ packages: typescript: optional: true + '@solana/codecs-data-structures@2.0.0-rc.1': + resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==} + peerDependencies: + typescript: '>=5' + '@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@5.5.1': - resolution: {integrity: sha512-97bJWGyUY9WvBz3mX1UV3YPWGDTez6btCfD0ip3UVEXJbItVuUiOkzcO5iFDUtQT5riKT6xC+Mzl+0nO76gd0w==} + '@solana/codecs-data-structures@5.0.0': + resolution: {integrity: sha512-y503Pqmv0LHcfcf0vQJGaxDvydQJbyCo8nK3nxn56EhFj5lBQ1NWb3WvTd83epigwuZurW2MhJARrpikfhQglQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/codecs-data-structures@5.1.0': + resolution: {integrity: sha512-ftAwL/jsurFrk9kFVhkTLdQ8fGZ8I0PcbVH+V1a0dIP2aKDofGePvK0XbwZE/ohizC9gEIZxyBX5IgRKk5PXyg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/codecs-data-structures@6.1.0': resolution: {integrity: sha512-1cb9g5hrrucTuGkGxqVVq7dCwSMnn4YqwTe365iKkK8HBpLBmUl8XATf1MUs5UtDun1g9eNWOL72Psr8mIUqTQ==} @@ -3304,20 +3257,28 @@ packages: typescript: optional: true + '@solana/codecs-numbers@2.0.0-rc.1': + resolution: {integrity: sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==} + peerDependencies: + typescript: '>=5' + '@solana/codecs-numbers@2.3.0': resolution: {integrity: sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/codecs-numbers@5.5.1': - resolution: {integrity: sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw==} + '@solana/codecs-numbers@5.0.0': + resolution: {integrity: sha512-a2+skRLuUK02f/XFe4L0e1+wHCyfK25PkyseFps1v1l4pvevukFwth/EhSyrs6w5CsTJRVoR7MuE3E00PM4egw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/codecs-numbers@5.1.0': + resolution: {integrity: sha512-Ea5/9yjDNOrDZcI40UGzzi6Aq1JNsmzM4m5pOk6Xb3JRZ0YdKOv/MwuCqb6jRgzZ7SQjHhkfGL43kHLJA++bOw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/codecs-numbers@6.1.0': resolution: {integrity: sha512-YPQwwl6LE3igH23ah+d8kgpyE5xFcPbuwhxCDsLWqY/ESrvO/0YQSbsgIXahbhZxN59ZC4uq1LnHhBNbpCSVQg==} @@ -3328,6 +3289,12 @@ packages: typescript: optional: true + '@solana/codecs-strings@2.0.0-rc.1': + resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5' + '@solana/codecs-strings@2.3.0': resolution: {integrity: sha512-y5pSBYwzVziXu521hh+VxqUtp0hYGTl1eWGoc1W+8mdvBdC1kTqm/X7aYQw33J42hw03JjryvYOvmGgk3Qz/Ug==} engines: {node: '>=20.18.0'} @@ -3335,17 +3302,22 @@ packages: fastestsmallesttextencoderdecoder: ^1.0.22 typescript: '>=5.3.3' - '@solana/codecs-strings@5.5.1': - resolution: {integrity: sha512-7klX4AhfHYA+uKKC/nxRGP2MntbYQCR3N6+v7bk1W/rSxYuhNmt+FN8aoThSZtWIKwN6BEyR1167ka8Co1+E7A==} + '@solana/codecs-strings@5.0.0': + resolution: {integrity: sha512-ALkRwpV8bGR6qjAYw0YXZwp2YI4wzvKOJGmx04Ut8gMdbaUx7qOcJkhEQKI6ZVC3lAWSIS1N1wGccUZDwvfKxw==} engines: {node: '>=20.18.0'} peerDependencies: fastestsmallesttextencoderdecoder: ^1.0.22 - typescript: ^5.0.0 - peerDependenciesMeta: + typescript: '>=5.3.3' + + '@solana/codecs-strings@5.1.0': + resolution: {integrity: sha512-014xwl5T/3VnGW0gceizF47DUs5EURRtgGmbWIR5+Z32yxgQ6hT9Zl0atZbL268RHbUQ03/J8Ush1StQgy7sfQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5.3.3' + peerDependenciesMeta: fastestsmallesttextencoderdecoder: optional: true - typescript: - optional: true '@solana/codecs-strings@6.1.0': resolution: {integrity: sha512-pRH5uAn4VCFUs2rYiDITyWsRnpvs3Uh/nhSc6OSP/kusghcCcCJcUzHBIjT4x08MVacXmGUlSLe/9qPQO+QK3Q==} @@ -3359,14 +3331,22 @@ packages: typescript: optional: true - '@solana/codecs@5.5.1': - resolution: {integrity: sha512-Vea29nJub/bXjfzEV7ZZQ/PWr1pYLZo3z0qW0LQL37uKKVzVFRQlwetd7INk3YtTD3xm9WUYr7bCvYUk3uKy2g==} + '@solana/codecs@2.0.0-rc.1': + resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==} + peerDependencies: + typescript: '>=5' + + '@solana/codecs@5.0.0': + resolution: {integrity: sha512-KOw0gFUSBxIMDWLJ3AkVFkEci91dw0Rpx3C6y83Our7fSW+SEP8vRZklCElieYR85LHVB1QIEhoeHR7rc+Ifkw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/codecs@5.1.0': + resolution: {integrity: sha512-krSuf/E2Sa/4oASZ/jb/5KGUG58m1/bQdLrKvBnoAFhYj7zZf+8V4UqHGTV5n2NCQfmMyORsg9n2saKjkUzo8w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/codecs@6.1.0': resolution: {integrity: sha512-VHBS3t8fyVjE0Nqo6b4TUnzdwdRaVo+B5ufHhPLbbjkEXzz8HB4E/OBjgasn+zWGlfScfQAiBFOsfZjbVWu4XA==} @@ -3377,6 +3357,12 @@ packages: typescript: optional: true + '@solana/errors@2.0.0-rc.1': + resolution: {integrity: sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==} + hasBin: true + peerDependencies: + typescript: '>=5' + '@solana/errors@2.3.0': resolution: {integrity: sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==} engines: {node: '>=20.18.0'} @@ -3384,15 +3370,19 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/errors@5.5.1': - resolution: {integrity: sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg==} + '@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.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/errors@5.1.0': + resolution: {integrity: sha512-JlTyekErWa6Fdcwu1Hrh+jZxjM4YxyorGCFDRVZlmHZFkp5N00DWKcYnSGZrTF8E6ZZEP9pfS2XwM8y7p7HPww==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' '@solana/errors@6.1.0': resolution: {integrity: sha512-cqSwcw3Rmn85UR7PyF5nKPdlQsRYBkx7YGRvFaJ6Sal1PM+bfolhL5iT7STQoXxdhXGYwHMPg7kZYxmMdjwnJA==} @@ -3410,14 +3400,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/fast-stable-stringify@5.5.1': - resolution: {integrity: sha512-Ni7s2FN33zTzhTFgRjEbOVFO+UAmK8qi3Iu0/GRFYK4jN696OjKHnboSQH/EacQ+yGqS54bfxf409wU5dsLLCw==} + '@solana/fast-stable-stringify@5.0.0': + resolution: {integrity: sha512-sGTbu7a4/olL+8EIOOJ7IZjzqOOpCJcK1UaVJ6015sRgo9vwGf4jg9KtXEYv5LVhLCTYmAb50L4BaIUcBph/Ig==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/fast-stable-stringify@5.1.0': + resolution: {integrity: sha512-ACZo7cH/5EXsBmruw/0gU2/PXL2l4aET0YpL93H6QEaZwEAICFD8cLkj20nBcfLTf4srEiuKtwuSDeONTWIulw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/fast-stable-stringify@6.1.0': resolution: {integrity: sha512-QXUfDFaJCFeARsxJgScWmJ153Tit7Cimk9y0UWWreNBr2Aphi67Nlcj/tr7UABTO0Qaw/0gwrK76zz3m1t3nIw==} @@ -3434,14 +3427,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/functional@5.5.1': - resolution: {integrity: sha512-tTHoJcEQq3gQx5qsdsDJ0LEJeFzwNpXD80xApW9o/PPoCNimI3SALkZl+zNW8VnxRrV3l3yYvfHWBKe/X3WG3w==} + '@solana/functional@5.0.0': + resolution: {integrity: sha512-UNBrpfzBL4dKD2iucjNnrkFbnjz5ZYDu2OvrIBAcCSQsxxgHMamUj1n3EDe6kl1us49YG1r05Ho8QLqNrbkVbw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/functional@5.1.0': + resolution: {integrity: sha512-R6jacWU0Gr+j49lTDp+FSECBolqw2Gq7JlC22rI0JkcxJiiAlp3G80v6zAYq0FkHzxZbjyR6//JYUXSwliem5g==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/functional@6.1.0': resolution: {integrity: sha512-+Sm8ldVxSTHIKaZDvcBu81FPjknXx6OMPlakkKmXjKxPgVLl86ruqMo2yEwoDUHV7DysLrLLcRNn13rfulomRw==} @@ -3452,14 +3448,17 @@ packages: typescript: optional: true - '@solana/instruction-plans@5.5.1': - resolution: {integrity: sha512-7z3CB7YMcFKuVvgcnNY8bY6IsZ8LG61Iytbz7HpNVGX2u1RthOs1tRW8luTzSG1MPL0Ox7afyAVMYeFqSPHnaQ==} + '@solana/instruction-plans@5.0.0': + resolution: {integrity: sha512-n9oFOMFUPYKEhsXzrXT97QBQ2WvOTar+5SFEj/IOtRuCn4gl2kh0369cjXZpFwUdE3tmKr1zfYFNwbtiNx5pvg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/instruction-plans@5.1.0': + resolution: {integrity: sha512-friMgHt0z5jQlCyyTDXfwAMYjCAagI7QYR+hLWB/BmvSuRpai0ddToWbWJoqrNRM312xZ+Oy/qjC3+Ftzi0DLA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/instruction-plans@6.1.0': resolution: {integrity: sha512-zcsHg544t1zn7LLOVUxOWYlsKn9gvT7R+pL3cTiP2wFNoUN0h9En87H6nVqkZ8LWw23asgW0uM5uJGwfBx2h1Q==} @@ -3476,14 +3475,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/instructions@5.5.1': - resolution: {integrity: sha512-h0G1CG6S+gUUSt0eo6rOtsaXRBwCq1+Js2a+Ps9Bzk9q7YHNFA75/X0NWugWLgC92waRp66hrjMTiYYnLBoWOQ==} + '@solana/instructions@5.0.0': + resolution: {integrity: sha512-12dbrmwERT1o6NTr/Uvrjj/ZsiteSXoT5Gi+dnjIeRNHWg9H+gEFuFzJvTDVKlNg34CZ71xdvbVdbV0V8gKGvg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/instructions@5.1.0': + resolution: {integrity: sha512-fkwpUwwqk5K14T/kZDnCrfeR0kww49HBx+BK8xdSeJx+bt4QTwAHa9YeOkGhGrHEFVEJEUf8FKoxxTzZzJZtKQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/instructions@6.1.0': resolution: {integrity: sha512-w1LdbJ3yanESckNTYC5KPckgN/25FyGCm07WWrs+dCnnpRNeLiVHIytXCPmArOVAXVkOYidXzhWmqCzqKUjYaA==} @@ -3500,14 +3502,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/keys@5.5.1': - resolution: {integrity: sha512-KRD61cL7CRL+b4r/eB9dEoVxIf/2EJ1Pm1DmRYhtSUAJD2dJ5Xw8QFuehobOGm9URqQ7gaQl+Fkc1qvDlsWqKg==} + '@solana/keys@5.0.0': + resolution: {integrity: sha512-kWkR7NslpTttk5i1BhBNCDtVQDkEtgkdsM3Jp9TGPk0GFjBjBwrQStw3vvwLe8itEIvRFGFZU6JHEk8HLS0WLQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/keys@5.1.0': + resolution: {integrity: sha512-ma4zTTuSOmtTCvATHMfUGNTw0Vqah/6XPe1VmLc66ohwXMI3yqatX1FQPXgDZozr15SvLAesfs7/bgl2TRoe9w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/keys@6.1.0': resolution: {integrity: sha512-C/SGCl3VOgBQZ0mLrMxCcJYnMsGpgE8wbx29jqRY+R91m5YhS1f/GfXJPR1lN/h7QGrJ6YDm8eI0Y3AZ7goKHg==} @@ -3518,14 +3523,17 @@ packages: typescript: optional: true - '@solana/kit@5.5.1': - resolution: {integrity: sha512-irKUGiV2yRoyf+4eGQ/ZeCRxa43yjFEL1DUI5B0DkcfZw3cr0VJtVJnrG8OtVF01vT0OUfYOcUn6zJW5TROHvQ==} + '@solana/kit@5.0.0': + resolution: {integrity: sha512-3ahtzmmMgU+1l2YMhQJSKKm14IdvCycOE/m4XNMu/4icBIptmBgZxrmgRpPHqBilBa+Krp/hBuTg4HWl9IAgWw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/kit@5.1.0': + resolution: {integrity: sha512-oNQRzI0+mGWmXy05psO0J7r9Boy8PF7LH5H0Y9Jxvs10AbG4oSOBtyj20EccsRrr+jkqLw42fqb/4rNuASfvsA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/kit@6.1.0': resolution: {integrity: sha512-24exn11BPonquufyCkGgypVtmN4JOsdGMsbF3EZ4kFyk7ZNryCn/N8eELr1FCVrHWRXoc0xy/HFaESBULTMf6g==} @@ -3542,14 +3550,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/nominal-types@5.5.1': - resolution: {integrity: sha512-I1ImR+kfrLFxN5z22UDiTWLdRZeKtU0J/pkWkO8qm/8WxveiwdIv4hooi8pb6JnlR4mSrWhq0pCIOxDYrL9GIQ==} + '@solana/nominal-types@5.0.0': + resolution: {integrity: sha512-Qn7xH4UG2rDAv+wAyheP4jWvX3oQmbZ/woxFZwug7PaRLvyjUswGr38Hil+SjiQyFDo+un1UqWM9N9yusUeeZQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/nominal-types@5.1.0': + resolution: {integrity: sha512-+4Cm+SpK+D811i9giqv4Up93ZlmUcZfLDHkSH24F4in61+Y2TKA+XKuRtKhNytQMmqCfbvJZ9MHFaIeZw5g+Bg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/nominal-types@6.1.0': resolution: {integrity: sha512-+skHjN0arNNB9TLsGqA94VCx7euyGURI+qG6wck6E4D7hH6i6DxGiVrtKRghx+smJkkLtTm9BvdVKGoeNQYr7Q==} @@ -3560,14 +3571,11 @@ packages: typescript: optional: true - '@solana/offchain-messages@5.5.1': - resolution: {integrity: sha512-g+xHH95prTU+KujtbOzj8wn+C7ZNoiLhf3hj6nYq3MTyxOXtBEysguc97jJveUZG0K97aIKG6xVUlMutg5yxhw==} + '@solana/offchain-messages@5.1.0': + resolution: {integrity: sha512-6FUXjiIJprjWa7y/T4E3rUb3HKi3P5zpBweBEwDflEEJ/QlieWUw7xlGAOvZ1eF3Wi+6LfcrdtZOwIkuv6o9Sg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' '@solana/offchain-messages@6.1.0': resolution: {integrity: sha512-jrUb7HGUnRA+k44upcqKeevtEdqMxYRSlFdE0JTctZunGlP3GCcTl12tFOpbnFHvBLt8RwS62+nyeES8zzNwXA==} @@ -3578,26 +3586,25 @@ packages: typescript: optional: true - '@solana/options@5.5.1': - resolution: {integrity: sha512-eo971c9iLNLmk+yOFyo7yKIJzJ/zou6uKpy6mBuyb/thKtS/haiKIc3VLhyTXty3OH2PW8yOlORJnv4DexJB8A==} + '@solana/options@2.0.0-rc.1': + resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==} + peerDependencies: + typescript: '>=5' + + '@solana/options@5.0.0': + resolution: {integrity: sha512-ezHVBFb9FXVSn8LUVRD2tLb6fejU0x8KtGEYyCYh0J0pQuXSITV0IQCjcEopvu/ZxWdXOJyzjvmymnhz90on5A==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' - '@solana/options@6.1.0': - resolution: {integrity: sha512-/4FtVfR6nkHkMCumyh7/lJ6jMqyES6tKUbOJRa6gJxcIUWeRDu+XrHTHLf3gRNUqDAbFvW8FMIrQm7PdreZgRA==} + '@solana/options@5.1.0': + resolution: {integrity: sha512-PqgfALd0yhK+QFaYIbRFTV6hBpiy5xwdu07zSw1RLoNvt1sg+MRsRFDk9R8ZdEdiM69PY/cKiClVSjpNzLLcJg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' - '@solana/plugin-core@5.5.1': - resolution: {integrity: sha512-VUZl30lDQFJeiSyNfzU1EjYt2QZvoBFKEwjn1lilUJw7KgqD5z7mbV7diJhT+dLFs36i0OsjXvq5kSygn8YJ3A==} + '@solana/options@6.1.0': + resolution: {integrity: sha512-/4FtVfR6nkHkMCumyh7/lJ6jMqyES6tKUbOJRa6gJxcIUWeRDu+XrHTHLf3gRNUqDAbFvW8FMIrQm7PdreZgRA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: ^5.0.0 @@ -3632,14 +3639,17 @@ packages: typescript: optional: true - '@solana/programs@5.5.1': - resolution: {integrity: sha512-7U9kn0Jsx1NuBLn5HRTFYh78MV4XN145Yc3WP/q5BlqAVNlMoU9coG5IUTJIG847TUqC1lRto3Dnpwm6T4YRpA==} + '@solana/programs@5.0.0': + resolution: {integrity: sha512-BKOfBDrSUCJGZ+qKk2aFLu0nU9/84o6z/VDCJkLjaNNuTv8nOlSYq5flNzo1eyJmnpyW372qNvqqRN3AS23+FQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/programs@5.1.0': + resolution: {integrity: sha512-zAghXyRGixWNcarShlrnpjMD2115BZTF9JMLIcgkCYDOwjDPFIB/Y0hwDCH87N5uSjzlgkDpxKEL4ILewoZTRQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/programs@6.1.0': resolution: {integrity: sha512-i4L4gSlIHDsdYRt3/YKVKMIN3UuYSKHRqK9B+AejcIc0y6Y/AXnHqzmpBRXEhvTXz18nt59MLXpVU4wu7ASjJA==} @@ -3656,14 +3666,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/promises@5.5.1': - resolution: {integrity: sha512-T9lfuUYkGykJmppEcssNiCf6yiYQxJkhiLPP+pyAc2z84/7r3UVIb2tNJk4A9sucS66pzJnVHZKcZVGUUp6wzA==} + '@solana/promises@5.0.0': + resolution: {integrity: sha512-Qmg3UfYfWINEUvBQL3DkPOq34tTg5cfrkPlDtJmi8RVifsPqb6hksbKZGu7ASLZohxIDGmnYQY6oELI7Me+5yw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/promises@5.1.0': + resolution: {integrity: sha512-LU9wwS1PvGc/It610dclfq+JCuUEZSIWjvaF0+sqMP7QCk12Uz7MK2m9TtvLcjTvvKTIrucglRZP6qKroWRqGg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/promises@6.1.0': resolution: {integrity: sha512-/mUW6peXQiEOaylLpGv4vtkvPzQvSbfhX9j5PNIK/ry4S3SHRQ3j3W/oGy4y3LR5alwo7NcVbubrkh4e4xwcww==} @@ -3680,14 +3693,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-api@5.5.1': - resolution: {integrity: sha512-XWOQQPhKl06Vj0xi3RYHAc6oEQd8B82okYJ04K7N0Vvy3J4PN2cxeK7klwkjgavdcN9EVkYCChm2ADAtnztKnA==} + '@solana/rpc-api@5.0.0': + resolution: {integrity: sha512-IJbZZnX2B1ldXPok1NhneXTYq9ZvdJbE5Pryr03pZTlPJaWGqDcZuQ14nwR4s6PoUUgdT+p87QlLZqLb8MusoQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-api@5.1.0': + resolution: {integrity: sha512-eI1tY0i3gmih1C65gFECYbfPRpHEYqFp+9IKjpknZtYpQIe9BqBKSpfYpGiCAbKdN/TMadBNPOzdK15ewhkkvQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-api@6.1.0': resolution: {integrity: sha512-+hO5+kZjJHuUNATUQxlJ1+ztXFkgn1j46zRwt3X7kF+VHkW3wsQ7up0JTS+Xsacmkrj1WKfymQweq8JTrsAG8A==} @@ -3704,14 +3720,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-parsed-types@5.5.1': - resolution: {integrity: sha512-HEi3G2nZqGEsa3vX6U0FrXLaqnUCg4SKIUrOe8CezD+cSFbRTOn3rCLrUmJrhVyXlHoQVaRO9mmeovk31jWxJg==} + '@solana/rpc-parsed-types@5.0.0': + resolution: {integrity: sha512-fU9uqlOYAaBqgk2qCl+ntenBm7wuSFBRbIO/rVjeBPd/qPCvNZU+qFET+ERLK6wbCTSz0MmdHqPn1V8KCMOvZQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-parsed-types@5.1.0': + resolution: {integrity: sha512-ZJoXHNItALMNa1zmGrNnIh96RBlc9GpIqoaZkdE14mAQ7gWe7Oc0ejYavUeSCmcL0wZcvIFh50AsfVxrHr4+2Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-parsed-types@6.1.0': resolution: {integrity: sha512-YKccynVgWt/gbs0tBYstNw6BSVuOeWdeAldTB2OgH95o2Q04DpO4v97X1MZDysA4SvSZM30Ek5Ni5ss3kskgdw==} @@ -3728,14 +3747,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-spec-types@5.5.1': - resolution: {integrity: sha512-6OFKtRpIEJQs8Jb2C4OO8KyP2h2Hy1MFhatMAoXA+0Ik8S3H+CicIuMZvGZ91mIu/tXicuOOsNNLu3HAkrakrw==} + '@solana/rpc-spec-types@5.0.0': + resolution: {integrity: sha512-B0P/ylXVaCG5oSIV+kB88s2qoW996D8iKhc7RyF0C/AyYvklF6kCwv0N9ZVrWp0ibjlQ8St290WbBHJyo7QZkA==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-spec-types@5.1.0': + resolution: {integrity: sha512-B8/WyjmHpC34vXtAmTpZyPwRCm7WwoSkmjBcBouaaY1uilJ9+Wp2nptbq2cJyWairOoMSoI7v5kvvnrJuquq4Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-spec-types@6.1.0': resolution: {integrity: sha512-tldMv1b6VGcvcRrY5MDWKlsyEKH6K96zE7gAIpKDX2G4T47ZOV+OMA3nh6xQpRgtyCUBsej0t80qmvTBDX/5IQ==} @@ -3752,14 +3774,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-spec@5.5.1': - resolution: {integrity: sha512-m3LX2bChm3E3by4mQrH4YwCAFY57QBzuUSWqlUw7ChuZ+oLLOq7b2czi4i6L4Vna67j3eCmB3e+4tqy1j5wy7Q==} + '@solana/rpc-spec@5.0.0': + resolution: {integrity: sha512-1LD2SYEQ5bYhiBumznAPzymtxSX4nYLZd6u+FA0bAxNBVzHDvUUQzVSXHAoWROhlGrCyvtALTs9u0DIDlgZHCA==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-spec@5.1.0': + resolution: {integrity: sha512-y8B6fUWA1EBKXUsNo6b9EiFcQPsaJREPLlcIDbo4b6TucQNwvl7FHfpf1VHJL64SkI/WE69i2WEkiOJYjmLO0A==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-spec@6.1.0': resolution: {integrity: sha512-RxpkIGizCYhXGUcap7npV2S/rAXZ7P/liozY/ExjMmCxYTDwGIW33kp/uH/JRxuzrL8+f8FqY76VsqqIe+2VZw==} @@ -3776,14 +3801,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-subscriptions-api@5.5.1': - resolution: {integrity: sha512-5Oi7k+GdeS8xR2ly1iuSFkAv6CZqwG0Z6b1QZKbEgxadE1XGSDrhM2cn59l+bqCozUWCqh4c/A2znU/qQjROlw==} + '@solana/rpc-subscriptions-api@5.0.0': + resolution: {integrity: sha512-DGUn3C12swV2FConOlLFN14npIrCtnxehtMLjszMC7g6p/P6WNIz5uAgF7YcIkLBDV8uTeWhM0azmK+V8Qqhvg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-subscriptions-api@5.1.0': + resolution: {integrity: sha512-84e2AsgqAGiVloW3G4RzpHPkInknu3rEuFPut2/69eq3Ab97TiTz2s5kc9gJpprtGM+xbgnIfeuGqr5F+2bXQA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-subscriptions-api@6.1.0': resolution: {integrity: sha512-I6J+3VU0dda6EySKbDyd+1urC7RGIRPRp0DcWRVcy68NOLbq0I5C40Dn9O2Zf8iCdK4PbQ7JKdCvZ/bDd45hdg==} @@ -3801,13 +3829,21 @@ packages: typescript: '>=5.3.3' ws: ^8.18.0 - '@solana/rpc-subscriptions-channel-websocket@5.5.1': - resolution: {integrity: sha512-7tGfBBrYY8TrngOyxSHoCU5shy86iA9SRMRrPSyBhEaZRAk6dnbdpmUTez7gtdVo0BCvh9nzQtUycKWSS7PnFQ==} + '@solana/rpc-subscriptions-channel-websocket@5.0.0': + resolution: {integrity: sha512-vsYXyjVX/kExfpr91zfMKTmWKKFCM+dkhXQDAz5aEE7kAF3KSZDiOGeYvN8Rc85lbIt9QK6BLAT+NBMv4/N9Qg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 + typescript: '>=5.3.3' + ws: ^8.18.0 + + '@solana/rpc-subscriptions-channel-websocket@5.1.0': + resolution: {integrity: sha512-FzAEmHzXtlckNn7T/1dzDS7r5HmekYPstrtZKjDcVxuGMVBUkZTnb69t7EJvKNuKw1wYZEUd0EEegtC2K/9dZA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + ws: ^8.18.0 peerDependenciesMeta: - typescript: + ws: optional: true '@solana/rpc-subscriptions-channel-websocket@6.1.0': @@ -3825,14 +3861,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-subscriptions-spec@5.5.1': - resolution: {integrity: sha512-iq+rGq5fMKP3/mKHPNB6MC8IbVW41KGZg83Us/+LE3AWOTWV1WT20KT2iH1F1ik9roi42COv/TpoZZvhKj45XQ==} + '@solana/rpc-subscriptions-spec@5.0.0': + resolution: {integrity: sha512-erRLvZMncwnciJP6I1SlAk0CyRGIgt83PyHWOVCRXENP9Q5dZbZ9pm4lar2yIp8EjIMnodGHsQWIlKc1hlCQlQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-subscriptions-spec@5.1.0': + resolution: {integrity: sha512-ORfjKtainnYisql6z4YsXByVwY8/rWsedVWn5oe/V7Og9LyetTM7hwJ8FbUdRDZwyLlUrI0cEE1aG+3ma/8tPw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-subscriptions-spec@6.1.0': resolution: {integrity: sha512-P06jhqzHpZGaLeJmIQkpDeMDD1xUp53ARpmXMsduMC+U5ZKQt29CLo+JrR18boNtls6WfttjVMEbzF25/4UPVA==} @@ -3849,14 +3888,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-subscriptions@5.5.1': - resolution: {integrity: sha512-CTMy5bt/6mDh4tc6vUJms9EcuZj3xvK0/xq8IQ90rhkpYvate91RjBP+egvjgSayUg9yucU9vNuUpEjz4spM7w==} + '@solana/rpc-subscriptions@5.0.0': + resolution: {integrity: sha512-cziOSzom/bwFZXViR9J+MxDsdLMcfvrXGw5Icng7dYODFKuVqfsDrQoG8uekJc4fREnbPEM2U+u9YnYSYbFbww==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-subscriptions@5.1.0': + resolution: {integrity: sha512-u/mafVzBbdqvYDD7x/98T5/5xk4Bl2C/90TaHiKx7FmutVC/H4QsritPTY0v9JG1dOVWbgIfUgfZ0C0DPkiYnA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-subscriptions@6.1.0': resolution: {integrity: sha512-sqwj+cQinWcZ7M/9+cudKxMPTkTQyGP73980vPCWM7vCpPkp2qzgrEie4DdgDGo+NMwIjeFgu2kdUuLHI3GD/g==} @@ -3873,14 +3915,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-transformers@5.5.1': - resolution: {integrity: sha512-OsWqLCQdcrRJKvHiMmwFhp9noNZ4FARuMkHT5us3ustDLXaxOjF0gfqZLnMkulSLcKt7TGXqMhBV+HCo7z5M8Q==} + '@solana/rpc-transformers@5.0.0': + resolution: {integrity: sha512-EMHhSgfF6/T4FfHbLaBP08SIj1ZAjxJr6WPNZMHLV7Cup8UfiB9TNV+bPQkum7JbVQNhUKzkKEEmyYqPfQoV9w==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-transformers@5.1.0': + resolution: {integrity: sha512-6v93xi/ewGS/xEiSktNQ0bh0Uiv1/q9nR5oiFMn3BiAJRC+FdMRMxCjp6H+/Tua7wdhpClaPKrZYBQHoIp59tw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-transformers@6.1.0': resolution: {integrity: sha512-OsSuuRPmsmS02eR9Zz+4iTsr+21hvEMEex5vwbwN6LAGPFlQ4ohqGkxgZCwmYd+Q5HWpnn9Uuf1MDTLLrKQkig==} @@ -3897,14 +3942,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-transport-http@5.5.1': - resolution: {integrity: sha512-yv8GoVSHqEV0kUJEIhkdOVkR2SvJ6yoWC51cJn2rSV7plr6huLGe0JgujCmB7uZhhaLbcbP3zxXxu9sOjsi7Fg==} + '@solana/rpc-transport-http@5.0.0': + resolution: {integrity: sha512-RoIEvWp7yc7rIRzNkOyjLs2UQF0odIEMWj87dbD4Ir4hwTCGo/TSTfQF/8KDV2etdke3Fa1K+W1NkpG2POqWFg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-transport-http@5.1.0': + resolution: {integrity: sha512-XoGX+2n/iXzoGb3Xrltbx8avnzp15vCfCGXuZpQWFL+xUg3P4CGl217XyDGjS5VxuUml+f/30xzWl18RaAIEcw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-transport-http@6.1.0': resolution: {integrity: sha512-3ebaTYuglLJagaXtjwDPVI7SQeeeFN2fpetpGKsuMAiti4fzYqEkNN8FIo+nXBzqqG/cVc2421xKjXl6sO1k/g==} @@ -3921,14 +3969,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc-types@5.5.1': - resolution: {integrity: sha512-bibTFQ7PbHJJjGJPmfYC2I+/5CRFS4O2p9WwbFraX1Keeel+nRrt/NBXIy8veP5AEn2sVJIyJPpWBRpCx1oATA==} + '@solana/rpc-types@5.0.0': + resolution: {integrity: sha512-JMbhwnV6nX4ezJv/KmaElOR0r/MZTKzKpaz6cv7FopLNuPrYCBrRCZKuM2XQh6gUbt9Mey08/KBOmOGmzTbL/g==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc-types@5.1.0': + resolution: {integrity: sha512-Rnpt5BuHQvnULPNXUC/yRqB+7iPbon95CSCeyRvPj5tJ4fx2JibvX3s/UEoud5vC+kRjPi/R0BGJ8XFvd3eDWg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc-types@6.1.0': resolution: {integrity: sha512-lR+Cb3v5Rpl49HsXWASy++TSE1AD86eRKabY+iuWnbBMYVGI4MamAvYwgBiygsCNc30nyO2TFNj9STMeSD/gAg==} @@ -3945,14 +3996,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/rpc@5.5.1': - resolution: {integrity: sha512-ku8zTUMrkCWci66PRIBC+1mXepEnZH/q1f3ck0kJZ95a06bOTl5KU7HeXWtskkyefzARJ5zvCs54AD5nxjQJ+A==} + '@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.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/rpc@5.1.0': + resolution: {integrity: sha512-j+ByLxFCoHWw9TnsGzkAVMFUfBDIUE53nIosJAYEsERpImD2mjwc33uDE6YXLKoaKRoYO4tc7IUzkKY1fQp/CA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/rpc@6.1.0': resolution: {integrity: sha512-R3y5PklW9mPy5Y34hsXj40R28zN2N7AGLnHqYJVkXkllwVub/QCNpSdDxAnbbS5EGOYGoUOW8s5LFoXwMSr1LQ==} @@ -3963,14 +4017,17 @@ packages: typescript: optional: true - '@solana/signers@5.5.1': - resolution: {integrity: sha512-FY0IVaBT2kCAze55vEieR6hag4coqcuJ31Aw3hqRH7mv6sV8oqwuJmUrx+uFwOp1gwd5OEAzlv6N4hOOple4sQ==} + '@solana/signers@5.0.0': + resolution: {integrity: sha512-9Hw6HekSEzj5O7UBBFPrxk96W5e8tMI3n7KbW7/QiKBDpuvYw9WtnjOsWUE7LqQoc1P0JjGEsrmxE9raQBLvuQ==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/signers@5.1.0': + resolution: {integrity: sha512-B8xO0SGN1ZWYfJROL+da3id279qNbXbXoqud+AuT5gur51RrS4YhNkTQ6khVbGtAOpPMAhkoZN0jnfCC1r33jQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/signers@6.1.0': resolution: {integrity: sha512-WDPGZJr6jIe2dEChv/2KQBnaga8dqOjd6ceBj/HcDHxnCudo66t7GlyZ9+9jMO40AgOOb7EDE5FDqPMrHMg5Yw==} @@ -3981,20 +4038,41 @@ packages: typescript: optional: true + '@solana/spl-token-group@0.0.7': + resolution: {integrity: sha512-V1N/iX7Cr7H0uazWUT2uk27TMqlqedpXHRqqAbVO2gvmJyT0E0ummMEAVQeXZ05ZhQ/xF39DLSdBp90XebWEug==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.95.3 + + '@solana/spl-token-metadata@0.1.6': + resolution: {integrity: sha512-7sMt1rsm/zQOQcUWllQX9mD2O6KhSAtY1hFR2hfFwgqfFWzSY9E9GDvFVNYUI1F0iQKcm6HmePU9QbKRXTEBiA==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.95.3 + + '@solana/spl-token@0.4.14': + resolution: {integrity: sha512-u09zr96UBpX4U685MnvQsNzlvw9TiY005hk1vJmJr7gMJldoPG1eYU5/wNEyOA5lkMLiR/gOi9SFD4MefOYEsA==} + engines: {node: '>=16'} + peerDependencies: + '@solana/web3.js': ^1.95.5 + '@solana/subscribable@2.3.0': resolution: {integrity: sha512-DkgohEDbMkdTWiKAoatY02Njr56WXx9e/dKKfmne8/Ad6/2llUIrax78nCdlvZW9quXMaXPTxZvdQqo9N669Og==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' - '@solana/subscribable@5.5.1': - resolution: {integrity: sha512-9K0PsynFq0CsmK1CDi5Y2vUIJpCqkgSS5yfDN0eKPgHqEptLEaia09Kaxc90cSZDZU5mKY/zv1NBmB6Aro9zQQ==} + '@solana/subscribable@5.0.0': + resolution: {integrity: sha512-C2TydIRRd5XUJ8asbARi67Sj/3DRLubWalnNoafBhDsrb88jsRVylntvwXgBw/+lwJdEPEsUnxvcdgdm+3lFlw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/subscribable@5.1.0': + resolution: {integrity: sha512-OeW5AJwKzHh18+PIPtghuuPJTmEep2Mhb3Lsrq4alas4fibmMGkr39z1HXxVF6l6e2lu/YGhHIDtuhouWmY7ow==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/subscribable@6.1.0': resolution: {integrity: sha512-HiUfkxN7638uxPmY4t0gI4+yqnFLZYJKFaT9EpWIuGrOB1d9n+uOHNs3NU7cVMwWXgfZUbztTCKyCVTbcwesNg==} @@ -4005,14 +4083,17 @@ packages: typescript: optional: true - '@solana/sysvars@5.5.1': - resolution: {integrity: sha512-k3Quq87Mm+geGUu1GWv6knPk0ALsfY6EKSJGw9xUJDHzY/RkYSBnh0RiOrUhtFm2TDNjOailg8/m0VHmi3reFA==} + '@solana/sysvars@5.0.0': + resolution: {integrity: sha512-F/GEb2rS8mrgDd79lDPyu8za9jGE6cRlS4jHNeKCkvOCJxdKQbX34JIzx4kwzjtvk7O8/yrDHfGdpA8nBg/l4w==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/sysvars@5.1.0': + resolution: {integrity: sha512-FJ9YIsLTAaajnOrYEYn54znstXJsvKndRhyCrlyiAEN1IXHw5HtZHploLF3ZZ78b7YU3uv3tFJMziXFBwPOn4Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/sysvars@6.1.0': resolution: {integrity: sha512-KwJyBBrAOx0BgkiZqOKAaySDb/0JrUFSBQL9/O1kSKGy9TCRX55Ytr1HxNTcTPppWNpbM6JZVK+yW3Ruey0HRw==} @@ -4029,14 +4110,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/transaction-confirmation@5.5.1': - resolution: {integrity: sha512-j4mKlYPHEyu+OD7MBt3jRoX4ScFgkhZC6H65on4Fux6LMScgivPJlwnKoZMnsgxFgWds0pl+BYzSiALDsXlYtw==} + '@solana/transaction-confirmation@5.0.0': + resolution: {integrity: sha512-LpusTopYIuQC8hBCloExkTr4Z5/zdp5f4IIbzD5XFeW3xXPZytS3H1IDMGk4bmLdZi9zQNA4lnNHKra5IncRbw==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/transaction-confirmation@5.1.0': + resolution: {integrity: sha512-6HnL0uH8tWZXJVuaoeTbCQp/FS11Bsc4GSlq+k0N21GdhTbFuqBhsxlAYWbzPWs9+/kYRGHqqXvBPCReWxT7BA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/transaction-confirmation@6.1.0': resolution: {integrity: sha512-akSjcqAMOGPFvKctFDSzhjcRc/45WbEVdVQ9mjgH6OYo7B11WZZZaeGPlzAw5KyuG34Px941xmICkBmNqEH47Q==} @@ -4053,14 +4137,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/transaction-messages@5.5.1': - resolution: {integrity: sha512-aXyhMCEaAp3M/4fP0akwBBQkFPr4pfwoC5CLDq999r/FUwDax2RE/h4Ic7h2Xk+JdcUwsb+rLq85Y52hq84XvQ==} + '@solana/transaction-messages@5.0.0': + resolution: {integrity: sha512-rJLe1wUGW5DovQFV0gjXHXnriPxTBgZ3TvGWnjCu2OIBU8mcQkQVJ7zzVZY2IAYlmJ6OSF9nvzhSt/ncPbkJPg==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/transaction-messages@5.1.0': + resolution: {integrity: sha512-9rNV2YJhd85WIMvnwa/vUY4xUw3ZTU17jP1KDo/fFZWk55a0ov0ATJJPyC5HAR1i6hT1cmJzGH/UHhnD9m/Q3w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/transaction-messages@6.1.0': resolution: {integrity: sha512-Dpv54LRVcfFbFEa/uB53LaY/TRfKuPGMKR7Z4F290zBgkj9xkpZkI+WLiJBiSloI7Qo2KZqXj3514BIeZvJLcg==} @@ -4077,14 +4164,17 @@ packages: peerDependencies: typescript: '>=5.3.3' - '@solana/transactions@5.5.1': - resolution: {integrity: sha512-8hHtDxtqalZ157pnx6p8k10D7J/KY/biLzfgh9R09VNLLY3Fqi7kJvJCr7M2ik3oRll56pxhraAGCC9yIT6eOA==} + '@solana/transactions@5.0.0': + resolution: {integrity: sha512-4TcsqH7JtgRKGGBIRRGz0n+tXu4h5TPPC49kkV0ygIndQaHW7FOZUYTwQ0epq0A5h9KYi+ClNbzF9xiuDbAD5Q==} engines: {node: '>=20.18.0'} peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=5.3.3' + + '@solana/transactions@5.1.0': + resolution: {integrity: sha512-06JwSPtz+38ozNgpysAXS2eTMPQCufIisXB6K88X8J4GF8ziqs4nkq0BpXAXn+MpZTkuMt+JeW2RxP3HKhXe5g==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' '@solana/transactions@6.1.0': resolution: {integrity: sha512-1dkiNJcTtlHm4Fvs5VohNVpv7RbvbUYYKV7lYXMPIskoLF1eZp0tVlEqD/cRl91RNz7HEysfHqBAwlcJcRmrRg==} @@ -4117,6 +4207,18 @@ packages: '@stablelib/wipe@1.0.1': resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + '@stellar/js-xdr@3.1.2': + resolution: {integrity: sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==} + + '@stellar/stellar-base@14.0.4': + resolution: {integrity: sha512-UbNW6zbdOBXJwLAV2mMak0bIC9nw3IZVlQXkv2w2dk1jgCbJjy3oRVC943zeGE5JAm0Z9PHxrIjmkpGhayY7kw==} + engines: {node: '>=20.0.0'} + + '@stellar/stellar-sdk@14.5.0': + resolution: {integrity: sha512-Uzjq+An/hUA+Q5ERAYPtT0+MMiwWnYYWMwozmZMjxjdL2MmSjucBDF8Q04db6K/ekU4B5cHuOfsdlrfaxQYblw==} + engines: {node: '>=20.0.0'} + hasBin: true + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -4198,72 +4300,72 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@swc/helpers@0.5.18': - resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==} + '@swc/helpers@0.5.17': + resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} '@szmarczak/http-timer@4.0.6': resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} engines: {node: '>=10'} - '@tailwindcss/node@4.1.18': - resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} + '@tailwindcss/node@4.1.17': + resolution: {integrity: sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==} - '@tailwindcss/oxide-android-arm64@4.1.18': - resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} + '@tailwindcss/oxide-android-arm64@4.1.17': + resolution: {integrity: sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.1.18': - resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} + '@tailwindcss/oxide-darwin-arm64@4.1.17': + resolution: {integrity: sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.1.18': - resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} + '@tailwindcss/oxide-darwin-x64@4.1.17': + resolution: {integrity: sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.1.18': - resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} + '@tailwindcss/oxide-freebsd-x64@4.1.17': + resolution: {integrity: sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': - resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17': + resolution: {integrity: sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': - resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.17': + resolution: {integrity: sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.1.18': - resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.17': + resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.1.18': - resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.17': + resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.1.18': - resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} + '@tailwindcss/oxide-linux-x64-musl@4.1.17': + resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.1.18': - resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} + '@tailwindcss/oxide-wasm32-wasi@4.1.17': + resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -4274,30 +4376,30 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': - resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} + '@tailwindcss/oxide-win32-arm64-msvc@4.1.17': + resolution: {integrity: sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.1.18': - resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.17': + resolution: {integrity: sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.1.18': - resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} + '@tailwindcss/oxide@4.1.17': + resolution: {integrity: sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==} engines: {node: '>= 10'} - '@tailwindcss/postcss@4.1.18': - resolution: {integrity: sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==} + '@tailwindcss/postcss@4.1.17': + resolution: {integrity: sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw==} - '@tanstack/query-core@5.90.20': - resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} + '@tanstack/query-core@5.90.11': + resolution: {integrity: sha512-f9z/nXhCgWDF4lHqgIE30jxLe4sYv15QodfdPDKYAk7nAEjNcndy4dHz3ezhdUaR23BpWa4I2EH4/DZ0//Uf8A==} - '@tanstack/react-query@5.90.20': - resolution: {integrity: sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw==} + '@tanstack/react-query@5.90.11': + resolution: {integrity: sha512-3uyzz01D1fkTLXuxF3JfoJoHQMU2fxsfJwE+6N5hHy0dVNoZOvwKP8Z2k7k1KDeD54N20apcJnG75TBAStIrBA==} peerDependencies: react: ^18 || ^19 @@ -4305,8 +4407,8 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.0': + resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==} '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} @@ -4314,8 +4416,8 @@ packages: '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -4329,14 +4431,14 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/express-serve-static-core@5.1.1': - resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} + '@types/express-serve-static-core@5.0.7': + resolution: {integrity: sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==} - '@types/express@5.0.6': - resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} + '@types/express@5.0.3': + resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==} - '@types/http-cache-semantics@4.0.4': - resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} @@ -4350,8 +4452,11 @@ packages: '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - '@types/lodash@4.17.23': - resolution: {integrity: sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==} + '@types/lodash@4.17.20': + resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -4359,8 +4464,8 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@22.19.7': - resolution: {integrity: sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==} + '@types/node@22.18.0': + resolution: {integrity: sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==} '@types/node@22.7.5': resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} @@ -4371,22 +4476,22 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + '@types/react-dom@19.1.9': + resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} peerDependencies: - '@types/react': ^19.2.0 + '@types/react': ^19.0.0 - '@types/react@19.2.10': - resolution: {integrity: sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==} + '@types/react@19.1.12': + resolution: {integrity: sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==} '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} - '@types/send@1.2.1': - resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + '@types/send@0.17.5': + resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==} - '@types/serve-static@2.2.0': - resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} + '@types/serve-static@1.15.8': + resolution: {integrity: sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==} '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -4400,63 +4505,122 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - '@typescript-eslint/eslint-plugin@8.54.0': - resolution: {integrity: sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==} + '@typescript-eslint/eslint-plugin@8.42.0': + resolution: {integrity: sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.54.0 + '@typescript-eslint/parser': ^8.42.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.54.0': - resolution: {integrity: sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==} + '@typescript-eslint/eslint-plugin@8.49.0': + resolution: {integrity: sha512-JXij0vzIaTtCwu6SxTh8qBc66kmf1xs7pI4UOiMDFVct6q86G0Zs7KRcEoJgY3Cav3x5Tq0MF5jwgpgLqgKG3A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: + '@typescript-eslint/parser': ^8.49.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.54.0': - resolution: {integrity: sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==} + '@typescript-eslint/parser@8.42.0': + resolution: {integrity: sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg==} + 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/parser@8.49.0': + resolution: {integrity: sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==} + 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.42.0': + resolution: {integrity: sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.49.0': + resolution: {integrity: sha512-/wJN0/DKkmRUMXjZUXYZpD1NEQzQAAn9QWfGwo+Ai8gnzqH7tvqS7oNVdTjKqOcPyVIdZdyCMoqN66Ia789e7g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.42.0': + resolution: {integrity: sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/scope-manager@8.49.0': + resolution: {integrity: sha512-npgS3zi+/30KSOkXNs0LQXtsg9ekZ8OISAOLGWA/ZOEn0ZH74Ginfl7foziV8DT+D98WfQ5Kopwqb/PZOaIJGg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.42.0': + resolution: {integrity: sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.54.0': - resolution: {integrity: sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==} + '@typescript-eslint/tsconfig-utils@8.49.0': + resolution: {integrity: sha512-8prixNi1/6nawsRYxet4YOhnbW+W9FK/bQPxsGB1D3ZrDzbJ5FXw5XmzxZv82X3B+ZccuSxo/X8q9nQ+mFecWA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/tsconfig-utils@8.54.0': - resolution: {integrity: sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==} + '@typescript-eslint/type-utils@8.42.0': + resolution: {integrity: sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ==} 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/type-utils@8.54.0': - resolution: {integrity: sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==} + '@typescript-eslint/type-utils@8.49.0': + resolution: {integrity: sha512-KTExJfQ+svY8I10P4HdxKzWsvtVnsuCifU5MvXrRwoP2KOlNZ9ADNEWWsQTJgMxLzS5VLQKDjkCT/YzgsnqmZg==} 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/types@8.54.0': - resolution: {integrity: sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==} + '@typescript-eslint/types@8.42.0': + resolution: {integrity: sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.54.0': - resolution: {integrity: sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==} + '@typescript-eslint/types@8.49.0': + resolution: {integrity: sha512-e9k/fneezorUo6WShlQpMxXh8/8wfyc+biu6tnAqA81oWrEic0k21RHzP9uqqpyBBeBKu4T+Bsjy9/b8u7obXQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.42.0': + resolution: {integrity: sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.54.0': - resolution: {integrity: sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==} + '@typescript-eslint/typescript-estree@8.49.0': + resolution: {integrity: sha512-jrLdRuAbPfPIdYNppHJ/D0wN+wwNfJ32YTAm10eJVsFmrVpXQnDWBn8niCSMlWjvml8jsce5E/O+86IQtTbJWA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.42.0': + resolution: {integrity: sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g==} + 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/utils@8.49.0': + resolution: {integrity: sha512-N3W7rJw7Rw+z1tRsHZbK395TWSYvufBXumYtEGzypgMUthlg0/hmCImeA8hgO2d2G4pd7ftpxxul2J8OdtdaFA==} 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/visitor-keys@8.54.0': - resolution: {integrity: sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==} + '@typescript-eslint/visitor-keys@8.42.0': + resolution: {integrity: sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/visitor-keys@8.49.0': + resolution: {integrity: sha512-LlKaciDe3GmZFphXIc79THF/YYBugZ7FS1pO581E/edlVVNbZKDy93evqmrfQ9/Y4uN0vVhX4iuchq26mK/iiA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -4596,10 +4760,10 @@ packages: '@vitest/utils@3.2.4': resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - '@wagmi/connectors@5.11.2': - resolution: {integrity: sha512-OkiElOI8xXGPDZE5UdG6NgDT3laSkEh9llX1DDapUnfnKecK3Tr/HUf5YzgwDhEoox8mdxp+8ZCjtnTKz56SdA==} + '@wagmi/connectors@5.9.9': + resolution: {integrity: sha512-6+eqU7P2OtxU2PkIw6kHojfYYUJykYG2K5rSkzVh29RDCAjhJqGEZW5f1b8kV5rUBORip1NpST8QTBNi96JHGQ==} peerDependencies: - '@wagmi/core': 2.21.2 + '@wagmi/core': 2.20.3 typescript: '>=5.0.4' viem: 2.x peerDependenciesMeta: @@ -4616,6 +4780,18 @@ packages: typescript: optional: true + '@wagmi/core@2.20.3': + resolution: {integrity: sha512-gsbuHnWxf0AYZISvR8LvF/vUCIq6/ZwT5f5/FKd6wLA7Wq05NihCvmQpIgrcVbpSJPL67wb6S8fXm3eJGJA1vQ==} + peerDependencies: + '@tanstack/query-core': '>=5.0.0' + typescript: '>=5.0.4' + viem: 2.x + peerDependenciesMeta: + '@tanstack/query-core': + optional: true + typescript: + optional: true + '@wagmi/core@2.22.1': resolution: {integrity: sha512-cG/xwQWsBEcKgRTkQVhH29cbpbs/TdcUJVFXCyri3ZknxhMyGv0YEjTcrNpRgt2SaswL1KrvslSNYKKo+5YEAg==} peerDependencies: @@ -4653,6 +4829,7 @@ packages: '@walletconnect/ethereum-provider@2.21.1': resolution: {integrity: sha512-SSlIG6QEVxClgl1s0LMk4xr2wg4eT3Zn/Hb81IocyqNSGfXpjtawWxKxiC5/9Z95f1INyBD6MctJbL/R1oBwIw==} + deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' '@walletconnect/events@1.0.1': resolution: {integrity: sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==} @@ -4697,9 +4874,11 @@ packages: '@walletconnect/sign-client@2.21.0': resolution: {integrity: sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA==} + deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' '@walletconnect/sign-client@2.21.1': resolution: {integrity: sha512-QaXzmPsMnKGV6tc4UcdnQVNOz4zyXgarvdIQibJ4L3EmLat73r5ZVl4c0cCOcoaV7rgM9Wbphgu5E/7jNcd3Zg==} + deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' '@walletconnect/time@1.0.2': resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} @@ -4712,9 +4891,11 @@ packages: '@walletconnect/universal-provider@2.21.0': resolution: {integrity: sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg==} + deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' '@walletconnect/universal-provider@2.21.1': resolution: {integrity: sha512-Wjx9G8gUHVMnYfxtasC9poGm8QMiPCpXpbbLFT+iPoQskDDly8BwueWnqKs4Mx2SdIAWAwuXeZ5ojk5qQOxJJg==} + deprecated: 'Reliability and performance improvements. See: https://github.com/WalletConnect/walletconnect-monorepo/releases' '@walletconnect/utils@2.21.0': resolution: {integrity: sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig==} @@ -4750,6 +4931,17 @@ 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.2.3: resolution: {integrity: sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==} peerDependencies: @@ -4812,10 +5004,18 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.2.0: + resolution: {integrity: sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==} + 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==} + engines: {node: '>=12'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -4904,8 +5104,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.11.1: - resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==} + axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} engines: {node: '>=4'} axios-retry@4.5.0: @@ -4913,6 +5113,9 @@ packages: peerDependencies: axios: 0.x || 1.x + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + axios@1.13.4: resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} @@ -4920,18 +5123,18 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} - babel-plugin-polyfill-corejs2@0.4.15: - resolution: {integrity: sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==} + babel-plugin-polyfill-corejs2@0.4.14: + resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.14.0: - resolution: {integrity: sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==} + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.6.6: - resolution: {integrity: sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==} + babel-plugin-polyfill-regenerator@0.6.5: + resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -4944,25 +5147,38 @@ packages: base-x@5.0.1: resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} + base32.js@0.1.0: + resolution: {integrity: sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==} + engines: {node: '>=0.12.0'} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.9.19: - resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} - hasBin: true - better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + 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.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + bn.js@5.2.2: resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} - body-parser@1.20.4: - resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} body-parser@2.2.2: @@ -4975,8 +5191,8 @@ packages: borsh@0.7.0: resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} - bowser@2.13.1: - resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} + bowser@2.12.1: + resolution: {integrity: sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==} brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -4988,8 +5204,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + browserslist@4.25.4: + resolution: {integrity: sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -5002,8 +5218,8 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - bufferutil@4.1.0: - resolution: {integrity: sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==} + bufferutil@4.0.9: + resolution: {integrity: sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==} engines: {node: '>=6.14.2'} bundle-require@5.1.0: @@ -5052,8 +5268,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001767: - resolution: {integrity: sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==} + caniuse-lite@1.0.30001739: + resolution: {integrity: sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==} chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} @@ -5073,18 +5289,14 @@ packages: charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} chokidar@4.0.3: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} - chokidar@5.0.0: - resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} - engines: {node: '>= 20.19.0'} - ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -5124,6 +5336,10 @@ packages: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} + commander@14.0.1: + resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} + engines: {node: '>=20'} + commander@14.0.2: resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} engines: {node: '>=20'} @@ -5175,19 +5391,19 @@ packages: cookie-es@1.2.2: resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} - cookie-signature@1.0.7: - resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} - core-js-compat@3.48.0: - resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} + core-js-compat@3.45.1: + resolution: {integrity: sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -5253,8 +5469,8 @@ packages: resolution: {integrity: sha512-legscpSpgSAeGEe0TNcai97DKt9Vd9AsAdOL7Uoetb52Ar/8eJm3LIa39qpv8wWzLFlNG4vVvppQM+teaMPj3A==} engines: {node: '>=20'} - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} @@ -5263,6 +5479,10 @@ packages: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} + data-urls@6.0.0: + resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} + engines: {node: '>=20'} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -5310,6 +5530,15 @@ packages: supports-color: optional: true + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -5442,15 +5671,18 @@ packages: duplexify@4.1.3: resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} - eciesjs@0.4.17: - resolution: {integrity: sha512-TOOURki4G7sD1wDCjj7NfLaXZZ49dFOeEb5y39IXpb8p0hRzVvfvzZHOi5JcT+PpyAbi/Y+lxPb8eTag2WYH8w==} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + eciesjs@0.4.15: + resolution: {integrity: sha512-r6kEJXDKecVOCj2nLMuXK/FCPeurW33+3JRpfXVbjLja3XUYFfD9I/JBreH6sUyzcm3G/YQboBjMla6poKeSdA==} engines: {bun: '>=1', deno: '>=2', node: '>=16'} ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.283: - resolution: {integrity: sha512-3vifjt1HgrGW/h76UEeny+adYApveS9dH2h3p57JYzBSXJIKUJAvtmIytDKjcSCt9xHfrNCFJ7gts6vkhuq++w==} + electron-to-chromium@1.5.214: + resolution: {integrity: sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -5461,6 +5693,10 @@ packages: encode-utf8@1.0.3: resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -5468,15 +5704,15 @@ packages: end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - engine.io-client@6.6.4: - resolution: {integrity: sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==} + engine.io-client@6.6.3: + resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==} engine.io-parser@5.2.3: resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} engines: {node: '>=10.0.0'} - enhanced-resolve@5.18.4: - resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} + enhanced-resolve@5.18.3: + resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} enquirer@2.4.1: @@ -5491,11 +5727,11 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} - error-ex@1.3.4: - resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.24.1: - resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -5506,8 +5742,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-iterator-helpers@1.2.2: - resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==} + es-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} engines: {node: '>= 0.4'} es-module-lexer@1.7.0: @@ -5535,16 +5771,11 @@ packages: es6-promise@4.2.8: resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - es6-promisify@5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true + es6-promisify@5.0.0: + resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + esbuild@0.25.9: + resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} engines: {node: '>=18'} hasBin: true @@ -5627,8 +5858,8 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-prettier@5.5.5: - resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==} + 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' @@ -5665,8 +5896,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + eslint@9.34.0: + resolution: {integrity: sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -5684,8 +5915,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -5734,9 +5965,6 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - eventemitter3@5.0.4: - resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -5745,22 +5973,26 @@ packages: resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} engines: {node: '>=18.0.0'} + eventsource@2.0.2: + resolution: {integrity: sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==} + engines: {node: '>=12.0.0'} + eventsource@3.0.7: resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} engines: {node: '>=18.0.0'} - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + expect-type@1.2.2: + resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} engines: {node: '>=12.0.0'} - express-rate-limit@7.5.1: - resolution: {integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==} + express-rate-limit@8.2.1: + resolution: {integrity: sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==} engines: {node: '>= 16'} peerDependencies: express: '>= 4.11' - express@4.22.1: - resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} express@5.2.1: @@ -5814,8 +6046,8 @@ packages: fastestsmallesttextencoderdecoder@1.0.22: resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} @@ -5826,10 +6058,16 @@ packages: picomatch: optional: true + feaxios@0.0.23: + resolution: {integrity: sha512-eghR0A21fvbkcQBgZuMfQhrXxJzC0GNUGC9fXhBge33D+mFDTwl0aJ35zoQQn575BhyjQitRc5N4f+L4cP708g==} + file-entry-cache@8.0.0: 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'} @@ -5838,8 +6076,8 @@ packages: resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} engines: {node: '>=0.10.0'} - finalhandler@1.3.2: - resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} finalhandler@2.1.1: @@ -5877,8 +6115,12 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} forwarded@0.2.0: @@ -5930,10 +6172,6 @@ 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'} @@ -5958,8 +6196,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.13.1: - resolution: {integrity: sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -5969,6 +6207,11 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -5999,17 +6242,20 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + graphql-request@6.1.0: resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} peerDependencies: graphql: 14 - 16 - graphql@16.12.0: - resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==} + graphql@16.11.0: + resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - h3@1.15.5: - resolution: {integrity: sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==} + h3@1.15.4: + resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==} has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} @@ -6044,6 +6290,10 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hono@4.10.7: + resolution: {integrity: sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw==} + engines: {node: '>=16.9.0'} + hono@4.11.7: resolution: {integrity: sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==} engines: {node: '>=16.9.0'} @@ -6052,9 +6302,17 @@ packages: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -6122,6 +6380,10 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} + ip-address@10.0.1: + resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} + engines: {node: '>= 12'} + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -6186,8 +6448,8 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.1.2: - resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} is-glob@4.0.3: @@ -6224,6 +6486,10 @@ packages: resolution: {integrity: sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==} engines: {node: '>=10'} + is-retry-allowed@3.0.0: + resolution: {integrity: sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==} + engines: {node: '>=12'} + is-set@2.0.3: resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} @@ -6296,8 +6562,11 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} - jayson@4.3.0: - resolution: {integrity: sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jayson@4.2.0: + resolution: {integrity: sha512-VfJ9t1YLwacIubLhONk0KFeosUBwstRWQ0IRT1KDjEjnVnSOVHC3uwugyV7L0c7R9lpVyrUGT2XWiBA1UTtpyg==} engines: {node: '>=8'} hasBin: true @@ -6308,6 +6577,9 @@ packages: jose@5.10.0: resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + jose@6.1.0: + resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==} + jose@6.1.3: resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} @@ -6328,6 +6600,10 @@ packages: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true @@ -6345,6 +6621,20 @@ packages: canvas: optional: true + jsdom@27.4.0: + resolution: {integrity: sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + 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'} @@ -6496,11 +6786,11 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lit-element@4.2.2: - resolution: {integrity: sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==} + lit-element@4.2.1: + resolution: {integrity: sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==} - lit-html@3.3.2: - resolution: {integrity: sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==} + lit-html@3.3.1: + resolution: {integrity: sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==} lit@3.3.0: resolution: {integrity: sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==} @@ -6523,11 +6813,14 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - lodash@4.17.23: - resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} @@ -6552,13 +6845,19 @@ packages: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} - lru-cache@11.2.5: - resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.2.4: + resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.18: + resolution: {integrity: sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -6647,6 +6946,10 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + mipd@0.0.7: resolution: {integrity: sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==} peerDependencies: @@ -6702,8 +7005,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - napi-postinstall@0.3.4: - resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} + napi-postinstall@0.3.3: + resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true @@ -6718,8 +7021,8 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - next@16.1.6: - resolution: {integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==} + next@16.0.10: + resolution: {integrity: sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==} engines: {node: '>=20.9.0'} hasBin: true peerDependencies: @@ -6761,11 +7064,11 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-mock-http@1.0.4: - resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + node-mock-http@1.0.2: + resolution: {integrity: sha512-zWaamgDUdo9SSLw47we78+zYw/bDr5gH8pH7oRRs8V3KmBtu8GLgGIbV2p/gRPd3LWpEOpjQj7X1FOU3VFMJ8g==} - node-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} @@ -6778,8 +7081,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nwsapi@2.2.23: - resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + nwsapi@2.2.21: + resolution: {integrity: sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==} obj-multiplex@1.0.0: resolution: {integrity: sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA==} @@ -6816,8 +7119,8 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} - ofetch@1.5.1: - resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + ofetch@1.4.1: + resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} on-exit-leak-free@0.2.0: resolution: {integrity: sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==} @@ -6886,6 +7189,22 @@ packages: typescript: optional: true + ox@0.9.3: + resolution: {integrity: sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==} + 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-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} @@ -6918,6 +7237,9 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@0.2.11: resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} @@ -6938,6 +7260,9 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parse5@8.0.0: + resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -6953,6 +7278,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} @@ -7022,26 +7351,6 @@ 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 - porto@0.2.35: resolution: {integrity: sha512-gu9FfjjvvYBgQXUHWTp6n3wkTxVtEcqFotM7i3GEZeoQbvLGbssAicCz6hFZ8+xggrJWwi/RLmbwNra50SMmUQ==} hasBin: true @@ -7110,15 +7419,15 @@ packages: preact@10.24.2: resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} - preact@10.28.3: - resolution: {integrity: sha512-tCmoRkPQLpBeWzpmbhryairGnhW9tKV6c6gr/w+RhoRoKEJwsjzipwp//1oCpGPOchvSLaAPlpcJi9MwMmoPyA==} + preact@10.27.2: + resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-linter-helpers@1.0.1: - resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} prettier@2.8.8: @@ -7167,6 +7476,10 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + qs@6.14.1: resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} engines: {node: '>=0.6'} @@ -7191,12 +7504,15 @@ packages: radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - raw-body@2.5.3: - resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} raw-body@3.0.2: @@ -7208,10 +7524,10 @@ packages: peerDependencies: react: ^19.2.1 - react-dom@19.2.4: - resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + react-dom@19.2.3: + resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: - react: ^19.2.4 + react: ^19.2.3 react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -7220,8 +7536,8 @@ packages: resolution: {integrity: sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==} engines: {node: '>=0.10.0'} - react@19.2.4: - resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + react@19.2.3: + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} read-yaml-file@1.1.0: @@ -7239,10 +7555,6 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} - engines: {node: '>= 20.19.0'} - real-require@0.1.0: resolution: {integrity: sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==} engines: {node: '>= 12.13.0'} @@ -7251,8 +7563,8 @@ packages: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - regenerate-unicode-properties@10.2.2: - resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} engines: {node: '>=4'} regenerate@1.4.2: @@ -7262,15 +7574,15 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - regexpu-core@6.4.0: - resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} engines: {node: '>=4'} regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.13.0: - resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true require-directory@2.1.1: @@ -7298,8 +7610,8 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} hasBin: true @@ -7314,8 +7626,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.57.1: - resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + rollup@4.50.0: + resolution: {integrity: sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -7323,8 +7635,8 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} - rpc-websockets@9.3.3: - resolution: {integrity: sha512-OkCsBBzrwxX4DoSv4Zlf9DgXKRB0MzVfCFg5MC+fNnf9ktr4SMWjsri0VNZQlDbCnGcImT6KNEv4ZoxktQhdpA==} + rpc-websockets@9.1.3: + resolution: {integrity: sha512-I+kNjW0udB4Fetr3vvtRuYZJS0PcSPyyvBcH5sDdoV8DFs5E4W2pTr7aiMlKfPxANTClP9RlqCPolj9dd5MsEA==} rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -7368,21 +7680,26 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + semver@7.7.3: resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true - send@0.19.2: - resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} send@1.2.1: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} - serve-static@1.16.3: - resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} serve-static@2.2.1: @@ -7459,12 +7776,12 @@ packages: snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} - socket.io-client@4.8.3: - resolution: {integrity: sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==} + socket.io-client@4.8.1: + resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} engines: {node: '>=10.0.0'} - socket.io-parser@4.2.5: - resolution: {integrity: sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==} + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} engines: {node: '>=10.0.0'} sonic-boom@2.8.0: @@ -7474,9 +7791,10 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.7.6: - resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} - engines: {node: '>= 12'} + 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 spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} @@ -7507,12 +7825,16 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} @@ -7535,6 +7857,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} engines: {node: '>= 0.4'} @@ -7568,6 +7894,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -7576,8 +7906,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + strip-literal@3.0.0: + resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} styled-jsx@5.1.6: resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} @@ -7592,8 +7922,8 @@ packages: babel-plugin-macros: optional: true - sucrase@3.35.1: - resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true @@ -7624,15 +7954,15 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - synckit@0.11.12: - resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} + synckit@0.11.11: + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} - tailwind-merge@2.6.1: - resolution: {integrity: sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==} + tailwind-merge@2.6.0: + resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} - tailwindcss@4.1.18: - resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} + tailwindcss@4.1.17: + resolution: {integrity: sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==} tapable@2.3.0: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} @@ -7661,6 +7991,10 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -7673,19 +8007,26 @@ packages: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + tinyspy@4.0.3: + resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} engines: {node: '>=14.0.0'} tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + tldts-core@7.0.19: + resolution: {integrity: sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==} + tldts@6.1.86: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - to-buffer@1.2.2: - resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} + tldts@7.0.19: + resolution: {integrity: sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==} + hasBin: true + + to-buffer@1.2.1: + resolution: {integrity: sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==} engines: {node: '>= 0.4'} to-regex-range@5.0.1: @@ -7696,23 +8037,37 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} + tough-cookie@6.0.0: + resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} + engines: {node: '>=16'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - ts-api-utils@2.4.0: - resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -7742,8 +8097,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsup@8.5.1: - resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + tsup@8.5.0: + resolution: {integrity: sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -7761,43 +8116,43 @@ packages: typescript: optional: true - tsx@4.21.0: - resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + tsx@4.20.5: + resolution: {integrity: sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==} engines: {node: '>=18.0.0'} hasBin: true - turbo-darwin-64@2.8.1: - resolution: {integrity: sha512-FQ6Uqxty/H1Nvn1dpBe8KUlMRclTuiyNSc1PCeDL/ad7M9ykpWutB51YpMpf9ibTA32M6wLdIRf+D96W6hDAtQ==} + turbo-darwin-64@2.5.6: + resolution: {integrity: sha512-3C1xEdo4aFwMJAPvtlPqz1Sw/+cddWIOmsalHFMrsqqydcptwBfu26WW2cDm3u93bUzMbBJ8k3zNKFqxJ9ei2A==} cpu: [x64] os: [darwin] - turbo-darwin-arm64@2.8.1: - resolution: {integrity: sha512-4bCcEpGP2/aSXmeN2gl5SuAmS1q5ykjubnFvSoXjQoCKtDOV+vc4CTl/DduZzUUutCVUWXjl8OyfIQ+DGCaV4A==} + turbo-darwin-arm64@2.5.6: + resolution: {integrity: sha512-LyiG+rD7JhMfYwLqB6k3LZQtYn8CQQUePbpA8mF/hMLPAekXdJo1g0bUPw8RZLwQXUIU/3BU7tXENvhSGz5DPA==} cpu: [arm64] os: [darwin] - turbo-linux-64@2.8.1: - resolution: {integrity: sha512-m99JRlWlEgXPR7mkThAbKh6jbTmWSOXM/c6rt8yd4Uxh0+wjq7+DYcQbead6aoOqmCP9akswZ8EXIv1ogKBblg==} + turbo-linux-64@2.5.6: + resolution: {integrity: sha512-GOcUTT0xiT/pSnHL4YD6Yr3HreUhU8pUcGqcI2ksIF9b2/r/kRHwGFcsHgpG3+vtZF/kwsP0MV8FTlTObxsYIA==} cpu: [x64] os: [linux] - turbo-linux-arm64@2.8.1: - resolution: {integrity: sha512-AsPlza3AsavJdl2o7FE67qyv0aLfmT1XwFQGzvwpoAO6Bj7S4a03tpUchZKNuGjNAkKVProQRFnB7PgUAScFXA==} + turbo-linux-arm64@2.5.6: + resolution: {integrity: sha512-10Tm15bruJEA3m0V7iZcnQBpObGBcOgUcO+sY7/2vk1bweW34LMhkWi8svjV9iDF68+KJDThnYDlYE/bc7/zzQ==} cpu: [arm64] os: [linux] - turbo-windows-64@2.8.1: - resolution: {integrity: sha512-GdqNO6bYShRsr79B+2G/2ssjLEp9uBTvLBJSWRtRCiac/SEmv8T6RYv9hu+h5oGbFALtnKNp6BQBw78RJURsPw==} + turbo-windows-64@2.5.6: + resolution: {integrity: sha512-FyRsVpgaj76It0ludwZsNN40ytHN+17E4PFJyeliBEbxrGTc5BexlXVpufB7XlAaoaZVxbS6KT8RofLfDRyEPg==} cpu: [x64] os: [win32] - turbo-windows-arm64@2.8.1: - resolution: {integrity: sha512-n40E6IpkzrShRo3yMdRpgnn1/sAbGC6tZXwyNu8fe9RsufeD7KBiaoRSvw8xLyqV3pd2yoTL2rdCXq24MnTCWA==} + turbo-windows-arm64@2.5.6: + resolution: {integrity: sha512-j/tWu8cMeQ7HPpKri6jvKtyXg9K1gRyhdK4tKrrchH8GNHscPX/F71zax58yYtLRWTiK04zNzPcUJuoS0+v/+Q==} cpu: [arm64] os: [win32] - turbo@2.8.1: - resolution: {integrity: sha512-pbSMlRflA0RAuk/0jnAt8pzOYh1+sKaT8nVtcs75OFGVWD0evleQRmKtHJJV42QOhaC3Hx9mUUSOom/irasbjA==} + turbo@2.5.6: + resolution: {integrity: sha512-gxToHmi9oTBNB05UjUsrWf0OyN5ZXtD0apOarC1KIx232Vp3WimRNy3810QzeNSgyD5rsaIDXlxlbnOzlouo+w==} hasBin: true tweetnacl@1.0.3: @@ -7831,20 +8186,20 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript-eslint@8.54.0: - resolution: {integrity: sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==} + typescript-eslint@8.49.0: + resolution: {integrity: sha512-zRSVH1WXD0uXczCXw+nsdjGPUdx4dfrs5VQoHnUWmv1U3oNlAKv4FUNdLDhVUg+gYn+a5hUESqch//Rv5wVhrg==} 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.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + typescript@5.9.2: + resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} engines: {node: '>=14.17'} hasBin: true - ufo@1.6.3: - resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} uint8arrays@3.1.0: resolution: {integrity: sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==} @@ -7862,8 +8217,8 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.20.0: - resolution: {integrity: sha512-PZDAAlMkNw5ZzN/ebfyrwzrMWfIf7Jbn9iM/I6SF456OKrb2wnfqVowaxEY/cMAM8MjFu1zhdpJyA0L+rTYwNw==} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} undici-types@7.22.0: resolution: {integrity: sha512-RKZvifiL60xdsIuC80UY0dq8Z7DbJUV8/l2hOVbyZAxBzEeQU4Z58+4ZzJ6WN2Lidi9KzT5EbiGX+PI/UGYuRw==} @@ -7876,12 +8231,12 @@ packages: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} - unicode-match-property-value-ecmascript@2.2.1: - resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} engines: {node: '>=4'} - unicode-property-aliases-ecmascript@2.2.0: - resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} universalify@0.1.2: @@ -7895,8 +8250,8 @@ packages: unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - unstorage@1.17.4: - resolution: {integrity: sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==} + unstorage@1.17.0: + resolution: {integrity: sha512-l9Z7lBiwtNp8ZmcoZ/dmPkFXFdtEdZtTZafCSnEIj3YvtkXeGAtL2rN8MQFy/0cs4eOLpuRJMp9ivdug7TCvww==} peerDependencies: '@azure/app-configuration': ^1.8.0 '@azure/cosmos': ^4.2.0 @@ -7904,14 +8259,14 @@ packages: '@azure/identity': ^4.6.0 '@azure/keyvault-secrets': ^4.9.0 '@azure/storage-blob': ^12.26.0 - '@capacitor/preferences': ^6 || ^7 || ^8 + '@capacitor/preferences': ^6.0.3 || ^7.0.0 '@deno/kv': '>=0.9.0' '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 '@planetscale/database': ^1.19.0 '@upstash/redis': ^1.34.3 '@vercel/blob': '>=0.27.1' - '@vercel/functions': ^2.2.12 || ^3.0.0 - '@vercel/kv': ^1 || ^2 || ^3 + '@vercel/functions': ^2.2.12 + '@vercel/kv': ^1.0.1 aws4fetch: ^1.0.20 db0: '>=0.2.1' idb-keyval: ^6.2.1 @@ -7957,8 +8312,8 @@ packages: uploadthing: optional: true - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -7966,6 +8321,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + urijs@1.19.11: + resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} + use-sync-external-store@1.2.0: resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: @@ -8025,6 +8383,22 @@ packages: typescript: optional: true + viem@2.37.3: + resolution: {integrity: sha512-hwoZqkFSy13GCFzIftgfIH8hNENvdlcHIvtLt73w91tL6rKmZjQisXWTahi1Vn5of8/JQ1FBKfwUus3YkDXwbw==} + 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 + viem@2.45.1: resolution: {integrity: sha512-LN6Pp7vSfv50LgwhkfSbIXftAM5J89lP9x8TeDa8QM7o41IxlHrDh0F9X+FfnCWtsz11pEVV5sn+yBUoOHNqYA==} peerDependencies: @@ -8046,8 +8420,8 @@ packages: vite: optional: true - vite@6.4.1: - resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} + vite@6.3.5: + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -8118,6 +8492,17 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + wagmi@2.16.9: + resolution: {integrity: sha512-5NbjvuNNhT0t0lQsDD5otQqZ5RZBM1UhInHoBq/Lpnr6xLLa8AWxYqHg5oZtGCdiUNltys11iBOS6z4mLepIqw==} + peerDependencies: + '@tanstack/react-query': '>=5.0.0' + react: '>=18' + typescript: '>=5.0.4' + viem: 2.x + peerDependenciesMeta: + typescript: + optional: true + wagmi@2.19.5: resolution: {integrity: sha512-RQUfKMv6U+EcSNNGiPbdkDtJwtuFxZWLmvDiQmjjBgkuPulUwDJsKhi7gjynzJdsx2yDqhHCXkKsbbfbIsHfcQ==} peerDependencies: @@ -8135,13 +8520,21 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} @@ -8151,9 +8544,16 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} + whatwg-url@15.1.0: + resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} + engines: {node: '>=20'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -8169,8 +8569,8 @@ packages: which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} which@2.0.2: @@ -8191,6 +8591,14 @@ packages: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -8278,6 +8686,11 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yaml@2.8.1: + resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} + engines: {node: '>= 14.6'} + hasBin: true + yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -8307,8 +8720,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zod@4.1.13: + resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} zustand@5.0.0: resolution: {integrity: sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==} @@ -8328,24 +8741,6 @@ packages: use-sync-external-store: optional: true - zustand@5.0.11: - resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==} - 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.3: resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} engines: {node: '>=12.20.0'} @@ -8366,12 +8761,20 @@ packages: snapshots: + '@acemir/cssom@0.9.30': + optional: true + '@adraffy/ens-normalize@1.10.1': {} - '@adraffy/ens-normalize@1.11.1': {} + '@adraffy/ens-normalize@1.11.0': {} '@alloc/quick-lru@5.2.0': {} + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.30 + '@aptos-labs/aptos-cli@1.1.1': dependencies: commander: 12.1.0 @@ -8401,770 +8804,762 @@ snapshots: '@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: 11.2.5 + lru-cache: 11.2.4 + + '@asamuzakjp/dom-selector@6.7.6': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.1.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.4 + optional: true - '@babel/code-frame@7.29.0': + '@asamuzakjp/nwsapi@2.3.9': + optional: true + + '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.27.1 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.0': {} + '@babel/compat-data@7.28.0': {} - '@babel/core@7.29.0': + '@babel/core@7.28.3': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.0 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.28.6 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/remapping': 2.3.5 + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) + '@babel/helpers': 7.28.3 + '@babel/parser': 7.28.3 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 convert-source-map: 2.0.0 - debug: 4.4.3 + debug: 4.4.1 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.29.0': + '@babel/generator@7.28.3': dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 + '@babel/parser': 7.28.3 + '@babel/types': 7.28.2 '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/trace-mapping': 0.3.30 jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.28.2 - '@babel/helper-compilation-targets@7.28.6': + '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/compat-data': 7.29.0 + '@babel/compat-data': 7.28.0 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 + browserslist: 4.25.4 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': + '@babel/helper-create-class-features-plugin@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.29.0 + '@babel/traverse': 7.28.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': + '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - regexpu-core: 6.4.0 + regexpu-core: 6.2.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)': + '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 debug: 4.4.3 lodash.debounce: 4.0.8 - resolve: 1.22.11 + resolve: 1.22.10 transitivePeerDependencies: - supports-color '@babel/helper-globals@7.28.0': {} - '@babel/helper-member-expression-to-functions@7.28.5': + '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.28.6': + '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.28.2 - '@babel/helper-plugin-utils@7.28.6': {} + '@babel/helper-plugin-utils@7.27.1': {} - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-wrap-function': 7.28.6 - '@babel/traverse': 7.29.0 + '@babel/helper-wrap-function': 7.28.3 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/core': 7.28.3 + '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.29.0 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.27.1': {} '@babel/helper-validator-option@7.27.1': {} - '@babel/helper-wrap-function@7.28.6': + '@babel/helper-wrap-function@7.28.3': dependencies: - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.3 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color - '@babel/helpers@7.28.6': + '@babel/helpers@7.28.3': dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 - '@babel/parser@7.29.0': + '@babel/parser@7.28.3': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.28.2 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.3) + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.28.3 + '@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.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-classes@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) - '@babel/traverse': 7.29.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/template': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/template': 7.27.2 - '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': + '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@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.29.0)': + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)': + '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) - '@babel/traverse': 7.29.0 + '@babel/core': 7.28.3 + '@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.3) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.3) + '@babel/traverse': 7.28.3 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@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.29.0)': + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-constant-elements@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-react-constant-elements@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)': + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/core': 7.28.3 + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - '@babel/types': 7.29.0 + '@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.3) + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': + '@babel/plugin-transform-regenerator@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@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.29.0)': + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.3) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/preset-env@7.29.0(@babel/core@7.29.0)': + '@babel/preset-env@7.28.3(@babel/core@7.28.3)': dependencies: - '@babel/compat-data': 7.29.0 - '@babel/core': 7.29.0 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/compat-data': 7.28.0 + '@babel/core': 7.28.3 + '@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.28.5(@babel/core@7.29.0) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) - '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.0) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) - '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) - '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) - '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) - babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) - babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.29.0) - babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) - core-js-compat: 3.48.0 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.3) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.3) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-class-static-block': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-transform-classes': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.3) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-regenerator': 7.28.3(@babel/core@7.28.3) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.3) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.3) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.3) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.3) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.3) + core-js-compat: 3.45.1 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/types': 7.29.0 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.28.2 esutils: 2.0.3 - '@babel/preset-react@7.28.5(@babel/core@7.29.0)': + '@babel/preset-react@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@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.29.0) - '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.3) + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': + '@babel/preset-typescript@7.27.1(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/core': 7.28.3 + '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) - '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.3) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.3) transitivePeerDependencies: - supports-color - '@babel/runtime@7.28.6': {} + '@babel/runtime@7.28.3': {} - '@babel/template@7.28.6': + '@babel/template@7.27.2': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.3 + '@babel/types': 7.28.2 - '@babel/traverse@7.29.0': + '@babel/traverse@7.28.3': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/parser': 7.28.3 + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.29.0': + '@babel/types@7.28.2': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@base-org/account@1.1.1(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': - 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.9.3)(zod@3.25.76) - preact: 10.24.2 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.3(@types/react@19.2.10)(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 + '@babel/helper-validator-identifier': 7.27.1 - '@base-org/account@1.1.1(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(zod@3.25.76)': + '@base-org/account@1.1.1(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': 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.9.3)(zod@3.25.76) + ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) preact: 10.24.2 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.3(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.3(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) transitivePeerDependencies: - '@types/react' - bufferutil @@ -9175,23 +9570,19 @@ snapshots: - utf-8-validate - zod - '@base-org/account@2.4.0(@types/react@19.2.10)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': + '@base-org/account@1.1.1(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@coinbase/cdp-sdk': 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) '@noble/hashes': 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 - ox: 0.6.9(typescript@5.9.3)(zod@3.25.76) + ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) preact: 10.24.2 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.3(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.3(@types/react@19.1.12)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) transitivePeerDependencies: - '@types/react' - bufferutil - - debug - - encoding - - fastestsmallesttextencoderdecoder - immer - react - typescript @@ -9199,17 +9590,17 @@ snapshots: - utf-8-validate - zod - '@base-org/account@2.4.0(@types/react@19.2.10)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(zod@3.25.76)': + '@base-org/account@2.4.0(@types/react@19.1.12)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@coinbase/cdp-sdk': 1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@coinbase/cdp-sdk': 1.36.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) '@noble/hashes': 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 - ox: 0.6.9(typescript@5.9.3)(zod@3.25.76) + ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) preact: 10.24.2 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.3(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.3(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) transitivePeerDependencies: - '@types/react' - bufferutil @@ -9260,7 +9651,7 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.29.8(@types/node@22.19.7)': + '@changesets/cli@2.29.8(@types/node@22.18.0)': dependencies: '@changesets/apply-release-plan': 7.0.14 '@changesets/assemble-release-plan': 6.0.9 @@ -9276,7 +9667,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@22.19.7) + '@inquirer/external-editor': 1.0.3(@types/node@22.18.0) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 ci-info: 3.9.0 @@ -9382,19 +9773,17 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 - '@coinbase/cdp-sdk@1.44.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@coinbase/cdp-sdk@1.36.1(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: - '@solana-program/system': 0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@solana-program/token': 0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)) - '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - abitype: 1.0.6(typescript@5.9.3)(zod@3.25.76) - axios: 1.13.4 - axios-retry: 4.5.0(axios@1.13.4) - jose: 6.1.3 + '@solana/spl-token': 0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + abitype: 1.0.6(typescript@5.9.2)(zod@3.25.76) + axios: 1.11.0 + axios-retry: 4.5.0(axios@1.11.0) + jose: 6.1.0 md5: 2.3.0 uncrypto: 0.1.3 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zod: 3.25.76 transitivePeerDependencies: - bufferutil @@ -9404,21 +9793,21 @@ snapshots: - typescript - utf-8-validate - '@coinbase/onchainkit@0.38.19(@farcaster/miniapp-sdk@0.2.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': + '@coinbase/onchainkit@0.38.19(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@farcaster/frame-sdk': 0.1.13(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@farcaster/miniapp-wagmi-connector': 1.1.0(@farcaster/miniapp-sdk@0.2.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@tanstack/react-query': 5.90.20(react@19.2.1) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@farcaster/frame-sdk': 0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@farcaster/miniapp-wagmi-connector': 1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@tanstack/react-query': 5.90.11(react@19.2.1) + '@wagmi/core': 2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) clsx: 2.1.1 - graphql: 16.12.0 - graphql-request: 6.1.0(graphql@16.12.0) + graphql: 16.11.0 + graphql-request: 6.1.0(graphql@16.11.0) qrcode: 1.5.4 react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - tailwind-merge: 2.6.1 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - wagmi: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) + tailwind-merge: 2.6.0 + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9464,23 +9853,23 @@ snapshots: clsx: 1.2.1 eth-block-tracker: 7.1.0 eth-json-rpc-filters: 6.0.1 - eventemitter3: 5.0.4 + eventemitter3: 5.0.1 keccak: 3.0.4 - preact: 10.28.3 + preact: 10.27.2 sha.js: 2.4.12 transitivePeerDependencies: - supports-color - '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': + '@coinbase/wallet-sdk@4.3.6(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76)': 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.9.3)(zod@3.25.76) + ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) preact: 10.24.2 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.3(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.3(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) transitivePeerDependencies: - '@types/react' - bufferutil @@ -9491,16 +9880,16 @@ snapshots: - utf-8-validate - zod - '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(zod@3.25.76)': + '@coinbase/wallet-sdk@4.3.6(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76)': 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.9.3)(zod@3.25.76) + ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) preact: 10.24.2 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.3(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.3(@types/react@19.1.12)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) transitivePeerDependencies: - '@types/react' - bufferutil @@ -9511,11 +9900,11 @@ snapshots: - utf-8-validate - zod - '@craftamap/esbuild-plugin-html@0.9.0(bufferutil@4.1.0)(esbuild@0.25.12)(utf-8-validate@5.0.10)': + '@craftamap/esbuild-plugin-html@0.9.0(bufferutil@4.0.9)(esbuild@0.25.9)(utf-8-validate@5.0.10)': dependencies: - esbuild: 0.25.12 - jsdom: 26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) - lodash: 4.17.23 + esbuild: 0.25.9 + jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + lodash: 4.17.21 transitivePeerDependencies: - bufferutil - canvas @@ -9530,248 +9919,173 @@ snapshots: '@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.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 - - '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-syntax-patches-for-csstree@1.0.26': {} - - '@csstools/css-tokenizer@3.0.4': {} - - '@ecies/ciphers@0.2.5(@noble/ciphers@1.3.0)': - dependencies: - '@noble/ciphers': 1.3.0 - - '@emnapi/core@1.8.1': - dependencies: - '@emnapi/wasi-threads': 1.1.0 - tslib: 2.8.1 - optional: true - - '@emnapi/runtime@1.8.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@1.1.0': - dependencies: - tslib: 2.8.1 - optional: true - - '@es-joy/jsdoccomment@0.50.2': - dependencies: - '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.54.0 - comment-parser: 1.4.1 - esquery: 1.7.0 - jsdoc-type-pratt-parser: 4.1.0 - - '@esbuild/aix-ppc64@0.25.12': - optional: true - - '@esbuild/aix-ppc64@0.27.2': - optional: true - - '@esbuild/android-arm64@0.25.12': - optional: true - - '@esbuild/android-arm64@0.27.2': - optional: true - - '@esbuild/android-arm@0.25.12': - optional: true - - '@esbuild/android-arm@0.27.2': - optional: true - - '@esbuild/android-x64@0.25.12': - optional: true - - '@esbuild/android-x64@0.27.2': - optional: true - - '@esbuild/darwin-arm64@0.25.12': - optional: true - - '@esbuild/darwin-arm64@0.27.2': - optional: true - - '@esbuild/darwin-x64@0.25.12': - optional: true - - '@esbuild/darwin-x64@0.27.2': - optional: true - - '@esbuild/freebsd-arm64@0.25.12': - optional: true - - '@esbuild/freebsd-arm64@0.27.2': - optional: true - - '@esbuild/freebsd-x64@0.25.12': - optional: true - - '@esbuild/freebsd-x64@0.27.2': - optional: true - - '@esbuild/linux-arm64@0.25.12': - optional: true + dependencies: + '@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 - '@esbuild/linux-arm64@0.27.2': - optional: true + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 - '@esbuild/linux-arm@0.25.12': - optional: true + '@csstools/css-syntax-patches-for-csstree@1.0.22': {} - '@esbuild/linux-arm@0.27.2': - optional: true + '@csstools/css-tokenizer@3.0.4': {} - '@esbuild/linux-ia32@0.25.12': - optional: true + '@ecies/ciphers@0.2.4(@noble/ciphers@1.3.0)': + dependencies: + '@noble/ciphers': 1.3.0 - '@esbuild/linux-ia32@0.27.2': + '@emnapi/core@1.5.0': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 optional: true - '@esbuild/linux-loong64@0.25.12': + '@emnapi/runtime@1.5.0': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/linux-loong64@0.27.2': + '@emnapi/runtime@1.7.1': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/linux-mips64el@0.25.12': + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/linux-mips64el@0.27.2': - optional: true + '@es-joy/jsdoccomment@0.50.2': + dependencies: + '@types/estree': 1.0.8 + '@typescript-eslint/types': 8.42.0 + comment-parser: 1.4.1 + esquery: 1.6.0 + jsdoc-type-pratt-parser: 4.1.0 - '@esbuild/linux-ppc64@0.25.12': + '@esbuild/aix-ppc64@0.25.9': optional: true - '@esbuild/linux-ppc64@0.27.2': + '@esbuild/android-arm64@0.25.9': optional: true - '@esbuild/linux-riscv64@0.25.12': + '@esbuild/android-arm@0.25.9': optional: true - '@esbuild/linux-riscv64@0.27.2': + '@esbuild/android-x64@0.25.9': optional: true - '@esbuild/linux-s390x@0.25.12': + '@esbuild/darwin-arm64@0.25.9': optional: true - '@esbuild/linux-s390x@0.27.2': + '@esbuild/darwin-x64@0.25.9': optional: true - '@esbuild/linux-x64@0.25.12': + '@esbuild/freebsd-arm64@0.25.9': optional: true - '@esbuild/linux-x64@0.27.2': + '@esbuild/freebsd-x64@0.25.9': optional: true - '@esbuild/netbsd-arm64@0.25.12': + '@esbuild/linux-arm64@0.25.9': optional: true - '@esbuild/netbsd-arm64@0.27.2': + '@esbuild/linux-arm@0.25.9': optional: true - '@esbuild/netbsd-x64@0.25.12': + '@esbuild/linux-ia32@0.25.9': optional: true - '@esbuild/netbsd-x64@0.27.2': + '@esbuild/linux-loong64@0.25.9': optional: true - '@esbuild/openbsd-arm64@0.25.12': + '@esbuild/linux-mips64el@0.25.9': optional: true - '@esbuild/openbsd-arm64@0.27.2': + '@esbuild/linux-ppc64@0.25.9': optional: true - '@esbuild/openbsd-x64@0.25.12': + '@esbuild/linux-riscv64@0.25.9': optional: true - '@esbuild/openbsd-x64@0.27.2': + '@esbuild/linux-s390x@0.25.9': optional: true - '@esbuild/openharmony-arm64@0.25.12': + '@esbuild/linux-x64@0.25.9': optional: true - '@esbuild/openharmony-arm64@0.27.2': + '@esbuild/netbsd-arm64@0.25.9': optional: true - '@esbuild/sunos-x64@0.25.12': + '@esbuild/netbsd-x64@0.25.9': optional: true - '@esbuild/sunos-x64@0.27.2': + '@esbuild/openbsd-arm64@0.25.9': optional: true - '@esbuild/win32-arm64@0.25.12': + '@esbuild/openbsd-x64@0.25.9': optional: true - '@esbuild/win32-arm64@0.27.2': + '@esbuild/openharmony-arm64@0.25.9': optional: true - '@esbuild/win32-ia32@0.25.12': + '@esbuild/sunos-x64@0.25.9': optional: true - '@esbuild/win32-ia32@0.27.2': + '@esbuild/win32-arm64@0.25.9': optional: true - '@esbuild/win32-x64@0.25.12': + '@esbuild/win32-ia32@0.25.9': optional: true - '@esbuild/win32-x64@0.27.2': + '@esbuild/win32-x64@0.25.9': optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.8.0(eslint@9.34.0(jiti@2.6.1))': dependencies: - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.34.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.2': {} + '@eslint-community/regexpp@4.12.1': {} - '@eslint/config-array@0.21.1': + '@eslint/config-array@0.21.0': dependencies: - '@eslint/object-schema': 2.1.7 - debug: 4.4.3 + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.4.2': - dependencies: - '@eslint/core': 0.17.0 + '@eslint/config-helpers@0.3.1': {} - '@eslint/core@0.17.0': + '@eslint/core@0.15.2': dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.3': + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.3 + 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.1 + js-yaml: 4.1.0 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@9.39.2': {} + '@eslint/js@9.34.0': {} - '@eslint/object-schema@2.1.7': {} + '@eslint/object-schema@2.1.6': {} - '@eslint/plugin-kit@0.4.1': + '@eslint/plugin-kit@0.3.5': dependencies: - '@eslint/core': 0.17.0 + '@eslint/core': 0.15.2 levn: 0.4.1 '@ethereumjs/common@3.2.0': @@ -9794,13 +10108,16 @@ snapshots: ethereum-cryptography: 2.2.1 micro-ftch: 0.3.1 - '@farcaster/frame-sdk@0.1.13(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@exodus/bytes@1.8.0': + optional: true + + '@farcaster/frame-sdk@0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@farcaster/miniapp-sdk': 0.2.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@farcaster/quick-auth': 0.0.8(typescript@5.9.3) + '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@farcaster/quick-auth': 0.0.6(typescript@5.9.2) comlink: 4.4.2 - eventemitter3: 5.0.4 - ox: 0.4.4(typescript@5.9.3)(zod@3.25.76) + eventemitter3: 5.0.1 + ox: 0.4.4(typescript@5.9.2)(zod@3.25.76) transitivePeerDependencies: - bufferutil - encoding @@ -9808,10 +10125,10 @@ snapshots: - utf-8-validate - zod - '@farcaster/miniapp-core@0.5.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@farcaster/miniapp-core@0.3.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: - '@solana/web3.js': 1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - ox: 0.4.4(typescript@5.9.3)(zod@3.25.76) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + ox: 0.4.4(typescript@5.9.2)(zod@3.25.76) zod: 3.25.76 transitivePeerDependencies: - bufferutil @@ -9819,13 +10136,13 @@ snapshots: - typescript - utf-8-validate - '@farcaster/miniapp-sdk@0.2.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@farcaster/miniapp-core': 0.5.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@farcaster/quick-auth': 0.0.6(typescript@5.9.3) + '@farcaster/miniapp-core': 0.3.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@farcaster/quick-auth': 0.0.6(typescript@5.9.2) comlink: 4.4.2 - eventemitter3: 5.0.4 - ox: 0.4.4(typescript@5.9.3)(zod@3.25.76) + eventemitter3: 5.0.1 + ox: 0.4.4(typescript@5.9.2)(zod@3.25.76) transitivePeerDependencies: - bufferutil - encoding @@ -9833,47 +10150,61 @@ snapshots: - utf-8-validate - zod - '@farcaster/miniapp-wagmi-connector@1.1.0(@farcaster/miniapp-sdk@0.2.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))': + '@farcaster/miniapp-wagmi-connector@1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: - '@farcaster/miniapp-sdk': 0.2.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@farcaster/quick-auth@0.0.6(typescript@5.9.3)': + '@farcaster/quick-auth@0.0.6(typescript@5.9.2)': dependencies: jose: 5.10.0 - typescript: 5.9.3 + typescript: 5.9.2 zod: 3.25.76 - '@farcaster/quick-auth@0.0.8(typescript@5.9.3)': + '@gemini-wallet/core@0.2.0(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: - jose: 5.10.0 - typescript: 5.9.3 - zod: 3.25.76 + '@metamask/rpc-errors': 7.0.2 + eventemitter3: 5.0.1 + viem: 2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + '@gemini-wallet/core@0.2.0(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': + dependencies: + '@metamask/rpc-errors': 7.0.2 + eventemitter3: 5.0.1 + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + transitivePeerDependencies: + - supports-color - '@gemini-wallet/core@0.2.0(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))': + '@gemini-wallet/core@0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: '@metamask/rpc-errors': 7.0.2 eventemitter3: 5.0.1 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - supports-color - '@gemini-wallet/core@0.3.2(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))': + '@gemini-wallet/core@0.3.2(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: '@metamask/rpc-errors': 7.0.2 eventemitter3: 5.0.1 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - supports-color - '@graphql-typed-document-node/core@3.2.0(graphql@16.12.0)': + '@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.3)': dependencies: - graphql: 16.12.0 + react: 19.2.3 - '@heroicons/react@2.2.0(react@19.2.4)': + '@hono/node-server@1.19.1(hono@4.10.7)': dependencies: - react: 19.2.4 + hono: 4.10.7 '@hono/node-server@1.19.9(hono@4.11.7)': dependencies: @@ -9975,7 +10306,7 @@ snapshots: '@img/sharp-wasm32@0.34.5': dependencies: - '@emnapi/runtime': 1.8.1 + '@emnapi/runtime': 1.7.1 optional: true '@img/sharp-win32-arm64@0.34.5': @@ -9987,48 +10318,57 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true - '@inquirer/external-editor@1.0.3(@types/node@22.19.7)': + '@inquirer/external-editor@1.0.3(@types/node@22.18.0)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 + + '@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 '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/trace-mapping': 0.3.30 '@jridgewell/remapping@2.3.5': dependencies: '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/trace-mapping': 0.3.30 '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.31': + '@jridgewell/trace-mapping@0.3.30': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@lit-labs/ssr-dom-shim@1.5.1': {} + '@lit-labs/ssr-dom-shim@1.4.0': {} - '@lit/reactive-element@2.1.2': + '@lit/reactive-element@2.1.1': dependencies: - '@lit-labs/ssr-dom-shim': 1.5.1 + '@lit-labs/ssr-dom-shim': 1.4.0 '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.28.3 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.28.3 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -10075,7 +10415,7 @@ snapshots: '@metamask/onboarding@1.0.1': dependencies: - bowser: 2.13.1 + bowser: 2.12.1 '@metamask/providers@16.1.0': dependencies: @@ -10103,7 +10443,7 @@ snapshots: '@metamask/rpc-errors@7.0.2': dependencies: - '@metamask/utils': 11.9.0 + '@metamask/utils': 11.7.0 fast-safe-stringify: 2.1.1 transitivePeerDependencies: - supports-color @@ -10116,45 +10456,91 @@ snapshots: dependencies: openapi-fetch: 0.13.8 - '@metamask/sdk-communication-layer@0.33.1(cross-fetch@4.1.0)(eciesjs@0.4.17)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@5.0.10))': + '@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))': + dependencies: + bufferutil: 4.0.9 + cross-fetch: 4.1.0 + date-fns: 2.30.0 + debug: 4.4.3 + 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 + transitivePeerDependencies: + - supports-color + + '@metamask/sdk-communication-layer@0.33.1(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))': dependencies: '@metamask/sdk-analytics': 0.0.5 - bufferutil: 4.1.0 + bufferutil: 4.0.9 cross-fetch: 4.1.0 date-fns: 2.30.0 debug: 4.3.4 - eciesjs: 0.4.17 + eciesjs: 0.4.15 eventemitter2: 6.4.9 readable-stream: 3.6.2 - socket.io-client: 4.8.3(bufferutil@4.1.0)(utf-8-validate@5.0.10) + 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.0': + dependencies: + '@paulmillr/qr': 0.2.1 + '@metamask/sdk-install-modal-web@0.32.1': dependencies: '@paulmillr/qr': 0.2.1 - '@metamask/sdk@0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10)': + '@metamask/sdk@0.32.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + dependencies: + '@babel/runtime': 7.28.3 + '@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.12.1 + 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 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + + '@metamask/sdk@0.33.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.28.3 '@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.17)(eventemitter2@6.4.9)(readable-stream@3.6.2)(socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + '@metamask/sdk-communication-layer': 0.33.1(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.1 '@paulmillr/qr': 0.2.1 - bowser: 2.13.1 + bowser: 2.12.1 cross-fetch: 4.1.0 debug: 4.3.4 - eciesjs: 0.4.17 + 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.3(bufferutil@4.1.0)(utf-8-validate@5.0.10) + 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 @@ -10166,16 +10552,16 @@ snapshots: '@metamask/superstruct@3.2.1': {} - '@metamask/utils@11.9.0': + '@metamask/utils@11.7.0': 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 - '@types/lodash': 4.17.23 + '@types/lodash': 4.17.20 debug: 4.4.3 - lodash: 4.17.23 + lodash: 4.17.21 pony-cause: 2.1.11 semver: 7.7.3 uuid: 9.0.1 @@ -10199,7 +10585,7 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.12 - debug: 4.3.4 + debug: 4.4.3 pony-cause: 2.1.11 semver: 7.7.3 uuid: 9.0.1 @@ -10213,14 +10599,14 @@ snapshots: '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 '@types/debug': 4.1.12 - debug: 4.4.1 + debug: 4.4.3 pony-cause: 2.1.11 semver: 7.7.3 uuid: 9.0.1 transitivePeerDependencies: - supports-color - '@modelcontextprotocol/sdk@1.25.3(hono@4.11.7)(zod@3.25.76)': + '@modelcontextprotocol/sdk@1.26.0(zod@3.25.76)': dependencies: '@hono/node-server': 1.19.9(hono@4.11.7) ajv: 8.17.1 @@ -10231,7 +10617,8 @@ snapshots: eventsource: 3.0.7 eventsource-parser: 3.0.6 express: 5.2.1 - express-rate-limit: 7.5.1(express@5.2.1) + express-rate-limit: 8.2.1(express@5.2.1) + hono: 4.11.7 jose: 6.1.3 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -10239,44 +10626,43 @@ snapshots: zod: 3.25.76 zod-to-json-schema: 3.25.1(zod@3.25.76) transitivePeerDependencies: - - hono - supports-color '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@emnapi/core': 1.8.1 - '@emnapi/runtime': 1.8.1 - '@tybys/wasm-util': 0.10.1 + '@emnapi/core': 1.5.0 + '@emnapi/runtime': 1.5.0 + '@tybys/wasm-util': 0.10.0 optional: true - '@next/env@16.1.6': {} + '@next/env@16.0.10': {} '@next/eslint-plugin-next@16.0.6': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@16.1.6': + '@next/swc-darwin-arm64@16.0.10': optional: true - '@next/swc-darwin-x64@16.1.6': + '@next/swc-darwin-x64@16.0.10': optional: true - '@next/swc-linux-arm64-gnu@16.1.6': + '@next/swc-linux-arm64-gnu@16.0.10': optional: true - '@next/swc-linux-arm64-musl@16.1.6': + '@next/swc-linux-arm64-musl@16.0.10': optional: true - '@next/swc-linux-x64-gnu@16.1.6': + '@next/swc-linux-x64-gnu@16.0.10': optional: true - '@next/swc-linux-x64-musl@16.1.6': + '@next/swc-linux-x64-musl@16.0.10': optional: true - '@next/swc-win32-arm64-msvc@16.1.6': + '@next/swc-win32-arm64-msvc@16.0.10': optional: true - '@next/swc-win32-x64-msvc@16.1.6': + '@next/swc-win32-x64-msvc@16.0.10': optional: true '@noble/ciphers@1.2.1': {} @@ -10327,43 +10713,46 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 + 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.9': {} - '@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4)': + '@reown/appkit-common@1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.22.4)': dependencies: big.js: 6.2.2 dayjs: 1.11.13 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.22.4) transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - zod - '@reown/appkit-common@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-common@1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: big.js: 6.2.2 dayjs: 1.11.13 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - bufferutil - typescript - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-controllers@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.1) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.1) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10392,13 +10781,13 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-controllers@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.4) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.3) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10427,14 +10816,14 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-pay@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1))(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.1))(zod@3.25.76) lit: 3.3.0 - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.1) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.1) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10463,14 +10852,14 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-pay@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4))(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3))(zod@3.25.76) lit: 3.3.0 - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.4) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.3) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10503,13 +10892,13 @@ snapshots: dependencies: buffer: 6.0.3 - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1))(zod@3.25.76)': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.1))(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1))(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.1))(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -10540,13 +10929,13 @@ snapshots: - valtio - zod - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4))(zod@3.25.76)': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3))(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4))(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3))(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -10577,11 +10966,11 @@ snapshots: - valtio - zod - '@reown/appkit-ui@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-ui@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 qrcode: 1.5.3 transitivePeerDependencies: @@ -10612,11 +11001,11 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-ui@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-ui@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 qrcode: 1.5.3 transitivePeerDependencies: @@ -10647,16 +11036,16 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1))(zod@3.25.76)': + '@reown/appkit-utils@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.1))(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.1) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.1) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10685,16 +11074,16 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4))(zod@3.25.76)': + '@reown/appkit-utils@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3))(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.4) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.3) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10723,9 +11112,9 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-wallet@1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@reown/appkit-wallet@1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(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 @@ -10734,21 +11123,21 @@ snapshots: - typescript - utf-8-validate - '@reown/appkit@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-pay': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-pay': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1))(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1))(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.1))(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.1))(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@vercel/functions@2.2.13) - '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) bs58: 6.0.0 - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.1) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.1) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10777,21 +11166,21 @@ snapshots: - utf-8-validate - zod - '@reown/appkit@1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit@1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-pay': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-pay': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4))(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4))(zod@3.25.76) - '@reown/appkit-wallet': 1.7.8(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3))(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3))(zod@3.25.76) + '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@vercel/functions@2.2.13) - '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) bs58: 6.0.0 - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.4) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.3) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10820,86 +11209,74 @@ snapshots: - utf-8-validate - zod - '@rollup/rollup-android-arm-eabi@4.57.1': - optional: true - - '@rollup/rollup-android-arm64@4.57.1': - optional: true - - '@rollup/rollup-darwin-arm64@4.57.1': - optional: true - - '@rollup/rollup-darwin-x64@4.57.1': + '@rollup/rollup-android-arm-eabi@4.50.0': optional: true - '@rollup/rollup-freebsd-arm64@4.57.1': + '@rollup/rollup-android-arm64@4.50.0': optional: true - '@rollup/rollup-freebsd-x64@4.57.1': + '@rollup/rollup-darwin-arm64@4.50.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + '@rollup/rollup-darwin-x64@4.50.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.57.1': + '@rollup/rollup-freebsd-arm64@4.50.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.57.1': + '@rollup/rollup-freebsd-x64@4.50.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.57.1': + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.57.1': + '@rollup/rollup-linux-arm-musleabihf@4.50.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.57.1': + '@rollup/rollup-linux-arm64-gnu@4.50.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.57.1': + '@rollup/rollup-linux-arm64-musl@4.50.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.57.1': + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.57.1': + '@rollup/rollup-linux-ppc64-gnu@4.50.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.57.1': + '@rollup/rollup-linux-riscv64-gnu@4.50.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.57.1': + '@rollup/rollup-linux-riscv64-musl@4.50.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.57.1': + '@rollup/rollup-linux-s390x-gnu@4.50.0': optional: true - '@rollup/rollup-linux-x64-musl@4.57.1': + '@rollup/rollup-linux-x64-gnu@4.50.0': optional: true - '@rollup/rollup-openbsd-x64@4.57.1': + '@rollup/rollup-linux-x64-musl@4.50.0': optional: true - '@rollup/rollup-openharmony-arm64@4.57.1': + '@rollup/rollup-openharmony-arm64@4.50.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.57.1': + '@rollup/rollup-win32-arm64-msvc@4.50.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.57.1': + '@rollup/rollup-win32-ia32-msvc@4.50.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.57.1': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.57.1': + '@rollup/rollup-win32-x64-msvc@4.50.0': optional: true '@rtsao/scc@1.1.0': {} - '@safe-global/safe-apps-provider@0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@safe-global/safe-apps-provider@0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: - bufferutil @@ -10907,10 +11284,10 @@ snapshots: - utf-8-validate - zod - '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@safe-global/safe-apps-sdk@9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@safe-global/safe-gateway-typescript-sdk': 3.23.1 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - bufferutil - typescript @@ -10960,1180 +11337,1680 @@ snapshots: '@socket.io/component-emitter@3.1.2': {} - '@solana-program/compute-budget@0.11.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@solana-program/compute-budget@0.11.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: - '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/compute-budget@0.8.0(@solana/kit@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@solana-program/compute-budget@0.11.0(@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: - '@solana/kit': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@solana/kit': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/system@0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@solana-program/compute-budget@0.8.0(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10))': dependencies: - '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@solana-program/token-2022@0.4.2(@solana/kit@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': + '@solana-program/token-2022@0.4.2(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2))': dependencies: - '@solana/kit': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana-program/token-2022@0.6.1(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': + '@solana-program/token-2022@0.6.1(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2))': dependencies: - '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana-program/token@0.5.1(@solana/kit@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@solana-program/token-2022@0.6.1(@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2))': dependencies: - '@solana/kit': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@solana/kit': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) - '@solana-program/token@0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10))': + '@solana-program/token@0.5.1(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10))': dependencies: - '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) + '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@solana/accounts@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana-program/token@0.9.0(@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec': 5.5.1(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/kit': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana-program/token@0.9.0(@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + dependencies: + '@solana/kit': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + + '@solana/accounts@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec': 5.0.0(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/accounts@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec': 5.1.0(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/accounts@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/accounts@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/addresses@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/addresses@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/assertions': 2.3.0(typescript@5.9.3) - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/nominal-types': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/assertions': 2.3.0(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/nominal-types': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/addresses@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/addresses@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/assertions': 5.5.1(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/assertions': 5.0.0(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/nominal-types': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/addresses@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/assertions': 5.1.0(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/addresses@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/addresses@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/assertions': 6.1.0(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) + '@solana/assertions': 6.1.0(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/assertions@2.3.0(typescript@5.9.3)': + '@solana/assertions@2.3.0(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/assertions@5.5.1(typescript@5.9.3)': + '@solana/assertions@5.0.0(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/assertions@5.1.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/assertions@6.1.0(typescript@5.9.3)': + '@solana/assertions@6.1.0(typescript@5.9.2)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/buffer-layout-utils@0.2.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@solana/buffer-layout': 4.0.1 + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + bigint-buffer: 1.1.5 + bignumber.js: 9.3.1 + transitivePeerDependencies: + - bufferutil + - encoding + - typescript + - utf-8-validate '@solana/buffer-layout@4.0.1': dependencies: buffer: 6.0.3 - '@solana/codecs-core@2.3.0(typescript@5.9.3)': + '@solana/codecs-core@2.0.0-rc.1(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 - '@solana/codecs-core@5.5.1(typescript@5.9.3)': + '@solana/codecs-core@2.3.0(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/codecs-core@6.1.0(typescript@5.9.3)': + '@solana/codecs-core@5.0.0(typescript@5.9.2)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/codecs-data-structures@2.3.0(typescript@5.9.3)': + '@solana/codecs-core@5.1.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/codecs-data-structures@5.5.1(typescript@5.9.3)': + '@solana/codecs-core@6.1.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/codecs-data-structures@6.1.0(typescript@5.9.3)': + '@solana/codecs-data-structures@2.0.0-rc.1(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-data-structures@2.3.0(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/codecs-numbers@2.3.0(typescript@5.9.3)': + '@solana/codecs-data-structures@5.0.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.0.0(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/codecs-numbers@5.5.1(typescript@5.9.3)': + '@solana/codecs-data-structures@5.1.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-data-structures@6.1.0(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/codecs-numbers@2.0.0-rc.1(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-numbers@2.3.0(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-numbers@5.0.0(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/codecs-numbers@6.1.0(typescript@5.9.3)': + '@solana/codecs-numbers@5.1.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/codecs-numbers@6.1.0(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/codecs-strings@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs-strings@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) fastestsmallesttextencoderdecoder: 1.0.22 - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/codecs-strings@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs-strings@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - optionalDependencies: + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + fastestsmallesttextencoderdecoder: 1.0.22 + typescript: 5.9.2 + + '@solana/codecs-strings@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.0.0(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) fastestsmallesttextencoderdecoder: 1.0.22 - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/codecs-strings@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs-strings@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 optionalDependencies: fastestsmallesttextencoderdecoder: 1.0.22 - typescript: 5.9.3 - '@solana/codecs@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs-strings@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/options': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + fastestsmallesttextencoderdecoder: 1.0.22 + typescript: 5.9.2 + + '@solana/codecs@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/options': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/codecs@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.0.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/options': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/codecs@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/options': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/codecs@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/codecs@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-data-structures': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/options': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/options': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/errors@2.3.0(typescript@5.9.3)': + '@solana/errors@2.0.0-rc.1(typescript@5.9.2)': dependencies: chalk: 5.6.2 - commander: 14.0.3 - typescript: 5.9.3 + commander: 12.1.0 + typescript: 5.9.2 - '@solana/errors@5.5.1(typescript@5.9.3)': + '@solana/errors@2.3.0(typescript@5.9.2)': dependencies: chalk: 5.6.2 commander: 14.0.2 - optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/errors@5.0.0(typescript@5.9.2)': + dependencies: + chalk: 5.6.2 + commander: 14.0.1 + typescript: 5.9.2 + + '@solana/errors@5.1.0(typescript@5.9.2)': + dependencies: + chalk: 5.6.2 + commander: 14.0.2 + typescript: 5.9.2 - '@solana/errors@6.1.0(typescript@5.9.3)': + '@solana/errors@6.1.0(typescript@5.9.2)': dependencies: chalk: 5.6.2 commander: 14.0.3 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/fast-stable-stringify@2.3.0(typescript@5.9.3)': + '@solana/fast-stable-stringify@2.3.0(typescript@5.9.2)': dependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/fast-stable-stringify@5.5.1(typescript@5.9.3)': - optionalDependencies: - typescript: 5.9.3 + '@solana/fast-stable-stringify@5.0.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@solana/fast-stable-stringify@5.1.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 - '@solana/fast-stable-stringify@6.1.0(typescript@5.9.3)': + '@solana/fast-stable-stringify@6.1.0(typescript@5.9.2)': optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/functional@2.3.0(typescript@5.9.3)': + '@solana/functional@2.3.0(typescript@5.9.2)': dependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/functional@5.5.1(typescript@5.9.3)': - optionalDependencies: - typescript: 5.9.3 + '@solana/functional@5.0.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@solana/functional@5.1.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 - '@solana/functional@6.1.0(typescript@5.9.3)': + '@solana/functional@6.1.0(typescript@5.9.2)': optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/instruction-plans@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/instruction-plans@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/instructions': 5.5.1(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/promises': 5.5.1(typescript@5.9.3) - '@solana/transaction-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/instructions': 5.0.0(typescript@5.9.2) + '@solana/promises': 5.0.0(typescript@5.9.2) + '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/instruction-plans@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/instructions': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 5.1.0(typescript@5.9.2) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/instruction-plans@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/instruction-plans@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/instructions': 6.1.0(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/promises': 6.1.0(typescript@5.9.3) - '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/instructions': 6.1.0(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 6.1.0(typescript@5.9.2) + '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/instructions@2.3.0(typescript@5.9.3)': + '@solana/instructions@2.3.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/instructions@5.5.1(typescript@5.9.3)': + '@solana/instructions@5.0.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/instructions@5.1.0(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/instructions@6.1.0(typescript@5.9.3)': + '@solana/instructions@6.1.0(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/keys@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/keys@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/assertions': 2.3.0(typescript@5.9.3) - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/nominal-types': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/assertions': 2.3.0(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/nominal-types': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/keys@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/keys@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/assertions': 5.5.1(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/assertions': 5.0.0(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/nominal-types': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/keys@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/keys@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/assertions': 6.1.0(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/assertions': 5.1.0(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@solana/accounts': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/functional': 5.5.1(typescript@5.9.3) - '@solana/instruction-plans': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/instructions': 5.5.1(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/offchain-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/plugin-core': 5.5.1(typescript@5.9.3) - '@solana/programs': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-api': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-parsed-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-subscriptions': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/signers': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/sysvars': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-confirmation': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/transaction-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/keys@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/assertions': 6.1.0(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - - bufferutil - fastestsmallesttextencoderdecoder - - utf-8-validate - '@solana/kit@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@solana/accounts': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/functional': 6.1.0(typescript@5.9.3) - '@solana/instruction-plans': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/instructions': 6.1.0(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/offchain-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/plugin-core': 6.1.0(typescript@5.9.3) - '@solana/plugin-interfaces': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/program-client-core': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/programs': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-parsed-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-subscriptions': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/signers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-confirmation': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/kit@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/functional': 5.0.0(typescript@5.9.2) + '@solana/instruction-plans': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/instructions': 5.0.0(typescript@5.9.2) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/programs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/signers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/sysvars': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-confirmation': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/instruction-plans': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/instructions': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/offchain-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/programs': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/signers': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/sysvars': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-confirmation': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/kit@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/instruction-plans': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/instructions': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/offchain-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/programs': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/signers': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/sysvars': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-confirmation': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@solana/accounts': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/functional': 6.1.0(typescript@5.9.2) + '@solana/instruction-plans': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/instructions': 6.1.0(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/offchain-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/plugin-core': 6.1.0(typescript@5.9.2) + '@solana/plugin-interfaces': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/program-client-core': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/programs': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/signers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-confirmation': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - bufferutil - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/nominal-types@2.3.0(typescript@5.9.3)': + '@solana/nominal-types@2.3.0(typescript@5.9.2)': dependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/nominal-types@5.5.1(typescript@5.9.3)': - optionalDependencies: - typescript: 5.9.3 + '@solana/nominal-types@5.0.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 - '@solana/nominal-types@6.1.0(typescript@5.9.3)': - optionalDependencies: - typescript: 5.9.3 - - '@solana/offchain-messages@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) + '@solana/nominal-types@5.1.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@solana/nominal-types@6.1.0(typescript@5.9.2)': optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/offchain-messages@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/offchain-messages@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/offchain-messages@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-data-structures': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/options@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/options@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/codecs-core': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.9.2) + '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.0.0-rc.1(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/options@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/options@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-data-structures': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.0.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/options@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/plugin-core@5.5.1(typescript@5.9.3)': + '@solana/options@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder - '@solana/plugin-core@6.1.0(typescript@5.9.3)': + '@solana/plugin-core@6.1.0(typescript@5.9.2)': optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/plugin-interfaces@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/plugin-interfaces@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/instruction-plans': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/signers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/instruction-plans': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/signers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/program-client-core@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/accounts': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/instruction-plans': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/instructions': 6.1.0(typescript@5.9.3) - '@solana/plugin-interfaces': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/signers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/program-client-core@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/accounts': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/instruction-plans': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/instructions': 6.1.0(typescript@5.9.2) + '@solana/plugin-interfaces': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/signers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/programs@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/programs@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/programs@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/programs@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/programs@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/promises@2.3.0(typescript@5.9.3)': + '@solana/promises@2.3.0(typescript@5.9.2)': dependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/promises@5.5.1(typescript@5.9.3)': - optionalDependencies: - typescript: 5.9.3 + '@solana/promises@5.0.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@solana/promises@5.1.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 - '@solana/promises@6.1.0(typescript@5.9.3)': + '@solana/promises@6.1.0(typescript@5.9.2)': optionalDependencies: - typescript: 5.9.3 - - '@solana/rpc-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-parsed-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec': 2.3.0(typescript@5.9.3) - '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/rpc-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec': 2.3.0(typescript@5.9.2) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-api@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-parsed-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec': 5.5.1(typescript@5.9.3) - '@solana/rpc-transformers': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/rpc-api@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec': 5.0.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-api@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-parsed-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/rpc-api@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec': 5.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-api@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-parsed-types@2.3.0(typescript@5.9.3)': + '@solana/rpc-parsed-types@2.3.0(typescript@5.9.2)': dependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/rpc-parsed-types@5.5.1(typescript@5.9.3)': - optionalDependencies: - typescript: 5.9.3 + '@solana/rpc-parsed-types@5.0.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@solana/rpc-parsed-types@5.1.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 - '@solana/rpc-parsed-types@6.1.0(typescript@5.9.3)': + '@solana/rpc-parsed-types@6.1.0(typescript@5.9.2)': optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/rpc-spec-types@2.3.0(typescript@5.9.3)': + '@solana/rpc-spec-types@2.3.0(typescript@5.9.2)': dependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/rpc-spec-types@5.5.1(typescript@5.9.3)': - optionalDependencies: - typescript: 5.9.3 + '@solana/rpc-spec-types@5.0.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@solana/rpc-spec-types@5.1.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 - '@solana/rpc-spec-types@6.1.0(typescript@5.9.3)': + '@solana/rpc-spec-types@6.1.0(typescript@5.9.2)': optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/rpc-spec@2.3.0(typescript@5.9.3)': + '@solana/rpc-spec@2.3.0(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/rpc-spec@5.5.1(typescript@5.9.3)': + '@solana/rpc-spec@5.0.0(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/rpc-spec@6.1.0(typescript@5.9.3)': + '@solana/rpc-spec@5.1.0(typescript@5.9.2)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec-types': 6.1.0(typescript@5.9.3) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/rpc-spec@6.1.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/rpc-subscriptions-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.2) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-subscriptions-api@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.3) - '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - typescript: 5.9.3 + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 5.0.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-api@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-subscriptions-api@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-spec': 5.5.1(typescript@5.9.3) - '@solana/rpc-transformers': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 5.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-api@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-subscriptions-api@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.2) + '@solana/subscribable': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@solana/rpc-subscriptions-channel-websocket@5.0.0(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/functional': 2.3.0(typescript@5.9.3) - '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.3) - '@solana/subscribable': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/functional': 5.0.0(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 5.0.0(typescript@5.9.2) + '@solana/subscribable': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-channel-websocket@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@solana/rpc-subscriptions-channel-websocket@5.1.0(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/functional': 5.5.1(typescript@5.9.3) - '@solana/rpc-subscriptions-spec': 5.5.1(typescript@5.9.3) - '@solana/subscribable': 5.5.1(typescript@5.9.3) - ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 5.1.0(typescript@5.9.2) + '@solana/subscribable': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate + ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) + + '@solana/rpc-subscriptions-channel-websocket@5.1.0(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 5.1.0(typescript@5.9.2) + '@solana/subscribable': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 + optionalDependencies: + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-channel-websocket@6.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@solana/rpc-subscriptions-channel-websocket@6.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/functional': 6.1.0(typescript@5.9.3) - '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.3) - '@solana/subscribable': 6.1.0(typescript@5.9.3) - ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/functional': 6.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.2) + '@solana/subscribable': 6.1.0(typescript@5.9.2) + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - bufferutil - utf-8-validate - '@solana/rpc-subscriptions-spec@2.3.0(typescript@5.9.3)': + '@solana/rpc-subscriptions-spec@2.3.0(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/promises': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) - '@solana/subscribable': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/promises': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + '@solana/subscribable': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/rpc-subscriptions-spec@5.5.1(typescript@5.9.3)': + '@solana/rpc-subscriptions-spec@5.0.0(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/promises': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - '@solana/subscribable': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/promises': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.0.0(typescript@5.9.2) + '@solana/subscribable': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/rpc-subscriptions-spec@5.1.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/promises': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + '@solana/subscribable': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/rpc-subscriptions-spec@6.1.0(typescript@5.9.3)': + '@solana/rpc-subscriptions-spec@6.1.0(typescript@5.9.2)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/promises': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec-types': 6.1.0(typescript@5.9.3) - '@solana/subscribable': 6.1.0(typescript@5.9.3) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/promises': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 6.1.0(typescript@5.9.2) + '@solana/subscribable': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 - - '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': - dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/fast-stable-stringify': 2.3.0(typescript@5.9.3) - '@solana/functional': 2.3.0(typescript@5.9.3) - '@solana/promises': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) - '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.3) - '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/subscribable': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/promises': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.2) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/subscribable': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - ws - '@solana/rpc-subscriptions@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/fast-stable-stringify': 5.5.1(typescript@5.9.3) - '@solana/functional': 5.5.1(typescript@5.9.3) - '@solana/promises': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-subscriptions-api': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-channel-websocket': 5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-spec': 5.5.1(typescript@5.9.3) - '@solana/rpc-transformers': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/subscribable': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/rpc-subscriptions@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 5.0.0(typescript@5.9.2) + '@solana/functional': 5.0.0(typescript@5.9.2) + '@solana/promises': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-subscriptions-api': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-channel-websocket': 5.0.0(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 5.0.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/subscribable': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - - bufferutil - fastestsmallesttextencoderdecoder - - utf-8-validate + - ws + + '@solana/rpc-subscriptions@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/promises': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions-api': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-channel-websocket': 5.1.0(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 5.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/subscribable': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws - '@solana/rpc-subscriptions@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/fast-stable-stringify': 6.1.0(typescript@5.9.3) - '@solana/functional': 6.1.0(typescript@5.9.3) - '@solana/promises': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-subscriptions-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-channel-websocket': 6.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/subscribable': 6.1.0(typescript@5.9.3) + '@solana/rpc-subscriptions@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/promises': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions-api': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-channel-websocket': 5.1.0(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 5.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/subscribable': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/rpc-subscriptions@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 6.1.0(typescript@5.9.2) + '@solana/functional': 6.1.0(typescript@5.9.2) + '@solana/promises': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-subscriptions-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-channel-websocket': 6.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/rpc-subscriptions-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/subscribable': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - bufferutil - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/rpc-transformers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-transformers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/functional': 2.3.0(typescript@5.9.3) - '@solana/nominal-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - typescript: 5.9.3 + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/nominal-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-transformers@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-transformers@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/functional': 5.5.1(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/functional': 5.0.0(typescript@5.9.2) + '@solana/nominal-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc-transformers@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-transformers@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-transformers@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/functional': 6.1.0(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/functional': 6.1.0(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-transport-http@2.3.0(typescript@5.9.3)': + '@solana/rpc-transport-http@2.3.0(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 - undici-types: 7.20.0 + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + undici-types: 7.16.0 - '@solana/rpc-transport-http@5.5.1(typescript@5.9.3)': + '@solana/rpc-transport-http@5.0.0(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - undici-types: 7.20.0 - optionalDependencies: - typescript: 5.9.3 + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + undici-types: 7.16.0 + + '@solana/rpc-transport-http@5.1.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 + undici-types: 7.16.0 - '@solana/rpc-transport-http@6.1.0(typescript@5.9.3)': + '@solana/rpc-transport-http@6.1.0(typescript@5.9.2)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec-types': 6.1.0(typescript@5.9.3) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 6.1.0(typescript@5.9.2) undici-types: 7.22.0 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 - '@solana/rpc-types@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-types@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/nominal-types': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/nominal-types': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-types@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-types@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/nominal-types': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-types@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-types@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/rpc-types@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/fast-stable-stringify': 2.3.0(typescript@5.9.3) - '@solana/functional': 2.3.0(typescript@5.9.3) - '@solana/rpc-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-spec': 2.3.0(typescript@5.9.3) - '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-transport-http': 2.3.0(typescript@5.9.3) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - typescript: 5.9.3 + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) + optionalDependencies: + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/fast-stable-stringify': 5.5.1(typescript@5.9.3) - '@solana/functional': 5.5.1(typescript@5.9.3) - '@solana/rpc-api': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-spec': 5.5.1(typescript@5.9.3) - '@solana/rpc-spec-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-transformers': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-transport-http': 5.5.1(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/rpc@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/rpc-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-spec': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-transport-http': 2.3.0(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/fast-stable-stringify': 6.1.0(typescript@5.9.3) - '@solana/functional': 6.1.0(typescript@5.9.3) - '@solana/rpc-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-spec': 6.1.0(typescript@5.9.3) - '@solana/rpc-spec-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-transport-http': 6.1.0(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/rpc@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 5.0.0(typescript@5.9.2) + '@solana/functional': 5.0.0(typescript@5.9.2) + '@solana/rpc-api': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-spec': 5.0.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-transport-http': 5.0.0(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/rpc@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/rpc-api': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-spec': 5.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-transport-http': 5.1.0(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/signers@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/instructions': 5.5.1(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) - '@solana/offchain-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/rpc@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 6.1.0(typescript@5.9.2) + '@solana/functional': 6.1.0(typescript@5.9.2) + '@solana/rpc-api': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-spec': 6.1.0(typescript@5.9.2) + '@solana/rpc-spec-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-transformers': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-transport-http': 6.1.0(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/signers@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/instructions': 5.0.0(typescript@5.9.2) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 5.0.0(typescript@5.9.2) + '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/signers@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/instructions': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + '@solana/offchain-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/signers@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/instructions': 6.1.0(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) - '@solana/offchain-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/signers@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/instructions': 6.1.0(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) + '@solana/offchain-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/subscribable@2.3.0(typescript@5.9.3)': + '@solana/spl-token-group@0.0.7(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 2.3.0(typescript@5.9.3) - typescript: 5.9.3 + '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - typescript - '@solana/subscribable@5.5.1(typescript@5.9.3)': + '@solana/spl-token-metadata@0.1.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/errors': 5.5.1(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - typescript - '@solana/subscribable@6.1.0(typescript@5.9.3)': + '@solana/spl-token@0.4.14(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: - '@solana/errors': 6.1.0(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/buffer-layout': 4.0.1 + '@solana/buffer-layout-utils': 0.2.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/spl-token-group': 0.0.7(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) + buffer: 6.0.3 + transitivePeerDependencies: + - bufferutil + - encoding + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + + '@solana/subscribable@2.3.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/subscribable@5.0.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.0.0(typescript@5.9.2) + typescript: 5.9.2 + + '@solana/subscribable@5.1.0(typescript@5.9.2)': + dependencies: + '@solana/errors': 5.1.0(typescript@5.9.2) + typescript: 5.9.2 - '@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/subscribable@6.1.0(typescript@5.9.2)': dependencies: - '@solana/accounts': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/errors': 6.1.0(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 + + '@solana/sysvars@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/accounts': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': + '@solana/sysvars@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/accounts': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/accounts': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))': + '@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: - '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/promises': 2.3.0(typescript@5.9.3) - '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - typescript: 5.9.3 + '@solana/accounts': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(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.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 2.3.0(typescript@5.9.2) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(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.9.2) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/promises': 5.5.1(typescript@5.9.3) - '@solana/rpc': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/transaction-confirmation@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 5.0.0(typescript@5.9.2) + '@solana/rpc': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - - bufferutil - fastestsmallesttextencoderdecoder - - utf-8-validate + - ws + + '@solana/transaction-confirmation@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 5.1.0(typescript@5.9.2) + '@solana/rpc': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + + '@solana/transaction-confirmation@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 5.1.0(typescript@5.9.2) + '@solana/rpc': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws - '@solana/transaction-confirmation@6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10)': - dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/promises': 6.1.0(typescript@5.9.3) - '@solana/rpc': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions': 6.1.0(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@5.0.10) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/transaction-confirmation@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)': + dependencies: + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 6.1.0(typescript@5.9.2) + '@solana/rpc': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - bufferutil - fastestsmallesttextencoderdecoder - utf-8-validate - '@solana/transaction-messages@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-data-structures': 2.3.0(typescript@5.9.3) - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/functional': 2.3.0(typescript@5.9.3) - '@solana/instructions': 2.3.0(typescript@5.9.3) - '@solana/nominal-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - typescript: 5.9.3 + '@solana/transaction-messages@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-data-structures': 2.3.0(typescript@5.9.2) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/instructions': 2.3.0(typescript@5.9.2) + '@solana/nominal-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-messages@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/functional': 5.5.1(typescript@5.9.3) - '@solana/instructions': 5.5.1(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/transaction-messages@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.0.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.0.0(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/functional': 5.0.0(typescript@5.9.2) + '@solana/instructions': 5.0.0(typescript@5.9.2) + '@solana/nominal-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/transaction-messages@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/instructions': 5.1.0(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-messages@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-data-structures': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/functional': 6.1.0(typescript@5.9.3) - '@solana/instructions': 6.1.0(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/transaction-messages@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/functional': 6.1.0(typescript@5.9.2) + '@solana/instructions': 6.1.0(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transactions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 2.3.0(typescript@5.9.3) - '@solana/codecs-data-structures': 2.3.0(typescript@5.9.3) - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) - '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 2.3.0(typescript@5.9.3) - '@solana/functional': 2.3.0(typescript@5.9.3) - '@solana/instructions': 2.3.0(typescript@5.9.3) - '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/nominal-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - typescript: 5.9.3 + '@solana/transactions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-data-structures': 2.3.0(typescript@5.9.2) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/instructions': 2.3.0(typescript@5.9.2) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transactions@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 5.5.1(typescript@5.9.3) - '@solana/codecs-data-structures': 5.5.1(typescript@5.9.3) - '@solana/codecs-numbers': 5.5.1(typescript@5.9.3) - '@solana/codecs-strings': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 5.5.1(typescript@5.9.3) - '@solana/functional': 5.5.1(typescript@5.9.3) - '@solana/instructions': 5.5.1(typescript@5.9.3) - '@solana/keys': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/nominal-types': 5.5.1(typescript@5.9.3) - '@solana/rpc-types': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - optionalDependencies: - typescript: 5.9.3 + '@solana/transactions@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.0.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.0.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.0.0(typescript@5.9.2) + '@solana/codecs-strings': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.0.0(typescript@5.9.2) + '@solana/functional': 5.0.0(typescript@5.9.2) + '@solana/instructions': 5.0.0(typescript@5.9.2) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 5.0.0(typescript@5.9.2) + '@solana/rpc-types': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + + '@solana/transactions@5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 5.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 5.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 5.1.0(typescript@5.9.2) + '@solana/codecs-strings': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 5.1.0(typescript@5.9.2) + '@solana/functional': 5.1.0(typescript@5.9.2) + '@solana/instructions': 5.1.0(typescript@5.9.2) + '@solana/keys': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 5.1.0(typescript@5.9.2) + '@solana/rpc-types': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transactions@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': - dependencies: - '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/codecs-core': 6.1.0(typescript@5.9.3) - '@solana/codecs-data-structures': 6.1.0(typescript@5.9.3) - '@solana/codecs-numbers': 6.1.0(typescript@5.9.3) - '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/errors': 6.1.0(typescript@5.9.3) - '@solana/functional': 6.1.0(typescript@5.9.3) - '@solana/instructions': 6.1.0(typescript@5.9.3) - '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/nominal-types': 6.1.0(typescript@5.9.3) - '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/transactions@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 6.1.0(typescript@5.9.2) + '@solana/codecs-data-structures': 6.1.0(typescript@5.9.2) + '@solana/codecs-numbers': 6.1.0(typescript@5.9.2) + '@solana/codecs-strings': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 6.1.0(typescript@5.9.2) + '@solana/functional': 6.1.0(typescript@5.9.2) + '@solana/instructions': 6.1.0(typescript@5.9.2) + '@solana/keys': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 6.1.0(typescript@5.9.2) + '@solana/rpc-types': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -12142,22 +13019,22 @@ snapshots: '@wallet-standard/base': 1.1.0 '@wallet-standard/features': 1.1.0 - '@solana/web3.js@1.98.4(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)': + '@solana/web3.js@1.98.4(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)': dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.28.3 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@solana/buffer-layout': 4.0.1 - '@solana/codecs-numbers': 2.3.0(typescript@5.9.3) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) agentkeepalive: 4.6.0 bn.js: 5.2.2 borsh: 0.7.0 bs58: 4.0.1 buffer: 6.0.3 fast-stable-stringify: 1.0.0 - jayson: 4.3.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + jayson: 4.2.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) node-fetch: 2.7.0 - rpc-websockets: 9.3.3 + rpc-websockets: 9.1.3 superstruct: 2.0.2 transitivePeerDependencies: - bufferutil @@ -12185,56 +13062,81 @@ snapshots: '@stablelib/wipe@1.0.1': {} - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.0)': + '@stellar/js-xdr@3.1.2': {} + + '@stellar/stellar-base@14.0.4': + dependencies: + '@noble/curves': 1.9.7 + '@stellar/js-xdr': 3.1.2 + base32.js: 0.1.0 + bignumber.js: 9.3.1 + buffer: 6.0.3 + sha.js: 2.4.12 + + '@stellar/stellar-sdk@14.5.0': + dependencies: + '@stellar/stellar-base': 14.0.4 + axios: 1.13.4 + bignumber.js: 9.3.1 + commander: 14.0.2 + eventsource: 2.0.2 + feaxios: 0.0.23 + randombytes: 2.1.0 + toml: 3.0.0 + urijs: 1.19.11 + transitivePeerDependencies: + - debug + + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.29.0)': + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.29.0)': + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.29.0)': + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.29.0)': + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.29.0)': + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.29.0)': + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.29.0)': + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - '@svgr/babel-preset@8.1.0(@babel/core@7.29.0)': + '@svgr/babel-preset@8.1.0(@babel/core@7.28.3)': dependencies: - '@babel/core': 7.29.0 - '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.29.0) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.29.0) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.29.0) - '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.29.0) - '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.29.0) - '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.29.0) - '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.29.0) - '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.29.0) + '@babel/core': 7.28.3 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.28.3) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.28.3) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.28.3) - '@svgr/core@8.1.0(typescript@5.9.3)': + '@svgr/core@8.1.0(typescript@5.9.2)': dependencies: - '@babel/core': 7.29.0 - '@svgr/babel-preset': 8.1.0(@babel/core@7.29.0) + '@babel/core': 7.28.3 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.3) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.9.3) + cosmiconfig: 8.3.6(typescript@5.9.2) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -12242,38 +13144,38 @@ snapshots: '@svgr/hast-util-to-babel-ast@8.0.0': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.28.2 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.2))': dependencies: - '@babel/core': 7.29.0 - '@svgr/babel-preset': 8.1.0(@babel/core@7.29.0) - '@svgr/core': 8.1.0(typescript@5.9.3) + '@babel/core': 7.28.3 + '@svgr/babel-preset': 8.1.0(@babel/core@7.28.3) + '@svgr/core': 8.1.0(typescript@5.9.2) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: - supports-color - '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))(typescript@5.9.3)': + '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.9.2))(typescript@5.9.2)': dependencies: - '@svgr/core': 8.1.0(typescript@5.9.3) - cosmiconfig: 8.3.6(typescript@5.9.3) + '@svgr/core': 8.1.0(typescript@5.9.2) + cosmiconfig: 8.3.6(typescript@5.9.2) deepmerge: 4.3.1 svgo: 3.3.2 transitivePeerDependencies: - typescript - '@svgr/webpack@8.1.0(typescript@5.9.3)': + '@svgr/webpack@8.1.0(typescript@5.9.2)': dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-constant-elements': 7.27.1(@babel/core@7.29.0) - '@babel/preset-env': 7.29.0(@babel/core@7.29.0) - '@babel/preset-react': 7.28.5(@babel/core@7.29.0) - '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0) - '@svgr/core': 8.1.0(typescript@5.9.3) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) - '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3))(typescript@5.9.3) + '@babel/core': 7.28.3 + '@babel/plugin-transform-react-constant-elements': 7.27.1(@babel/core@7.28.3) + '@babel/preset-env': 7.28.3(@babel/core@7.28.3) + '@babel/preset-react': 7.27.1(@babel/core@7.28.3) + '@babel/preset-typescript': 7.27.1(@babel/core@7.28.3) + '@svgr/core': 8.1.0(typescript@5.9.2) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2)) + '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))(typescript@5.9.2) transitivePeerDependencies: - supports-color - typescript @@ -12282,7 +13184,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@swc/helpers@0.5.18': + '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 @@ -12290,90 +13192,90 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tailwindcss/node@4.1.18': + '@tailwindcss/node@4.1.17': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.18.4 + enhanced-resolve: 5.18.3 jiti: 2.6.1 lightningcss: 1.30.2 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.1.18 + tailwindcss: 4.1.17 - '@tailwindcss/oxide-android-arm64@4.1.18': + '@tailwindcss/oxide-android-arm64@4.1.17': optional: true - '@tailwindcss/oxide-darwin-arm64@4.1.18': + '@tailwindcss/oxide-darwin-arm64@4.1.17': optional: true - '@tailwindcss/oxide-darwin-x64@4.1.18': + '@tailwindcss/oxide-darwin-x64@4.1.17': optional: true - '@tailwindcss/oxide-freebsd-x64@4.1.18': + '@tailwindcss/oxide-freebsd-x64@4.1.17': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.17': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.1.18': + '@tailwindcss/oxide-linux-arm64-musl@4.1.17': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.1.18': + '@tailwindcss/oxide-linux-x64-gnu@4.1.17': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.1.18': + '@tailwindcss/oxide-linux-x64-musl@4.1.17': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.1.18': + '@tailwindcss/oxide-wasm32-wasi@4.1.17': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.17': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.1.18': + '@tailwindcss/oxide-win32-x64-msvc@4.1.17': optional: true - '@tailwindcss/oxide@4.1.18': + '@tailwindcss/oxide@4.1.17': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.18 - '@tailwindcss/oxide-darwin-arm64': 4.1.18 - '@tailwindcss/oxide-darwin-x64': 4.1.18 - '@tailwindcss/oxide-freebsd-x64': 4.1.18 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.18 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.18 - '@tailwindcss/oxide-linux-x64-musl': 4.1.18 - '@tailwindcss/oxide-wasm32-wasi': 4.1.18 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - - '@tailwindcss/postcss@4.1.18': + '@tailwindcss/oxide-android-arm64': 4.1.17 + '@tailwindcss/oxide-darwin-arm64': 4.1.17 + '@tailwindcss/oxide-darwin-x64': 4.1.17 + '@tailwindcss/oxide-freebsd-x64': 4.1.17 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.17 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.17 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.17 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.17 + '@tailwindcss/oxide-linux-x64-musl': 4.1.17 + '@tailwindcss/oxide-wasm32-wasi': 4.1.17 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.17 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.17 + + '@tailwindcss/postcss@4.1.17': dependencies: '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.1.18 - '@tailwindcss/oxide': 4.1.18 + '@tailwindcss/node': 4.1.17 + '@tailwindcss/oxide': 4.1.17 postcss: 8.5.6 - tailwindcss: 4.1.18 + tailwindcss: 4.1.17 - '@tanstack/query-core@5.90.20': {} + '@tanstack/query-core@5.90.11': {} - '@tanstack/react-query@5.90.20(react@19.2.1)': + '@tanstack/react-query@5.90.11(react@19.2.1)': dependencies: - '@tanstack/query-core': 5.90.20 + '@tanstack/query-core': 5.90.11 react: 19.2.1 - '@tanstack/react-query@5.90.20(react@19.2.4)': + '@tanstack/react-query@5.90.11(react@19.2.3)': dependencies: - '@tanstack/query-core': 5.90.20 - react: 19.2.4 + '@tanstack/query-core': 5.90.11 + react: 19.2.3 '@trysound/sax@0.2.0': {} - '@tybys/wasm-util@0.10.1': + '@tybys/wasm-util@0.10.0': dependencies: tslib: 2.8.1 optional: true @@ -12381,23 +13283,22 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.19.7 + '@types/node': 22.18.0 '@types/cacheable-request@6.0.3': dependencies: - '@types/http-cache-semantics': 4.0.4 + '@types/http-cache-semantics': 4.2.0 '@types/keyv': 3.1.4 - '@types/node': 22.19.7 + '@types/node': 22.18.0 '@types/responselike': 1.0.3 - '@types/chai@5.2.3': + '@types/chai@5.2.2': dependencies: '@types/deep-eql': 4.0.2 - assertion-error: 2.0.1 '@types/connect@3.4.38': dependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 '@types/debug@4.1.12': dependencies: @@ -12407,20 +13308,20 @@ snapshots: '@types/estree@1.0.8': {} - '@types/express-serve-static-core@5.1.1': + '@types/express-serve-static-core@5.0.7': dependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 + '@types/send': 0.17.5 - '@types/express@5.0.6': + '@types/express@5.0.3': dependencies: '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 5.1.1 - '@types/serve-static': 2.2.0 + '@types/express-serve-static-core': 5.0.7 + '@types/serve-static': 1.15.8 - '@types/http-cache-semantics@4.0.4': {} + '@types/http-cache-semantics@4.2.0': {} '@types/http-errors@2.0.5': {} @@ -12430,15 +13331,17 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 + + '@types/lodash@4.17.20': {} - '@types/lodash@4.17.23': {} + '@types/mime@1.3.5': {} '@types/ms@2.1.0': {} '@types/node@12.20.55': {} - '@types/node@22.19.7': + '@types/node@22.18.0': dependencies: undici-types: 6.21.0 @@ -12450,26 +13353,28 @@ snapshots: '@types/range-parser@1.2.7': {} - '@types/react-dom@19.2.3(@types/react@19.2.10)': + '@types/react-dom@19.1.9(@types/react@19.1.12)': dependencies: - '@types/react': 19.2.10 + '@types/react': 19.1.12 - '@types/react@19.2.10': + '@types/react@19.1.12': dependencies: - csstype: 3.2.3 + csstype: 3.1.3 '@types/responselike@1.0.3': dependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 - '@types/send@1.2.1': + '@types/send@0.17.5': dependencies: - '@types/node': 22.19.7 + '@types/mime': 1.3.5 + '@types/node': 22.18.0 - '@types/serve-static@2.2.0': + '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.19.7 + '@types/node': 22.18.0 + '@types/send': 0.17.5 '@types/trusted-types@2.0.7': {} @@ -12477,101 +13382,194 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 '@types/ws@8.18.1': dependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 + + '@typescript-eslint/eslint-plugin@8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.42.0 + '@typescript-eslint/type-utils': 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.42.0 + eslint: 9.34.0(jiti@2.6.1) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color - '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 - eslint: 9.39.2(jiti@2.6.1) + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.49.0 + '@typescript-eslint/type-utils': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.49.0 + eslint: 9.34.0(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': dependencies: - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/scope-manager': 8.42.0 + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.42.0 + debug: 4.4.1 + eslint: 9.34.0(jiti@2.6.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.49.0 + '@typescript-eslint/types': 8.49.0 + '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.49.0 debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 + eslint: 9.34.0(jiti@2.6.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.42.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2) + '@typescript-eslint/types': 8.42.0 + debug: 4.4.1 + typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.54.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.49.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) - '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/tsconfig-utils': 8.49.0(typescript@5.9.2) + '@typescript-eslint/types': 8.49.0 debug: 4.4.3 - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.54.0': + '@typescript-eslint/scope-manager@8.42.0': + dependencies: + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/visitor-keys': 8.42.0 + + '@typescript-eslint/scope-manager@8.49.0': + dependencies: + '@typescript-eslint/types': 8.49.0 + '@typescript-eslint/visitor-keys': 8.49.0 + + '@typescript-eslint/tsconfig-utils@8.42.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@typescript-eslint/tsconfig-utils@8.49.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/visitor-keys': 8.54.0 + typescript: 5.9.2 - '@typescript-eslint/tsconfig-utils@8.54.0(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': dependencies: - typescript: 5.9.3 + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + debug: 4.4.1 + eslint: 9.34.0(jiti@2.6.1) + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color - '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': dependencies: - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.49.0 + '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 + eslint: 9.34.0(jiti@2.6.1) + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.54.0': {} + '@typescript-eslint/types@8.42.0': {} + + '@typescript-eslint/types@8.49.0': {} + + '@typescript-eslint/typescript-estree@8.42.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/project-service': 8.42.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2) + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/visitor-keys': 8.42.0 + 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.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color - '@typescript-eslint/typescript-estree@8.54.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.49.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/project-service': 8.54.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/visitor-keys': 8.54.0 + '@typescript-eslint/project-service': 8.49.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.49.0(typescript@5.9.2) + '@typescript-eslint/types': 8.49.0 + '@typescript-eslint/visitor-keys': 8.49.0 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 tinyglobby: 0.2.15 - ts-api-utils: 2.4.0(typescript@5.9.3) - typescript: 5.9.3 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.8.0(eslint@9.34.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.42.0 + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2) + eslint: 9.34.0(jiti@2.6.1) + typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.54.0 - '@typescript-eslint/types': 8.54.0 - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 + '@eslint-community/eslint-utils': 4.8.0(eslint@9.34.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.49.0 + '@typescript-eslint/types': 8.49.0 + '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.2) + eslint: 9.34.0(jiti@2.6.1) + typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.54.0': + '@typescript-eslint/visitor-keys@8.42.0': dependencies: - '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/types': 8.42.0 + eslint-visitor-keys: 4.2.1 + + '@typescript-eslint/visitor-keys@8.49.0': + dependencies: + '@typescript-eslint/types': 8.49.0 eslint-visitor-keys: 4.2.1 '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -12644,19 +13642,19 @@ snapshots: '@vitest/expect@3.2.4': dependencies: - '@types/chai': 5.2.3 + '@types/chai': 5.2.2 '@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.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 0.30.18 optionalDependencies: - vite: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + vite: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -12666,17 +13664,17 @@ snapshots: dependencies: '@vitest/utils': 3.2.4 pathe: 2.0.3 - strip-literal: 3.1.0 + strip-literal: 3.0.0 '@vitest/snapshot@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 - magic-string: 0.30.21 + magic-string: 0.30.18 pathe: 2.0.3 '@vitest/spy@3.2.4': dependencies: - tinyspy: 4.0.4 + tinyspy: 4.0.3 '@vitest/utils@3.2.4': dependencies: @@ -12684,21 +13682,20 @@ snapshots: loupe: 3.2.1 tinyrainbow: 2.0.0 - '@wagmi/connectors@5.11.2(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': + '@wagmi/connectors@5.9.9(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(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.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)': dependencies: - '@base-org/account': 1.1.1(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) - '@gemini-wallet/core': 0.2.0(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@base-org/account': 1.1.1(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@gemini-wallet/core': 0.2.0(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.19(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -12711,7 +13708,6 @@ snapshots: - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' - - '@tanstack/react-query' - '@types/react' - '@upstash/redis' - '@vercel/blob' @@ -12728,24 +13724,22 @@ snapshots: - uploadthing - use-sync-external-store - utf-8-validate - - wagmi - zod - '@wagmi/connectors@5.11.2(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': + '@wagmi/connectors@5.9.9(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)': dependencies: - '@base-org/account': 1.1.1(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(zod@3.25.76) - '@gemini-wallet/core': 0.2.0(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@base-org/account': 1.1.1(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76) + '@gemini-wallet/core': 0.2.0(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.19(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -12758,7 +13752,6 @@ snapshots: - '@netlify/blobs' - '@planetscale/database' - '@react-native-async-storage/async-storage' - - '@tanstack/react-query' - '@types/react' - '@upstash/redis' - '@vercel/blob' @@ -12775,24 +13768,23 @@ snapshots: - uploadthing - use-sync-external-store - utf-8-validate - - wagmi - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': + '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(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.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.2.10)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) - '@gemini-wallet/core': 0.3.2(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@base-org/account': 2.4.0(@types/react@19.1.12)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@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.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -12831,21 +13823,21 @@ snapshots: - wagmi - zod - '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': + '@wagmi/connectors@6.2.0(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.2.10)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.10)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(zod@3.25.76) - '@gemini-wallet/core': 0.3.2(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@metamask/sdk': 0.33.1(bufferutil@4.1.0)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@base-org/account': 2.4.0(@types/react@19.1.12)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.12)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(zod@3.25.76) + '@gemini-wallet/core': 0.3.2(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@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.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -12884,30 +13876,75 @@ snapshots: - wagmi - zod - '@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))': + '@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.7(typescript@5.9.2) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.0(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + optionalDependencies: + '@tanstack/query-core': 5.90.11 + typescript: 5.9.2 + transitivePeerDependencies: + - '@types/react' + - immer + - react + - use-sync-external-store + + '@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.7(typescript@5.9.2) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.0(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + optionalDependencies: + '@tanstack/query-core': 5.90.11 + typescript: 5.9.2 + transitivePeerDependencies: + - '@types/react' + - immer + - react + - use-sync-external-store + + '@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.7(typescript@5.9.2) + viem: 2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.0(@types/react@19.1.12)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) + optionalDependencies: + '@tanstack/query-core': 5.90.11 + typescript: 5.9.2 + transitivePeerDependencies: + - '@types/react' + - immer + - react + - use-sync-external-store + + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: eventemitter3: 5.0.1 - mipd: 0.0.7(typescript@5.9.3) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.0(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + mipd: 0.0.7(typescript@5.9.2) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.0(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) optionalDependencies: - '@tanstack/query-core': 5.90.20 - typescript: 5.9.3 + '@tanstack/query-core': 5.90.11 + typescript: 5.9.2 transitivePeerDependencies: - '@types/react' - immer - react - use-sync-external-store - '@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))': + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: eventemitter3: 5.0.1 - mipd: 0.0.7(typescript@5.9.3) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zustand: 5.0.0(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)) + mipd: 0.0.7(typescript@5.9.2) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zustand: 5.0.0(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) optionalDependencies: - '@tanstack/query-core': 5.90.20 - typescript: 5.9.3 + '@tanstack/query-core': 5.90.11 + typescript: 5.9.2 transitivePeerDependencies: - '@types/react' - immer @@ -12924,13 +13961,13 @@ snapshots: dependencies: '@wallet-standard/base': 1.1.0 - '@walletconnect/core@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/core@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.1.0)(utf-8-validate@5.0.10) + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@walletconnect/keyvaluestorage': 1.1.1(@vercel/functions@2.2.13) '@walletconnect/logger': 2.1.2 '@walletconnect/relay-api': 1.0.11 @@ -12938,7 +13975,7 @@ snapshots: '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 '@walletconnect/types': 2.21.0(@vercel/functions@2.2.13) - '@walletconnect/utils': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/window-getters': 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 @@ -12968,13 +14005,13 @@ snapshots: - utf-8-validate - zod - '@walletconnect/core@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/core@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.1.0)(utf-8-validate@5.0.10) + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@walletconnect/keyvaluestorage': 1.1.1(@vercel/functions@2.2.13) '@walletconnect/logger': 2.1.2 '@walletconnect/relay-api': 1.0.11 @@ -12982,7 +14019,7 @@ snapshots: '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 '@walletconnect/types': 2.21.1(@vercel/functions@2.2.13) - '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/window-getters': 1.0.1 es-toolkit: 1.33.0 events: 3.3.0 @@ -13016,18 +14053,18 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/ethereum-provider@2.21.1(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@vercel/functions@2.2.13) - '@walletconnect/sign-client': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/sign-client': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/types': 2.21.1(@vercel/functions@2.2.13) - '@walletconnect/universal-provider': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -13057,18 +14094,18 @@ snapshots: - utf-8-validate - zod - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/ethereum-provider@2.21.1(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit': 1.7.8(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit': 1.7.8(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/jsonrpc-http-connection': 1.0.8 '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@vercel/functions@2.2.13) - '@walletconnect/sign-client': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/sign-client': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/types': 2.21.1(@vercel/functions@2.2.13) - '@walletconnect/universal-provider': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -13135,12 +14172,12 @@ snapshots: '@walletconnect/jsonrpc-types': 1.0.4 tslib: 1.14.1 - '@walletconnect/jsonrpc-ws-connection@1.0.16(bufferutil@4.1.0)(utf-8-validate@5.0.10)': + '@walletconnect/jsonrpc-ws-connection@1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10)': dependencies: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/safe-json': 1.0.2 events: 3.3.0 - ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -13149,7 +14186,7 @@ snapshots: dependencies: '@walletconnect/safe-json': 1.0.2 idb-keyval: 6.2.2 - unstorage: 1.17.4(@vercel/functions@2.2.13)(idb-keyval@6.2.2) + unstorage: 1.17.0(@vercel/functions@2.2.13)(idb-keyval@6.2.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -13191,16 +14228,16 @@ snapshots: dependencies: tslib: 1.14.1 - '@walletconnect/sign-client@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/sign-client@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@walletconnect/core': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/core': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 '@walletconnect/time': 1.0.2 '@walletconnect/types': 2.21.0(@vercel/functions@2.2.13) - '@walletconnect/utils': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -13227,16 +14264,16 @@ snapshots: - utf-8-validate - zod - '@walletconnect/sign-client@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/sign-client@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@walletconnect/core': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/core': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/events': 1.0.1 '@walletconnect/heartbeat': 1.2.2 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/logger': 2.1.2 '@walletconnect/time': 1.0.2 '@walletconnect/types': 2.21.1(@vercel/functions@2.2.13) - '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -13325,7 +14362,7 @@ snapshots: - ioredis - uploadthing - '@walletconnect/universal-provider@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/universal-provider@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/jsonrpc-http-connection': 1.0.8 @@ -13334,9 +14371,9 @@ snapshots: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@vercel/functions@2.2.13) '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/sign-client': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/types': 2.21.0(@vercel/functions@2.2.13) - '@walletconnect/utils': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) es-toolkit: 1.33.0 events: 3.3.0 transitivePeerDependencies: @@ -13365,7 +14402,7 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/universal-provider@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/events': 1.0.1 '@walletconnect/jsonrpc-http-connection': 1.0.8 @@ -13374,9 +14411,9 @@ snapshots: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@vercel/functions@2.2.13) '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/sign-client': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/types': 2.21.1(@vercel/functions@2.2.13) - '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) es-toolkit: 1.33.0 events: 3.3.0 transitivePeerDependencies: @@ -13405,7 +14442,7 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/utils@2.21.0(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 '@noble/curves': 1.8.1 @@ -13423,7 +14460,7 @@ snapshots: detect-browser: 5.3.0 query-string: 7.1.3 uint8arrays: 3.1.0 - viem: 2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -13449,7 +14486,7 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/utils@2.21.1(@vercel/functions@2.2.13)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 '@noble/curves': 1.8.1 @@ -13467,7 +14504,7 @@ snapshots: detect-browser: 5.3.0 query-string: 7.1.3 uint8arrays: 3.1.0 - viem: 2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -13502,30 +14539,35 @@ snapshots: '@walletconnect/window-getters': 1.0.1 tslib: 1.14.1 - abitype@1.0.6(typescript@5.9.3)(zod@3.25.76): + abitype@1.0.6(typescript@5.9.2)(zod@3.25.76): optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 zod: 3.25.76 - abitype@1.0.8(typescript@5.9.3)(zod@3.25.76): + abitype@1.0.8(typescript@5.9.2)(zod@3.25.76): optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 zod: 3.25.76 - abitype@1.2.3(typescript@5.9.3)(zod@3.22.4): + abitype@1.1.0(typescript@5.9.2)(zod@3.25.76): optionalDependencies: - typescript: 5.9.3 - zod: 3.22.4 + typescript: 5.9.2 + zod: 3.25.76 - abitype@1.2.3(typescript@5.9.3)(zod@3.25.76): + abitype@1.1.0(typescript@5.9.2)(zod@4.1.13): optionalDependencies: - typescript: 5.9.3 - zod: 3.25.76 + typescript: 5.9.2 + zod: 4.1.13 + + abitype@1.2.3(typescript@5.9.2)(zod@3.22.4): + optionalDependencies: + typescript: 5.9.2 + zod: 3.22.4 - abitype@1.2.3(typescript@5.9.3)(zod@4.3.6): + abitype@1.2.3(typescript@5.9.2)(zod@3.25.76): optionalDependencies: - typescript: 5.9.3 - zod: 4.3.6 + typescript: 5.9.2 + zod: 3.25.76 accepts@1.3.8: dependencies: @@ -13573,10 +14615,14 @@ snapshots: ansi-regex@5.0.1: {} + ansi-regex@6.2.0: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.1: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -13608,7 +14654,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 is-string: 1.1.1 @@ -13620,7 +14666,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -13630,7 +14676,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -13639,21 +14685,21 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-shim-unscopables: 1.1.0 @@ -13662,7 +14708,7 @@ snapshots: array-buffer-byte-length: 1.0.2 call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 @@ -13685,44 +14731,52 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axe-core@4.11.1: {} + axe-core@4.10.3: {} - axios-retry@4.5.0(axios@1.13.4): + axios-retry@4.5.0(axios@1.11.0): dependencies: - axios: 1.13.4 + axios: 1.11.0 is-retry-allowed: 2.2.0 + axios@1.11.0: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axios@1.13.4: dependencies: follow-redirects: 1.15.11 - form-data: 4.0.5 + form-data: 4.0.4 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug axobject-query@4.1.0: {} - babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.3): dependencies: - '@babel/compat-data': 7.29.0 - '@babel/core': 7.29.0 - '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + '@babel/compat-data': 7.28.0 + '@babel/core': 7.28.3 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.3) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.14.0(@babel/core@7.29.0): + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.3): dependencies: - '@babel/core': 7.29.0 - '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) - core-js-compat: 3.48.0 + '@babel/core': 7.28.3 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.3) + core-js-compat: 3.45.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0): + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.3): dependencies: - '@babel/core': 7.29.0 - '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + '@babel/core': 7.28.3 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.3) transitivePeerDependencies: - supports-color @@ -13734,30 +14788,45 @@ snapshots: base-x@5.0.1: {} - base64-js@1.5.1: {} + base32.js@0.1.0: {} - baseline-browser-mapping@2.9.19: {} + base64-js@1.5.1: {} better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + optional: true + big.js@6.2.2: {} + bigint-buffer@1.1.5: + dependencies: + bindings: 1.5.0 + + bignumber.js@9.3.1: {} + + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + bn.js@5.2.2: {} - body-parser@1.20.4: + body-parser@1.20.3: dependencies: bytes: 3.1.2 content-type: 1.0.5 debug: 2.6.9 depd: 2.0.0 destroy: 1.2.0 - http-errors: 2.0.1 + http-errors: 2.0.0 iconv-lite: 0.4.24 on-finished: 2.4.1 - qs: 6.14.1 - raw-body: 2.5.3 + qs: 6.13.0 + raw-body: 2.5.2 type-is: 1.6.18 unpipe: 1.0.0 transitivePeerDependencies: @@ -13768,7 +14837,7 @@ snapshots: bytes: 3.1.2 content-type: 1.0.5 debug: 4.4.3 - http-errors: 2.0.1 + http-errors: 2.0.0 iconv-lite: 0.7.2 on-finished: 2.4.1 qs: 6.14.1 @@ -13785,7 +14854,7 @@ snapshots: bs58: 4.0.1 text-encoding-utf-8: 1.0.2 - bowser@2.13.1: {} + bowser@2.12.1: {} brace-expansion@1.1.12: dependencies: @@ -13800,13 +14869,12 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.28.1: + browserslist@4.25.4: dependencies: - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001767 - electron-to-chromium: 1.5.283 - node-releases: 2.0.27 - update-browserslist-db: 1.2.3(browserslist@4.28.1) + caniuse-lite: 1.0.30001739 + electron-to-chromium: 1.5.214 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.25.4) bs58@4.0.1: dependencies: @@ -13821,13 +14889,13 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - bufferutil@4.1.0: + bufferutil@4.0.9: dependencies: node-gyp-build: 4.8.4 - bundle-require@5.1.0(esbuild@0.27.2): + bundle-require@5.1.0(esbuild@0.25.9): dependencies: - esbuild: 0.27.2 + esbuild: 0.25.9 load-tsconfig: 0.2.5 bytes@3.1.2: {} @@ -13869,12 +14937,12 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001767: {} + caniuse-lite@1.0.30001739: {} chai@5.3.3: dependencies: assertion-error: 2.0.1 - check-error: 2.1.3 + check-error: 2.1.1 deep-eql: 5.0.2 loupe: 3.2.1 pathval: 2.0.1 @@ -13890,16 +14958,12 @@ snapshots: charenc@0.0.2: {} - check-error@2.1.3: {} + check-error@2.1.1: {} chokidar@4.0.3: dependencies: readdirp: 4.1.2 - chokidar@5.0.0: - dependencies: - readdirp: 5.0.0 - ci-info@3.9.0: {} client-only@0.0.1: {} @@ -13932,6 +14996,8 @@ snapshots: commander@12.1.0: {} + commander@14.0.1: {} + commander@14.0.2: {} commander@14.0.3: {} @@ -13962,15 +15028,15 @@ snapshots: cookie-es@1.2.2: {} - cookie-signature@1.0.7: {} + cookie-signature@1.0.6: {} cookie-signature@1.2.2: {} - cookie@0.7.2: {} + cookie@0.7.1: {} - core-js-compat@3.48.0: + core-js-compat@3.45.1: dependencies: - browserslist: 4.28.1 + browserslist: 4.25.4 core-util-is@1.0.3: {} @@ -13979,14 +15045,14 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig@8.3.6(typescript@5.9.3): + cosmiconfig@8.3.6(typescript@5.9.2): dependencies: import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 crc-32@1.2.2: {} @@ -14046,11 +15112,11 @@ snapshots: cssstyle@5.3.6: dependencies: '@asamuzakjp/css-color': 4.1.1 - '@csstools/css-syntax-patches-for-csstree': 1.0.26 + '@csstools/css-syntax-patches-for-csstree': 1.0.22 css-tree: 3.1.0 - lru-cache: 11.2.5 + lru-cache: 11.2.4 - csstype@3.2.3: {} + csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} @@ -14059,6 +15125,12 @@ snapshots: whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 + data-urls@6.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + optional: true + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -14081,7 +15153,7 @@ snapshots: date-fns@2.30.0: dependencies: - '@babel/runtime': 7.28.6 + '@babel/runtime': 7.28.3 dayjs@1.11.13: {} @@ -14097,6 +15169,10 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.3.7: + dependencies: + ms: 2.1.3 + debug@4.4.1: dependencies: ms: 2.1.3 @@ -14143,13 +15219,13 @@ snapshots: depd@2.0.0: {} - derive-valtio@0.1.0(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1)): + derive-valtio@0.1.0(valtio@1.13.2(@types/react@19.1.12)(react@19.2.1)): dependencies: - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.1) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.1) - derive-valtio@0.1.0(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4)): + derive-valtio@0.1.0(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3)): dependencies: - valtio: 1.13.2(@types/react@19.2.10)(react@19.2.4) + valtio: 1.13.2(@types/react@19.1.12)(react@19.2.3) destr@2.0.5: {} @@ -14209,16 +15285,18 @@ snapshots: readable-stream: 3.6.2 stream-shift: 1.0.3 - eciesjs@0.4.17: + eastasianwidth@0.2.0: {} + + eciesjs@0.4.15: dependencies: - '@ecies/ciphers': 0.2.5(@noble/ciphers@1.3.0) + '@ecies/ciphers': 0.2.4(@noble/ciphers@1.3.0) '@noble/ciphers': 1.3.0 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 ee-first@1.1.1: {} - electron-to-chromium@1.5.283: {} + electron-to-chromium@1.5.214: {} emoji-regex@8.0.0: {} @@ -14226,18 +15304,20 @@ snapshots: encode-utf8@1.0.3: {} + encodeurl@1.0.2: {} + encodeurl@2.0.0: {} end-of-stream@1.4.5: dependencies: once: 1.4.0 - engine.io-client@6.6.4(bufferutil@4.1.0)(utf-8-validate@5.0.10): + 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.4.3 + debug: 4.3.7 engine.io-parser: 5.2.3 - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 8.17.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) xmlhttprequest-ssl: 2.1.2 transitivePeerDependencies: - bufferutil @@ -14246,7 +15326,7 @@ snapshots: engine.io-parser@5.2.3: {} - enhanced-resolve@5.18.4: + enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 tapable: 2.3.0 @@ -14260,11 +15340,11 @@ snapshots: entities@6.0.1: {} - error-ex@1.3.4: + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - es-abstract@1.24.1: + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 arraybuffer.prototype.slice: 1.0.4 @@ -14319,18 +15399,18 @@ snapshots: typed-array-byte-offset: 1.0.4 typed-array-length: 1.0.7 unbox-primitive: 1.1.0 - which-typed-array: 1.1.20 + which-typed-array: 1.1.19 es-define-property@1.0.1: {} es-errors@1.3.0: {} - es-iterator-helpers@1.2.2: + es-iterator-helpers@1.2.1: dependencies: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-set-tostringtag: 2.1.0 function-bind: 1.1.2 @@ -14375,63 +15455,34 @@ snapshots: dependencies: es6-promise: 4.2.8 - esbuild@0.25.12: + esbuild@0.25.9: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 - - esbuild@0.27.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 + '@esbuild/aix-ppc64': 0.25.9 + '@esbuild/android-arm': 0.25.9 + '@esbuild/android-arm64': 0.25.9 + '@esbuild/android-x64': 0.25.9 + '@esbuild/darwin-arm64': 0.25.9 + '@esbuild/darwin-x64': 0.25.9 + '@esbuild/freebsd-arm64': 0.25.9 + '@esbuild/freebsd-x64': 0.25.9 + '@esbuild/linux-arm': 0.25.9 + '@esbuild/linux-arm64': 0.25.9 + '@esbuild/linux-ia32': 0.25.9 + '@esbuild/linux-loong64': 0.25.9 + '@esbuild/linux-mips64el': 0.25.9 + '@esbuild/linux-ppc64': 0.25.9 + '@esbuild/linux-riscv64': 0.25.9 + '@esbuild/linux-s390x': 0.25.9 + '@esbuild/linux-x64': 0.25.9 + '@esbuild/netbsd-arm64': 0.25.9 + '@esbuild/netbsd-x64': 0.25.9 + '@esbuild/openbsd-arm64': 0.25.9 + '@esbuild/openbsd-x64': 0.25.9 + '@esbuild/openharmony-arm64': 0.25.9 + '@esbuild/sunos-x64': 0.25.9 + '@esbuild/win32-arm64': 0.25.9 + '@esbuild/win32-ia32': 0.25.9 + '@esbuild/win32-x64': 0.25.9 escalade@3.2.0: {} @@ -14439,20 +15490,20 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@16.0.6(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + eslint-config-next@16.0.6(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2): dependencies: '@next/eslint-plugin-next': 16.0.6 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.34.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.34.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.34.0(jiti@2.6.1)) + eslint-plugin-react: 7.37.5(eslint@9.34.0(jiti@2.6.1)) + eslint-plugin-react-hooks: 7.0.1(eslint@9.34.0(jiti@2.6.1)) globals: 16.4.0 - typescript-eslint: 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + typescript-eslint: 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-webpack @@ -14463,37 +15514,76 @@ snapshots: dependencies: debug: 3.2.7 is-core-module: 2.16.1 - resolve: 1.22.11 + resolve: 1.22.10 transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.34.0(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.3 - eslint: 9.39.2(jiti@2.6.1) - get-tsconfig: 4.13.1 + debug: 4.4.1 + eslint: 9.34.0(jiti@2.6.1) + get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 - tinyglobby: 0.2.15 + tinyglobby: 0.2.14 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + eslint: 9.34.0(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.34.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.34.0(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) + '@typescript-eslint/parser': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + eslint: 9.34.0(jiti@2.6.1) + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)): + 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.34.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.6.1)) + 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.42.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -14502,9 +15592,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.34.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.34.0(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -14516,39 +15606,39 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsdoc@50.8.0(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-jsdoc@50.8.0(eslint@9.34.0(jiti@2.6.1)): dependencies: '@es-joy/jsdoccomment': 0.50.2 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.4.3 + debug: 4.4.1 escape-string-regexp: 4.0.0 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.34.0(jiti@2.6.1) espree: 10.4.0 - esquery: 1.7.0 + esquery: 1.6.0 parse-imports-exports: 0.2.4 - semver: 7.7.3 + semver: 7.7.2 spdx-expression-parse: 4.0.0 transitivePeerDependencies: - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.34.0(jiti@2.6.1)): 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.11.1 + axe-core: 4.10.3 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.34.0(jiti@2.6.1) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -14557,33 +15647,33 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-prettier@5.5.5(eslint@9.39.2(jiti@2.6.1))(prettier@3.5.2): + eslint-plugin-prettier@5.5.4(eslint@9.34.0(jiti@2.6.1))(prettier@3.5.2): dependencies: - eslint: 9.39.2(jiti@2.6.1) + eslint: 9.34.0(jiti@2.6.1) prettier: 3.5.2 - prettier-linter-helpers: 1.0.1 - synckit: 0.11.12 + prettier-linter-helpers: 1.0.0 + synckit: 0.11.11 - eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-react-hooks@7.0.1(eslint@9.34.0(jiti@2.6.1)): dependencies: - '@babel/core': 7.29.0 - '@babel/parser': 7.29.0 - eslint: 9.39.2(jiti@2.6.1) + '@babel/core': 7.28.3 + '@babel/parser': 7.28.3 + eslint: 9.34.0(jiti@2.6.1) hermes-parser: 0.25.1 zod: 3.25.76 zod-validation-error: 4.0.2(zod@3.25.76) transitivePeerDependencies: - supports-color - eslint-plugin-react@7.37.5(eslint@9.39.2(jiti@2.6.1)): + eslint-plugin-react@7.37.5(eslint@9.34.0(jiti@2.6.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 array.prototype.flatmap: 1.3.3 array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 - es-iterator-helpers: 1.2.2 - eslint: 9.39.2(jiti@2.6.1) + es-iterator-helpers: 1.2.1 + eslint: 9.34.0(jiti@2.6.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -14606,29 +15696,30 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.2(jiti@2.6.1): + eslint@9.34.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1 - '@eslint/config-helpers': 0.4.2 - '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.2 - '@eslint/plugin-kit': 0.4.1 + '@eslint-community/eslint-utils': 4.8.0(eslint@9.34.0(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.34.0 + '@eslint/plugin-kit': 0.3.5 '@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.3 + debug: 4.4.1 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 - esquery: 1.7.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -14655,7 +15746,7 @@ snapshots: esprima@4.0.1: {} - esquery@1.7.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -14707,7 +15798,7 @@ snapshots: '@scure/bip32': 1.4.0 '@scure/bip39': 1.3.0 - ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + ethers@6.16.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@adraffy/ens-normalize': 1.10.1 '@noble/curves': 1.2.0 @@ -14715,7 +15806,7 @@ snapshots: '@types/node': 22.7.5 aes-js: 4.0.0-beta.5 tslib: 2.7.0 - ws: 8.17.1(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 8.17.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -14724,52 +15815,53 @@ snapshots: eventemitter3@5.0.1: {} - eventemitter3@5.0.4: {} - events@3.3.0: {} eventsource-parser@3.0.6: {} + eventsource@2.0.2: {} + eventsource@3.0.7: dependencies: eventsource-parser: 3.0.6 - expect-type@1.3.0: {} + expect-type@1.2.2: {} - express-rate-limit@7.5.1(express@5.2.1): + express-rate-limit@8.2.1(express@5.2.1): dependencies: express: 5.2.1 + ip-address: 10.0.1 - express@4.22.1: + express@4.21.2: dependencies: accepts: 1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.4 + body-parser: 1.20.3 content-disposition: 0.5.4 content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.0.7 + cookie: 0.7.1 + cookie-signature: 1.0.6 debug: 2.6.9 depd: 2.0.0 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 1.3.2 + finalhandler: 1.3.1 fresh: 0.5.2 - http-errors: 2.0.1 + http-errors: 2.0.0 merge-descriptors: 1.0.3 methods: 1.1.2 on-finished: 2.4.1 parseurl: 1.3.3 path-to-regexp: 0.1.12 proxy-addr: 2.0.7 - qs: 6.14.1 + qs: 6.13.0 range-parser: 1.2.1 safe-buffer: 5.2.1 - send: 0.19.2 - serve-static: 1.16.3 + send: 0.19.0 + serve-static: 1.16.2 setprototypeof: 1.2.0 - statuses: 2.0.2 + statuses: 2.0.1 type-is: 1.6.18 utils-merge: 1.0.1 vary: 1.1.2 @@ -14782,7 +15874,7 @@ snapshots: body-parser: 2.2.2 content-disposition: 1.0.1 content-type: 1.0.5 - cookie: 0.7.2 + cookie: 0.7.1 cookie-signature: 1.2.2 debug: 4.4.3 depd: 2.0.0 @@ -14791,7 +15883,7 @@ snapshots: etag: 1.8.1 finalhandler: 2.1.1 fresh: 2.0.0 - http-errors: 2.0.1 + http-errors: 2.0.0 merge-descriptors: 2.0.0 mime-types: 3.0.2 on-finished: 2.4.1 @@ -14803,7 +15895,7 @@ snapshots: router: 2.2.0 send: 1.2.1 serve-static: 2.2.1 - statuses: 2.0.2 + statuses: 2.0.1 type-is: 2.0.1 vary: 1.1.2 transitivePeerDependencies: @@ -14852,7 +15944,7 @@ snapshots: fastestsmallesttextencoderdecoder@1.0.22: {} - fastq@1.20.1: + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -14860,24 +15952,30 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + feaxios@0.0.23: + dependencies: + is-retry-allowed: 3.0.0 + 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 filter-obj@1.1.0: {} - finalhandler@1.3.2: + finalhandler@1.3.1: dependencies: debug: 2.6.9 encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 parseurl: 1.3.3 - statuses: 2.0.2 + statuses: 2.0.1 unpipe: 1.0.0 transitivePeerDependencies: - supports-color @@ -14889,7 +15987,7 @@ snapshots: escape-html: 1.0.3 on-finished: 2.4.1 parseurl: 1.3.3 - statuses: 2.0.2 + statuses: 2.0.1 transitivePeerDependencies: - supports-color @@ -14905,9 +16003,9 @@ snapshots: fix-dts-default-cjs-exports@1.0.1: dependencies: - magic-string: 0.30.21 + magic-string: 0.30.18 mlly: 1.8.0 - rollup: 4.57.1 + rollup: 4.50.0 flat-cache@4.0.1: dependencies: @@ -14922,7 +16020,12 @@ snapshots: dependencies: is-callable: 1.2.7 - form-data@4.0.5: + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.4: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -14932,14 +16035,14 @@ snapshots: forwarded@0.2.0: {} - framer-motion@11.18.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + framer-motion@11.18.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: motion-dom: 11.18.1 motion-utils: 11.18.1 tslib: 2.8.1 optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) fresh@0.5.2: {} @@ -14973,8 +16076,6 @@ snapshots: functions-have-names@1.2.3: {} - generator-function@2.0.1: {} - gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} @@ -15007,7 +16108,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.13.1: + get-tsconfig@4.10.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -15019,6 +16120,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + globals@14.0.0: {} globals@16.4.0: {} @@ -15057,26 +16167,28 @@ snapshots: graceful-fs@4.2.11: {} - graphql-request@6.1.0(graphql@16.12.0): + graphemer@1.4.0: {} + + graphql-request@6.1.0(graphql@16.11.0): dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0) cross-fetch: 3.2.0 - graphql: 16.12.0 + graphql: 16.11.0 transitivePeerDependencies: - encoding - graphql@16.12.0: {} + graphql@16.11.0: {} - h3@1.15.5: + 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.4 + node-mock-http: 1.0.2 radix3: 1.1.2 - ufo: 1.6.3 + ufo: 1.6.1 uncrypto: 0.1.3 has-bigints@1.1.0: {} @@ -15107,14 +16219,31 @@ snapshots: dependencies: hermes-estree: 0.25.1 + hono@4.10.7: {} + hono@4.11.7: {} html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.8.0 + transitivePeerDependencies: + - '@exodus/crypto' + optional: true + http-cache-semantics@4.2.0: {} + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -15185,6 +16314,8 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 + ip-address@10.0.1: {} + ipaddr.js@1.9.1: {} iron-webcrypto@1.2.1: {} @@ -15250,10 +16381,9 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.1.2: + is-generator-function@1.1.0: 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 @@ -15286,6 +16416,8 @@ snapshots: is-retry-allowed@2.2.0: {} + is-retry-allowed@3.0.0: {} + is-set@2.0.3: {} is-shared-array-buffer@1.0.4: @@ -15311,7 +16443,7 @@ snapshots: is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.20 + which-typed-array: 1.1.19 is-weakmap@2.0.2: {} @@ -15332,17 +16464,17 @@ snapshots: isexe@2.0.0: {} - isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@5.0.10)): + isomorphic-ws@4.0.1(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: - ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) - isows@1.0.6(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)): + isows@1.0.6(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: - ws: 8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - isows@1.0.7(ws@8.18.3(bufferutil@4.1.0)(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.1.0)(utf-8-validate@5.0.10) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) iterator.prototype@1.1.5: dependencies: @@ -15353,7 +16485,13 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 - jayson@4.3.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jayson@4.2.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: '@types/connect': 3.4.38 '@types/node': 12.20.55 @@ -15362,11 +16500,11 @@ snapshots: delay: 5.0.0 es6-promisify: 5.0.0 eyes: 0.1.8 - isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@5.0.10)) + isomorphic-ws: 4.0.1(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) json-stringify-safe: 5.0.1 stream-json: 1.9.1 uuid: 8.3.2 - ws: 7.5.10(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -15375,6 +16513,8 @@ snapshots: jose@5.10.0: {} + jose@6.1.0: {} + jose@6.1.3: {} joycon@3.1.1: {} @@ -15390,13 +16530,17 @@ snapshots: argparse: 1.0.10 esprima: 4.0.1 + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + js-yaml@4.1.1: dependencies: argparse: 2.0.1 jsdoc-type-pratt-parser@4.1.0: {} - jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): dependencies: cssstyle: 5.3.6 data-urls: 5.0.0 @@ -15405,7 +16549,7 @@ snapshots: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.23 + nwsapi: 2.2.21 parse5: 7.3.0 rrweb-cssom: 0.8.0 saxes: 6.0.0 @@ -15416,12 +16560,43 @@ snapshots: whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): + dependencies: + '@acemir/cssom': 0.9.30 + '@asamuzakjp/dom-selector': 6.7.6 + '@exodus/bytes': 1.8.0 + cssstyle: 5.3.6 + data-urls: 6.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 8.0.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) xml-name-validator: 5.0.0 transitivePeerDependencies: + - '@exodus/crypto' - bufferutil - supports-color - utf-8-validate + optional: true + + jsesc@3.0.2: {} jsesc@3.1.0: {} @@ -15541,21 +16716,21 @@ snapshots: lines-and-columns@1.2.4: {} - lit-element@4.2.2: + lit-element@4.2.1: dependencies: - '@lit-labs/ssr-dom-shim': 1.5.1 - '@lit/reactive-element': 2.1.2 - lit-html: 3.3.2 + '@lit-labs/ssr-dom-shim': 1.4.0 + '@lit/reactive-element': 2.1.1 + lit-html: 3.3.1 - lit-html@3.3.2: + lit-html@3.3.1: dependencies: '@types/trusted-types': 2.0.7 lit@3.3.0: dependencies: - '@lit/reactive-element': 2.1.2 - lit-element: 4.2.2 - lit-html: 3.3.2 + '@lit/reactive-element': 2.1.1 + lit-element: 4.2.1 + lit-html: 3.3.1 load-tsconfig@0.2.5: {} @@ -15571,19 +16746,21 @@ snapshots: lodash.merge@4.6.2: {} + lodash.sortby@4.7.0: {} + lodash.startcase@4.4.0: {} - lodash@4.17.23: {} + lodash@4.17.21: {} loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 - lottie-react@2.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + lottie-react@2.4.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: lottie-web: 5.13.0 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) lottie-web@5.13.0: {} @@ -15595,12 +16772,18 @@ snapshots: lowercase-keys@2.0.0: {} - lru-cache@11.2.5: {} + lru-cache@10.4.3: {} + + lru-cache@11.2.4: {} lru-cache@5.1.1: dependencies: yallist: 3.1.1 + magic-string@0.30.18: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -15666,16 +16849,18 @@ snapshots: minimist@1.2.8: {} - mipd@0.0.7(typescript@5.9.3): + minipass@7.1.2: {} + + mipd@0.0.7(typescript@5.9.2): optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 mlly@1.8.0: dependencies: acorn: 8.15.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.3 + ufo: 1.6.1 motion-dom@11.18.1: dependencies: @@ -15683,13 +16868,13 @@ snapshots: motion-utils@11.18.1: {} - motion@11.18.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + motion@11.18.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: - framer-motion: 11.18.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + framer-motion: 11.18.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) tslib: 2.8.1 optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) mri@1.2.0: {} @@ -15709,7 +16894,7 @@ snapshots: nanoid@3.3.11: {} - napi-postinstall@0.3.4: {} + napi-postinstall@0.3.3: {} natural-compare@1.4.0: {} @@ -15717,25 +16902,24 @@ snapshots: negotiator@1.0.0: {} - next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next@16.0.10(@babel/core@7.28.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: - '@next/env': 16.1.6 + '@next/env': 16.0.10 '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001767 + caniuse-lite: 1.0.30001739 postcss: 8.4.31 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.4) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + styled-jsx: 5.1.6(@babel/core@7.28.3)(react@19.2.3) optionalDependencies: - '@next/swc-darwin-arm64': 16.1.6 - '@next/swc-darwin-x64': 16.1.6 - '@next/swc-linux-arm64-gnu': 16.1.6 - '@next/swc-linux-arm64-musl': 16.1.6 - '@next/swc-linux-x64-gnu': 16.1.6 - '@next/swc-linux-x64-musl': 16.1.6 - '@next/swc-win32-arm64-msvc': 16.1.6 - '@next/swc-win32-x64-msvc': 16.1.6 + '@next/swc-darwin-arm64': 16.0.10 + '@next/swc-darwin-x64': 16.0.10 + '@next/swc-linux-arm64-gnu': 16.0.10 + '@next/swc-linux-arm64-musl': 16.0.10 + '@next/swc-linux-x64-gnu': 16.0.10 + '@next/swc-linux-x64-musl': 16.0.10 + '@next/swc-win32-arm64-msvc': 16.0.10 + '@next/swc-win32-x64-msvc': 16.0.10 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -15756,9 +16940,9 @@ snapshots: node-gyp-build@4.8.4: {} - node-mock-http@1.0.4: {} + node-mock-http@1.0.2: {} - node-releases@2.0.27: {} + node-releases@2.0.19: {} normalize-path@3.0.0: {} @@ -15768,7 +16952,7 @@ snapshots: dependencies: boolbase: 1.0.0 - nwsapi@2.2.23: {} + nwsapi@2.2.21: {} obj-multiplex@1.0.0: dependencies: @@ -15802,14 +16986,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 object.groupby@1.0.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 object.values@1.2.1: dependencies: @@ -15818,11 +17002,11 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - ofetch@1.5.1: + ofetch@1.4.1: dependencies: destr: 2.0.5 node-fetch-native: 1.6.7 - ufo: 1.6.3 + ufo: 1.6.1 on-exit-leak-free@0.2.0: {} @@ -15857,90 +17041,120 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - ox@0.11.3(typescript@5.9.3)(zod@3.22.4): + ox@0.11.3(typescript@5.9.2)(zod@3.22.4): dependencies: - '@adraffy/ens-normalize': 1.11.1 + '@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.2.3(typescript@5.9.3)(zod@3.22.4) + abitype: 1.2.3(typescript@5.9.2)(zod@3.22.4) eventemitter3: 5.0.1 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - zod - ox@0.11.3(typescript@5.9.3)(zod@3.25.76): + ox@0.11.3(typescript@5.9.2)(zod@3.25.76): dependencies: - '@adraffy/ens-normalize': 1.11.1 + '@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.2.3(typescript@5.9.3)(zod@3.25.76) + abitype: 1.2.3(typescript@5.9.2)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - zod - ox@0.4.4(typescript@5.9.3)(zod@3.25.76): + ox@0.4.4(typescript@5.9.2)(zod@3.25.76): dependencies: - '@adraffy/ens-normalize': 1.11.1 + '@adraffy/ens-normalize': 1.11.0 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) + abitype: 1.1.0(typescript@5.9.2)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - zod - ox@0.6.7(typescript@5.9.3)(zod@3.25.76): + ox@0.6.7(typescript@5.9.2)(zod@3.25.76): dependencies: - '@adraffy/ens-normalize': 1.11.1 + '@adraffy/ens-normalize': 1.11.0 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) + abitype: 1.1.0(typescript@5.9.2)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - zod - ox@0.6.9(typescript@5.9.3)(zod@3.25.76): + ox@0.6.9(typescript@5.9.2)(zod@3.25.76): dependencies: - '@adraffy/ens-normalize': 1.11.1 + '@adraffy/ens-normalize': 1.11.0 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) + abitype: 1.1.0(typescript@5.9.2)(zod@3.25.76) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - zod + + ox@0.9.17(typescript@5.9.2)(zod@4.1.13): + 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.0(typescript@5.9.2)(zod@4.1.13) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - zod + + ox@0.9.3(typescript@5.9.2)(zod@3.25.76): + 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.0(typescript@5.9.2)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - zod - ox@0.9.17(typescript@5.9.3)(zod@4.3.6): + ox@0.9.6(typescript@5.9.2)(zod@3.25.76): dependencies: - '@adraffy/ens-normalize': 1.11.1 + '@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.2.3(typescript@5.9.3)(zod@4.3.6) + abitype: 1.1.0(typescript@5.9.2)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - zod @@ -15970,6 +17184,8 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + package-manager-detector@0.2.11: dependencies: quansync: 0.2.11 @@ -15984,8 +17200,8 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.29.0 - error-ex: 1.3.4 + '@babel/code-frame': 7.27.1 + error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -15995,6 +17211,11 @@ snapshots: dependencies: entities: 6.0.1 + parse5@8.0.0: + dependencies: + entities: 6.0.1 + optional: true + parseurl@1.3.3: {} path-exists@4.0.0: {} @@ -16003,6 +17224,11 @@ snapshots: path-parse@1.0.7: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + path-to-regexp@0.1.12: {} path-to-regexp@8.3.0: {} @@ -16060,81 +17286,41 @@ snapshots: pony-cause@2.1.11: {} - porto@0.2.19(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)): dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - hono: 4.11.7 + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + hono: 4.10.7 idb-keyval: 6.2.2 - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zod: 4.3.6 - zustand: 5.0.11(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + mipd: 0.0.7(typescript@5.9.2) + ox: 0.9.17(typescript@5.9.2)(zod@4.1.13) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zod: 4.1.13 + zustand: 5.0.3(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) optionalDependencies: - '@tanstack/react-query': 5.90.20(react@19.2.1) + '@tanstack/react-query': 5.90.11(react@19.2.1) react: 19.2.1 - typescript: 5.9.3 - wagmi: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) - transitivePeerDependencies: - - '@types/react' - - immer - - use-sync-external-store - - porto@0.2.19(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)): - dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - hono: 4.11.7 - idb-keyval: 6.2.2 - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zod: 4.3.6 - zustand: 5.0.11(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)) - optionalDependencies: - '@tanstack/react-query': 5.90.20(react@19.2.4) - react: 19.2.4 - typescript: 5.9.3 - wagmi: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) + typescript: 5.9.2 + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - '@types/react' - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)): dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - hono: 4.11.7 + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + hono: 4.10.7 idb-keyval: 6.2.2 - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zod: 4.3.6 - zustand: 5.0.11(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) + mipd: 0.0.7(typescript@5.9.2) + ox: 0.9.17(typescript@5.9.2)(zod@4.1.13) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + zod: 4.1.13 + zustand: 5.0.3(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)) optionalDependencies: - '@tanstack/react-query': 5.90.20(react@19.2.1) + '@tanstack/react-query': 5.90.11(react@19.2.1) react: 19.2.1 - typescript: 5.9.3 - wagmi: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) - transitivePeerDependencies: - - '@types/react' - - immer - - use-sync-external-store - - porto@0.2.35(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76)): - dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - hono: 4.11.7 - idb-keyval: 6.2.2 - mipd: 0.0.7(typescript@5.9.3) - ox: 0.9.17(typescript@5.9.3)(zod@4.3.6) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) - zod: 4.3.6 - zustand: 5.0.11(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)) - optionalDependencies: - '@tanstack/react-query': 5.90.20(react@19.2.4) - react: 19.2.4 - typescript: 5.9.3 - wagmi: 2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) + typescript: 5.9.2 + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) transitivePeerDependencies: - '@types/react' - immer @@ -16144,13 +17330,14 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0): + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(yaml@2.8.1): dependencies: lilconfig: 3.1.3 optionalDependencies: jiti: 2.6.1 postcss: 8.5.6 - tsx: 4.21.0 + tsx: 4.20.5 + yaml: 2.8.1 postcss@8.4.31: dependencies: @@ -16166,11 +17353,11 @@ snapshots: preact@10.24.2: {} - preact@10.28.3: {} + preact@10.27.2: {} prelude-ls@1.2.1: {} - prettier-linter-helpers@1.0.1: + prettier-linter-helpers@1.0.0: dependencies: fast-diff: 1.3.0 @@ -16217,6 +17404,10 @@ snapshots: pngjs: 5.0.0 yargs: 15.4.1 + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + qs@6.14.1: dependencies: side-channel: 1.1.0 @@ -16238,12 +17429,16 @@ snapshots: radix3@1.1.2: {} + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + range-parser@1.2.1: {} - raw-body@2.5.3: + raw-body@2.5.2: dependencies: bytes: 3.1.2 - http-errors: 2.0.1 + http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 @@ -16259,16 +17454,16 @@ snapshots: react: 19.2.1 scheduler: 0.27.0 - react-dom@19.2.4(react@19.2.4): + react-dom@19.2.3(react@19.2.3): dependencies: - react: 19.2.4 + react: 19.2.3 scheduler: 0.27.0 react-is@16.13.1: {} react@19.2.1: {} - react@19.2.4: {} + react@19.2.3: {} read-yaml-file@1.1.0: dependencies: @@ -16295,22 +17490,20 @@ snapshots: readdirp@4.1.2: {} - readdirp@5.0.0: {} - real-require@0.1.0: {} reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 get-proto: 1.0.1 which-builtin-type: 1.2.1 - regenerate-unicode-properties@10.2.2: + regenerate-unicode-properties@10.2.0: dependencies: regenerate: 1.4.2 @@ -16325,20 +17518,20 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 - regexpu-core@6.4.0: + regexpu-core@6.2.0: dependencies: regenerate: 1.4.2 - regenerate-unicode-properties: 10.2.2 + regenerate-unicode-properties: 10.2.0 regjsgen: 0.8.0 - regjsparser: 0.13.0 + regjsparser: 0.12.0 unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.2.1 + unicode-match-property-value-ecmascript: 2.2.0 regjsgen@0.8.0: {} - regjsparser@0.13.0: + regjsparser@0.12.0: dependencies: - jsesc: 3.1.0 + jsesc: 3.0.2 require-directory@2.1.1: {} @@ -16354,7 +17547,7 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.22.11: + resolve@1.22.10: dependencies: is-core-module: 2.16.1 path-parse: 1.0.7 @@ -16372,35 +17565,31 @@ snapshots: reusify@1.1.0: {} - rollup@4.57.1: + rollup@4.50.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.57.1 - '@rollup/rollup-android-arm64': 4.57.1 - '@rollup/rollup-darwin-arm64': 4.57.1 - '@rollup/rollup-darwin-x64': 4.57.1 - '@rollup/rollup-freebsd-arm64': 4.57.1 - '@rollup/rollup-freebsd-x64': 4.57.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 - '@rollup/rollup-linux-arm-musleabihf': 4.57.1 - '@rollup/rollup-linux-arm64-gnu': 4.57.1 - '@rollup/rollup-linux-arm64-musl': 4.57.1 - '@rollup/rollup-linux-loong64-gnu': 4.57.1 - '@rollup/rollup-linux-loong64-musl': 4.57.1 - '@rollup/rollup-linux-ppc64-gnu': 4.57.1 - '@rollup/rollup-linux-ppc64-musl': 4.57.1 - '@rollup/rollup-linux-riscv64-gnu': 4.57.1 - '@rollup/rollup-linux-riscv64-musl': 4.57.1 - '@rollup/rollup-linux-s390x-gnu': 4.57.1 - '@rollup/rollup-linux-x64-gnu': 4.57.1 - '@rollup/rollup-linux-x64-musl': 4.57.1 - '@rollup/rollup-openbsd-x64': 4.57.1 - '@rollup/rollup-openharmony-arm64': 4.57.1 - '@rollup/rollup-win32-arm64-msvc': 4.57.1 - '@rollup/rollup-win32-ia32-msvc': 4.57.1 - '@rollup/rollup-win32-x64-gnu': 4.57.1 - '@rollup/rollup-win32-x64-msvc': 4.57.1 + '@rollup/rollup-android-arm-eabi': 4.50.0 + '@rollup/rollup-android-arm64': 4.50.0 + '@rollup/rollup-darwin-arm64': 4.50.0 + '@rollup/rollup-darwin-x64': 4.50.0 + '@rollup/rollup-freebsd-arm64': 4.50.0 + '@rollup/rollup-freebsd-x64': 4.50.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.50.0 + '@rollup/rollup-linux-arm-musleabihf': 4.50.0 + '@rollup/rollup-linux-arm64-gnu': 4.50.0 + '@rollup/rollup-linux-arm64-musl': 4.50.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.50.0 + '@rollup/rollup-linux-ppc64-gnu': 4.50.0 + '@rollup/rollup-linux-riscv64-gnu': 4.50.0 + '@rollup/rollup-linux-riscv64-musl': 4.50.0 + '@rollup/rollup-linux-s390x-gnu': 4.50.0 + '@rollup/rollup-linux-x64-gnu': 4.50.0 + '@rollup/rollup-linux-x64-musl': 4.50.0 + '@rollup/rollup-openharmony-arm64': 4.50.0 + '@rollup/rollup-win32-arm64-msvc': 4.50.0 + '@rollup/rollup-win32-ia32-msvc': 4.50.0 + '@rollup/rollup-win32-x64-msvc': 4.50.0 fsevents: 2.3.3 router@2.2.0: @@ -16413,17 +17602,17 @@ snapshots: transitivePeerDependencies: - supports-color - rpc-websockets@9.3.3: + rpc-websockets@9.1.3: dependencies: - '@swc/helpers': 0.5.18 + '@swc/helpers': 0.5.17 '@types/uuid': 8.3.4 '@types/ws': 8.18.1 buffer: 6.0.3 - eventemitter3: 5.0.4 + eventemitter3: 5.0.1 uuid: 8.3.2 - ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: - bufferutil: 4.1.0 + bufferutil: 4.0.9 utf-8-validate: 5.0.10 rrweb-cssom@0.8.0: {} @@ -16467,23 +17656,25 @@ snapshots: semver@6.3.1: {} + semver@7.7.2: {} + semver@7.7.3: {} - send@0.19.2: + send@0.19.0: dependencies: debug: 2.6.9 depd: 2.0.0 destroy: 1.2.0 - encodeurl: 2.0.0 + encodeurl: 1.0.2 escape-html: 1.0.3 etag: 1.8.1 fresh: 0.5.2 - http-errors: 2.0.1 + http-errors: 2.0.0 mime: 1.6.0 ms: 2.1.3 on-finished: 2.4.1 range-parser: 1.2.1 - statuses: 2.0.2 + statuses: 2.0.1 transitivePeerDependencies: - supports-color @@ -16503,12 +17694,12 @@ snapshots: transitivePeerDependencies: - supports-color - serve-static@1.16.3: + serve-static@1.16.2: dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 0.19.2 + send: 0.19.0 transitivePeerDependencies: - supports-color @@ -16551,7 +17742,7 @@ snapshots: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 - to-buffer: 1.2.2 + to-buffer: 1.2.1 sharp@0.34.5: dependencies: @@ -16623,11 +17814,11 @@ snapshots: signal-exit@4.1.0: {} - siwe@2.3.2(ethers@6.16.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)): + siwe@2.3.2(ethers@6.16.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: '@spruceid/siwe-parser': 2.1.2 '@stablelib/random': 1.0.2 - ethers: 6.16.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + ethers: 6.16.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) uri-js: 4.4.1 valid-url: 1.0.9 @@ -16638,21 +17829,21 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 - socket.io-client@4.8.3(bufferutil@4.1.0)(utf-8-validate@5.0.10): + 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.4.3 - engine.io-client: 6.6.4(bufferutil@4.1.0)(utf-8-validate@5.0.10) - socket.io-parser: 4.2.5 + debug: 4.3.7 + engine.io-client: 6.6.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + socket.io-parser: 4.2.4 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-parser@4.2.5: + socket.io-parser@4.2.4: dependencies: '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3 + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -16662,7 +17853,9 @@ snapshots: source-map-js@1.2.1: {} - source-map@0.7.6: {} + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 spawndamnit@3.0.1: dependencies: @@ -16688,9 +17881,11 @@ snapshots: stackback@0.0.2: {} + statuses@2.0.1: {} + statuses@2.0.2: {} - std-env@3.10.0: {} + std-env@3.9.0: {} stop-iteration-iterator@1.1.0: dependencies: @@ -16713,18 +17908,24 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 @@ -16738,7 +17939,7 @@ snapshots: string.prototype.repeat@1.0.0: dependencies: define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 string.prototype.trim@1.2.10: dependencies: @@ -16746,7 +17947,7 @@ snapshots: call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 @@ -16775,29 +17976,33 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.2.0 + strip-bom@3.0.0: {} strip-json-comments@3.1.1: {} - strip-literal@3.1.0: + strip-literal@3.0.0: dependencies: js-tokens: 9.0.1 - styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.4): + styled-jsx@5.1.6(@babel/core@7.28.3)(react@19.2.3): dependencies: client-only: 0.0.1 - react: 19.2.4 + react: 19.2.3 optionalDependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.28.3 - sucrase@3.35.1: + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 + glob: 10.4.5 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 - tinyglobby: 0.2.15 ts-interface-checker: 0.1.13 superstruct@1.0.4: {} @@ -16824,13 +18029,13 @@ snapshots: symbol-tree@3.2.4: {} - synckit@0.11.12: + synckit@0.11.11: dependencies: '@pkgr/core': 0.2.9 - tailwind-merge@2.6.1: {} + tailwind-merge@2.6.0: {} - tailwindcss@4.1.18: {} + tailwindcss@4.1.17: {} tapable@2.3.0: {} @@ -16854,6 +18059,11 @@ snapshots: tinyexec@0.3.2: {} + tinyglobby@0.2.14: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -16863,15 +18073,23 @@ snapshots: tinyrainbow@2.0.0: {} - tinyspy@4.0.4: {} + tinyspy@4.0.3: {} tldts-core@6.1.86: {} + tldts-core@7.0.19: + optional: true + tldts@6.1.86: dependencies: tldts-core: 6.1.86 - to-buffer@1.2.2: + tldts@7.0.19: + dependencies: + tldts-core: 7.0.19 + optional: true + + to-buffer@1.2.1: dependencies: isarray: 2.0.5 safe-buffer: 5.2.1 @@ -16883,27 +18101,43 @@ snapshots: toidentifier@1.0.1: {} + toml@3.0.0: {} + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 + tough-cookie@6.0.0: + dependencies: + tldts: 7.0.19 + optional: true + tr46@0.0.3: {} + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + tr46@5.1.1: dependencies: punycode: 2.3.1 + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + optional: true + tree-kill@1.2.2: {} - ts-api-utils@2.4.0(typescript@5.9.3): + ts-api-utils@2.1.0(typescript@5.9.2): dependencies: - typescript: 5.9.3 + typescript: 5.9.2 ts-interface-checker@0.1.13: {} - tsconfck@3.1.6(typescript@5.9.3): + tsconfck@3.1.6(typescript@5.9.2): optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 tsconfig-paths@3.15.0: dependencies: @@ -16918,67 +18152,67 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3): + tsup@8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(typescript@5.9.2)(yaml@2.8.1): dependencies: - bundle-require: 5.1.0(esbuild@0.27.2) + bundle-require: 5.1.0(esbuild@0.25.9) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 - debug: 4.4.3 - esbuild: 0.27.2 + debug: 4.4.1 + esbuild: 0.25.9 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0) + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.5)(yaml@2.8.1) resolve-from: 5.0.0 - rollup: 4.57.1 - source-map: 0.7.6 - sucrase: 3.35.1 + rollup: 4.50.0 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 tinyexec: 0.3.2 - tinyglobby: 0.2.15 + tinyglobby: 0.2.14 tree-kill: 1.2.2 optionalDependencies: postcss: 8.5.6 - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - jiti - supports-color - tsx - yaml - tsx@4.21.0: + tsx@4.20.5: dependencies: - esbuild: 0.27.2 - get-tsconfig: 4.13.1 + esbuild: 0.25.9 + get-tsconfig: 4.10.1 optionalDependencies: fsevents: 2.3.3 - turbo-darwin-64@2.8.1: + turbo-darwin-64@2.5.6: optional: true - turbo-darwin-arm64@2.8.1: + turbo-darwin-arm64@2.5.6: optional: true - turbo-linux-64@2.8.1: + turbo-linux-64@2.5.6: optional: true - turbo-linux-arm64@2.8.1: + turbo-linux-arm64@2.5.6: optional: true - turbo-windows-64@2.8.1: + turbo-windows-64@2.5.6: optional: true - turbo-windows-arm64@2.8.1: + turbo-windows-arm64@2.5.6: optional: true - turbo@2.8.1: + turbo@2.5.6: optionalDependencies: - turbo-darwin-64: 2.8.1 - turbo-darwin-arm64: 2.8.1 - turbo-linux-64: 2.8.1 - turbo-linux-arm64: 2.8.1 - turbo-windows-64: 2.8.1 - turbo-windows-arm64: 2.8.1 + turbo-darwin-64: 2.5.6 + turbo-darwin-arm64: 2.5.6 + turbo-linux-64: 2.5.6 + turbo-linux-arm64: 2.5.6 + turbo-windows-64: 2.5.6 + turbo-windows-arm64: 2.5.6 tweetnacl@1.0.3: {} @@ -17030,20 +18264,20 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.2(jiti@2.6.1) - typescript: 5.9.3 + '@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.49.0(eslint@9.34.0(jiti@2.6.1))(typescript@5.9.2) + eslint: 9.34.0(jiti@2.6.1) + typescript: 5.9.2 transitivePeerDependencies: - supports-color - typescript@5.9.3: {} + typescript@5.9.2: {} - ufo@1.6.3: {} + ufo@1.6.1: {} uint8arrays@3.1.0: dependencies: @@ -17062,7 +18296,7 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.20.0: {} + undici-types@7.16.0: {} undici-types@7.22.0: {} @@ -17071,11 +18305,11 @@ snapshots: unicode-match-property-ecmascript@2.0.0: dependencies: unicode-canonical-property-names-ecmascript: 2.0.1 - unicode-property-aliases-ecmascript: 2.2.0 + unicode-property-aliases-ecmascript: 2.1.0 - unicode-match-property-value-ecmascript@2.2.1: {} + unicode-match-property-value-ecmascript@2.2.0: {} - unicode-property-aliases-ecmascript@2.2.0: {} + unicode-property-aliases-ecmascript@2.1.0: {} universalify@0.1.2: {} @@ -17083,7 +18317,7 @@ snapshots: unrs-resolver@1.11.1: dependencies: - napi-postinstall: 0.3.4 + napi-postinstall: 0.3.3 optionalDependencies: '@unrs/resolver-binding-android-arm-eabi': 1.11.1 '@unrs/resolver-binding-android-arm64': 1.11.1 @@ -17105,23 +18339,23 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - unstorage@1.17.4(@vercel/functions@2.2.13)(idb-keyval@6.2.2): + unstorage@1.17.0(@vercel/functions@2.2.13)(idb-keyval@6.2.2): dependencies: anymatch: 3.1.3 - chokidar: 5.0.0 + chokidar: 4.0.3 destr: 2.0.5 - h3: 1.15.5 - lru-cache: 11.2.5 + h3: 1.15.4 + lru-cache: 10.4.3 node-fetch-native: 1.6.7 - ofetch: 1.5.1 - ufo: 1.6.3 + ofetch: 1.4.1 + ufo: 1.6.1 optionalDependencies: '@vercel/functions': 2.2.13 idb-keyval: 6.2.2 - update-browserslist-db@1.2.3(browserslist@4.28.1): + update-browserslist-db@1.1.3(browserslist@4.25.4): dependencies: - browserslist: 4.28.1 + browserslist: 4.25.4 escalade: 3.2.0 picocolors: 1.1.1 @@ -17129,21 +18363,23 @@ snapshots: dependencies: punycode: 2.3.1 + urijs@1.19.11: {} + use-sync-external-store@1.2.0(react@19.2.1): dependencies: react: 19.2.1 - use-sync-external-store@1.2.0(react@19.2.4): + use-sync-external-store@1.2.0(react@19.2.3): dependencies: - react: 19.2.4 + react: 19.2.3 use-sync-external-store@1.4.0(react@19.2.1): dependencies: react: 19.2.1 - use-sync-external-store@1.4.0(react@19.2.4): + use-sync-external-store@1.4.0(react@19.2.3): dependencies: - react: 19.2.4 + react: 19.2.3 utf-8-validate@5.0.10: dependencies: @@ -17155,9 +18391,9 @@ snapshots: dependencies: inherits: 2.0.4 is-arguments: 1.2.0 - is-generator-function: 1.1.2 + is-generator-function: 1.1.0 is-typed-array: 1.1.15 - which-typed-array: 1.1.20 + which-typed-array: 1.1.19 utils-merge@1.0.1: {} @@ -17167,84 +18403,118 @@ snapshots: valid-url@1.0.9: {} - valtio@1.13.2(@types/react@19.2.10)(react@19.2.1): + valtio@1.13.2(@types/react@19.1.12)(react@19.2.1): dependencies: - derive-valtio: 0.1.0(valtio@1.13.2(@types/react@19.2.10)(react@19.2.1)) + derive-valtio: 0.1.0(valtio@1.13.2(@types/react@19.1.12)(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.10 + '@types/react': 19.1.12 react: 19.2.1 - valtio@1.13.2(@types/react@19.2.10)(react@19.2.4): + valtio@1.13.2(@types/react@19.1.12)(react@19.2.3): dependencies: - derive-valtio: 0.1.0(valtio@1.13.2(@types/react@19.2.10)(react@19.2.4)) + derive-valtio: 0.1.0(valtio@1.13.2(@types/react@19.1.12)(react@19.2.3)) proxy-compare: 2.6.0 - use-sync-external-store: 1.2.0(react@19.2.4) + use-sync-external-store: 1.2.0(react@19.2.3) optionalDependencies: - '@types/react': 19.2.10 - react: 19.2.4 + '@types/react': 19.1.12 + react: 19.2.3 vary@1.1.2: {} - viem@2.23.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76): + viem@2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76): dependencies: '@noble/curves': 1.8.1 '@noble/hashes': 1.7.1 '@scure/bip32': 1.6.2 '@scure/bip39': 1.5.4 - abitype: 1.0.8(typescript@5.9.3)(zod@3.25.76) - isows: 1.0.6(ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10)) - ox: 0.6.7(typescript@5.9.3)(zod@3.25.76) - ws: 8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + abitype: 1.0.8(typescript@5.9.2)(zod@3.25.76) + isows: 1.0.6(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.6.7(typescript@5.9.2)(zod@3.25.76) + ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.0(typescript@5.9.2)(zod@3.25.76) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.9.3(typescript@5.9.2)(zod@3.25.76) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76): + dependencies: + '@noble/curves': 1.9.1 + '@noble/hashes': 1.8.0 + '@scure/bip32': 1.7.0 + '@scure/bip39': 1.6.0 + abitype: 1.1.0(typescript@5.9.2)(zod@3.25.76) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.9.6(typescript@5.9.2)(zod@3.25.76) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - bufferutil - utf-8-validate - zod - viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.22.4): + viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(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.2.3(typescript@5.9.3)(zod@3.22.4) - isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10)) - ox: 0.11.3(typescript@5.9.3)(zod@3.22.4) - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10) + abitype: 1.2.3(typescript@5.9.2)(zod@3.22.4) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.11.3(typescript@5.9.2)(zod@3.22.4) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - bufferutil - utf-8-validate - zod - viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76): + viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76): dependencies: '@noble/curves': 1.9.1 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) - isows: 1.0.7(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10)) - ox: 0.11.3(typescript@5.9.3)(zod@3.25.76) - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10) + abitype: 1.2.3(typescript@5.9.2)(zod@3.25.76) + isows: 1.0.7(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + ox: 0.11.3(typescript@5.9.2)(zod@3.25.76) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - bufferutil - utf-8-validate - zod - vite-node@3.2.4(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0): + vite-node@3.2.4(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1): dependencies: cac: 6.7.14 - debug: 4.4.3 + debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + vite: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -17259,61 +18529,62 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)): + vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1)): dependencies: - debug: 4.4.3 + debug: 4.4.1 globrex: 0.1.2 - tsconfck: 3.1.6(typescript@5.9.3) + tsconfck: 3.1.6(typescript@5.9.2) optionalDependencies: - vite: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + vite: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) transitivePeerDependencies: - supports-color - typescript - vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0): + vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1): dependencies: - esbuild: 0.25.12 + esbuild: 0.25.9 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.57.1 - tinyglobby: 0.2.15 + rollup: 4.50.0 + tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 22.19.7 + '@types/node': 22.18.0 fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 - tsx: 4.21.0 + tsx: 4.20.5 + yaml: 2.8.1 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.21.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.0)(jiti@2.6.1)(jsdom@27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1): dependencies: - '@types/chai': 5.2.3 + '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(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.3.3 - debug: 4.4.3 - expect-type: 1.3.0 - magic-string: 0.30.21 + debug: 4.4.1 + expect-type: 1.2.2 + magic-string: 0.30.18 pathe: 2.0.3 picomatch: 4.0.3 - std-env: 3.10.0 + std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.15 + tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) - vite-node: 3.2.4(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) + vite: 6.3.5(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@22.18.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.5)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 22.19.7 - jsdom: 26.1.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + '@types/node': 22.18.0 + jsdom: 27.4.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) transitivePeerDependencies: - jiti - less @@ -17332,16 +18603,55 @@ snapshots: dependencies: xml-name-validator: 5.0.0 - wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76): + wagmi@2.16.9(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76): + dependencies: + '@tanstack/react-query': 5.90.11(react@19.2.3) + '@wagmi/connectors': 5.9.9(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76) + '@wagmi/core': 2.20.3(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + react: 19.2.3 + use-sync-external-store: 1.4.0(react@19.2.3) + viem: 2.37.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + optionalDependencies: + typescript: 5.9.2 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@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.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76): dependencies: - '@tanstack/react-query': 5.90.20(react@19.2.1) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.1))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@tanstack/react-query': 5.90.11(react@19.2.1) + '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(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.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -17377,16 +18687,16 @@ snapshots: - utf-8-validate - zod - wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76): dependencies: - '@tanstack/react-query': 5.90.20(react@19.2.4) - '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.20)(@tanstack/react-query@5.90.20(react@19.2.4))(@types/react@19.2.10)(@vercel/functions@2.2.13)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.4)(typescript@5.9.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.20)(@types/react@19.2.10)(react@19.2.4)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@19.2.4))(viem@2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76)) - react: 19.2.4 - use-sync-external-store: 1.4.0(react@19.2.4) - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@tanstack/react-query': 5.90.11(react@19.2.1) + '@wagmi/connectors': 6.2.0(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.1))(@types/react@19.1.12)(@vercel/functions@2.2.13)(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.1)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(zod@3.25.76))(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.12)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.1))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + react: 19.2.1 + use-sync-external-store: 1.4.0(react@19.2.1) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: - typescript: 5.9.3 + typescript: 5.9.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -17426,8 +18736,13 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@4.0.2: {} + webidl-conversions@7.0.0: {} + webidl-conversions@8.0.1: + optional: true + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 @@ -17439,11 +18754,23 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 + whatwg-url@15.1.0: + dependencies: + tr46: 6.0.0 + webidl-conversions: 8.0.1 + optional: true + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -17460,13 +18787,13 @@ snapshots: is-async-function: 2.1.1 is-date-object: 1.1.0 is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.2 + is-generator-function: 1.1.0 is-regex: 1.2.1 is-weakref: 1.1.1 isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 - which-typed-array: 1.1.20 + which-typed-array: 1.1.19 which-collection@1.0.2: dependencies: @@ -17477,7 +18804,7 @@ snapshots: which-module@2.0.1: {} - which-typed-array@1.1.20: + which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 @@ -17504,40 +18831,52 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} - ws@7.5.10(bufferutil@4.1.0)(utf-8-validate@5.0.10): + ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10): optionalDependencies: - bufferutil: 4.1.0 + bufferutil: 4.0.9 utf-8-validate: 5.0.10 - ws@8.17.1(bufferutil@4.1.0)(utf-8-validate@5.0.10): + ws@8.17.1(bufferutil@4.0.9)(utf-8-validate@5.0.10): optionalDependencies: - bufferutil: 4.1.0 + bufferutil: 4.0.9 utf-8-validate: 5.0.10 - ws@8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): optionalDependencies: - bufferutil: 4.1.0 + bufferutil: 4.0.9 utf-8-validate: 5.0.10 - ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@5.0.10): + ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10): optionalDependencies: - bufferutil: 4.1.0 + bufferutil: 4.0.9 utf-8-validate: 5.0.10 - ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10): optionalDependencies: - bufferutil: 4.1.0 + bufferutil: 4.0.9 utf-8-validate: 5.0.10 - x402@0.1.2(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10): + x402@0.1.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10): dependencies: - '@hono/node-server': 1.19.9(hono@4.11.7) - axios: 1.13.4 - express: 4.22.1 - hono: 4.11.7 - viem: 2.45.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10)(zod@3.25.76) + '@hono/node-server': 1.19.1(hono@4.10.7) + axios: 1.11.0 + express: 4.21.2 + hono: 4.10.7 + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zod: 3.25.76 transitivePeerDependencies: - bufferutil @@ -17558,6 +18897,9 @@ snapshots: yallist@3.1.1: {} + yaml@2.8.1: + optional: true + yargs-parser@18.1.3: dependencies: camelcase: 5.3.1 @@ -17591,40 +18933,28 @@ snapshots: zod@3.25.76: {} - zod@4.3.6: {} - - zustand@5.0.0(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): - optionalDependencies: - '@types/react': 19.2.10 - react: 19.2.1 - use-sync-external-store: 1.4.0(react@19.2.1) - - zustand@5.0.0(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)): - optionalDependencies: - '@types/react': 19.2.10 - react: 19.2.4 - use-sync-external-store: 1.4.0(react@19.2.4) + zod@4.1.13: {} - zustand@5.0.11(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): + zustand@5.0.0(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): optionalDependencies: - '@types/react': 19.2.10 + '@types/react': 19.1.12 react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) - zustand@5.0.11(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)): + zustand@5.0.0(@types/react@19.1.12)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): optionalDependencies: - '@types/react': 19.2.10 - react: 19.2.4 - use-sync-external-store: 1.4.0(react@19.2.4) + '@types/react': 19.1.12 + react: 19.2.3 + use-sync-external-store: 1.4.0(react@19.2.3) - zustand@5.0.3(@types/react@19.2.10)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): + zustand@5.0.3(@types/react@19.1.12)(react@19.2.1)(use-sync-external-store@1.4.0(react@19.2.1)): optionalDependencies: - '@types/react': 19.2.10 + '@types/react': 19.1.12 react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) - zustand@5.0.3(@types/react@19.2.10)(react@19.2.4)(use-sync-external-store@1.4.0(react@19.2.4)): + zustand@5.0.3(@types/react@19.1.12)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): optionalDependencies: - '@types/react': 19.2.10 - react: 19.2.4 - use-sync-external-store: 1.4.0(react@19.2.4) + '@types/react': 19.1.12 + react: 19.2.3 + use-sync-external-store: 1.4.0(react@19.2.3) From aeef1bff6694099922c8df5b6e943b894433718b Mon Sep 17 00:00:00 2001 From: phdargen Date: Thu, 5 Mar 2026 09:46:39 +0900 Subject: [PATCH 024/129] Custom settlement failures responses (#1430) * py fix for 1176 * fix settle response body * same for go/py * fix format --- e2e/clients/mcp-go/go.mod | 8 ++ e2e/clients/mcp-go/go.sum | 111 +++++++++++++++ e2e/clients/mcp-python/uv.lock | 4 +- e2e/servers/mcp-python/uv.lock | 4 +- examples/go/clients/advanced/all_networks.go | 8 +- .../go/clients/advanced/custom_transport.go | 6 +- .../go/clients/advanced/error_recovery.go | 6 +- examples/go/clients/advanced/hooks.go | 6 +- .../advanced/multi_network_priority.go | 6 +- examples/go/clients/custom/main.go | 47 ++++-- examples/go/clients/http/main.go | 8 +- .../go/clients/payment-identifier/main.go | 51 +++++-- .../python/clients/advanced/all_networks.py | 19 +-- .../clients/advanced/builder_pattern.py | 18 ++- examples/python/clients/advanced/hooks.py | 18 ++- .../clients/advanced/preferred_network.py | 18 ++- examples/python/clients/httpx/main.py | 19 +-- examples/python/clients/httpx/uv.lock | 4 +- .../python/clients/payment-identifier/main.py | 31 ++-- examples/python/clients/requests/main.py | 19 +-- examples/python/clients/requests/uv.lock | 4 +- .../clients/advanced/all_networks.ts | 13 +- .../clients/advanced/builder-pattern.ts | 12 +- examples/typescript/clients/axios/index.ts | 12 +- examples/typescript/clients/fetch/index.ts | 12 +- .../clients/payment-identifier/index.ts | 28 ++-- .../clients/sign-in-with-x/index.ts | 4 +- go/http/gin/middleware.go | 23 +-- go/http/gin/middleware_test.go | 17 ++- go/http/server.go | 64 +++++++-- go/http/server_test.go | 53 +++++++ python/x402/changelog.d/1430.bugfix.md | 1 + python/x402/http/__init__.py | 6 +- python/x402/http/middleware/fastapi.py | 31 ++-- python/x402/http/middleware/flask.py | 47 +++--- python/x402/http/types.py | 14 +- python/x402/http/x402_http_server.py | 88 +++++++++++- python/x402/http/x402_http_server_base.py | 92 +++++++++++- python/x402/schemas/responses.py | 4 + .../unit/http/middleware/test_fastapi.py | 134 +++++++++++++++++- .../tests/unit/http/middleware/test_flask.py | 14 +- specs/transports-v2/http.md | 22 ++- typescript/.changeset/bold-mice-sink.md | 8 ++ typescript/packages/core/src/http/index.ts | 3 +- .../core/src/http/x402HTTPResourceServer.ts | 77 ++++++++-- typescript/packages/core/src/server/index.ts | 3 +- .../mocks/generic/MockFacilitatorClient.ts | 18 ++- .../packages/http/express/src/index.test.ts | 25 ++-- typescript/packages/http/express/src/index.ts | 17 ++- .../packages/http/hono/src/index.test.ts | 33 +++-- typescript/packages/http/hono/src/index.ts | 24 ++-- .../packages/http/next/src/index.test.ts | 33 ++++- .../packages/http/next/src/utils.test.ts | 18 ++- typescript/packages/http/next/src/utils.ts | 30 ++-- 54 files changed, 1041 insertions(+), 354 deletions(-) create mode 100644 python/x402/changelog.d/1430.bugfix.md create mode 100644 typescript/.changeset/bold-mice-sink.md diff --git a/e2e/clients/mcp-go/go.mod b/e2e/clients/mcp-go/go.mod index c439a05d14..e52c71c235 100644 --- a/e2e/clients/mcp-go/go.mod +++ b/e2e/clients/mcp-go/go.mod @@ -10,18 +10,26 @@ require ( ) require ( + 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/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/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-ethereum v1.16.7 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/google/jsonschema-go v0.4.2 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/holiman/uint256 v1.3.2 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // 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/yosida95/uritemplate/v3 v3.0.2 // indirect golang.org/x/crypto v0.41.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect diff --git a/e2e/clients/mcp-go/go.sum b/e2e/clients/mcp-go/go.sum index f897f19fa1..4bb7ac5577 100644 --- a/e2e/clients/mcp-go/go.sum +++ b/e2e/clients/mcp-go/go.sum @@ -1,17 +1,45 @@ +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/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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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.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= @@ -20,18 +48,29 @@ 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/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY= github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= +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/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/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-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 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.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -40,50 +79,122 @@ 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/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8= github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +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/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.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/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/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.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/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= 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/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/modelcontextprotocol/go-sdk v1.3.0 h1:gMfZkv3DzQF5q/DcQePo5rahEY+sguyPfXDfNBcT0Zs= github.com/modelcontextprotocol/go-sdk v1.3.0/go.mod h1:AnQ//Qc6+4nIyyrB4cxBU7UW9VibK4iOZBeyP/rF1IE= 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/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.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.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= +github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= 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/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/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/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/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/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= 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-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.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/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.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/e2e/clients/mcp-python/uv.lock b/e2e/clients/mcp-python/uv.lock index a1964f57e4..84907b68f1 100644 --- a/e2e/clients/mcp-python/uv.lock +++ b/e2e/clients/mcp-python/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -2137,7 +2137,7 @@ wheels = [ [[package]] name = "x402" -version = "2.1.0" +version = "2.2.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/servers/mcp-python/uv.lock b/e2e/servers/mcp-python/uv.lock index 31abc9061e..0ca9a78b4d 100644 --- a/e2e/servers/mcp-python/uv.lock +++ b/e2e/servers/mcp-python/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -2137,7 +2137,7 @@ wheels = [ [[package]] name = "x402" -version = "2.1.0" +version = "2.2.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/examples/go/clients/advanced/all_networks.go b/examples/go/clients/advanced/all_networks.go index be399f1bd0..b4b508702c 100644 --- a/examples/go/clients/advanced/all_networks.go +++ b/examples/go/clients/advanced/all_networks.go @@ -106,7 +106,13 @@ func printPaymentDetails(headers http.Header) { } fmt.Println("πŸ’° Payment Details:") - fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + fmt.Printf(" Success: %v\n", settleResp.Success) + if settleResp.ErrorReason != "" { + fmt.Printf(" ErrorReason: %s\n", settleResp.ErrorReason) + } + if settleResp.Transaction != "" { + fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + } fmt.Printf(" Network: %s\n", settleResp.Network) fmt.Printf(" Payer: %s\n", settleResp.Payer) } diff --git a/examples/go/clients/advanced/custom_transport.go b/examples/go/clients/advanced/custom_transport.go index 7b8ee4c2c9..1ecf3a9bad 100644 --- a/examples/go/clients/advanced/custom_transport.go +++ b/examples/go/clients/advanced/custom_transport.go @@ -135,6 +135,10 @@ func runCustomTransportExample(ctx context.Context, evmPrivateKey, url string) e } defer resp.Body.Close() - return printResponse(resp, "Response with custom transport") + if err := printResponse(resp, "Response with custom transport"); err != nil { + return err + } + printPaymentDetails(resp.Header) + return nil } diff --git a/examples/go/clients/advanced/error_recovery.go b/examples/go/clients/advanced/error_recovery.go index b4ad618f2e..befc8fb3ed 100644 --- a/examples/go/clients/advanced/error_recovery.go +++ b/examples/go/clients/advanced/error_recovery.go @@ -122,7 +122,11 @@ func runErrorRecoveryExample(ctx context.Context, evmPrivateKey, url string) err fmt.Printf(" Successful recoveries: %d\n", successfulRecoveries) fmt.Printf(" Final status: %d\n\n", resp.StatusCode) - return printResponse(resp, "Response after error recovery") + if err := printResponse(resp, "Response after error recovery"); err != nil { + return err + } + printPaymentDetails(resp.Header) + return nil } // classifyError categorizes errors for targeted recovery strategies diff --git a/examples/go/clients/advanced/hooks.go b/examples/go/clients/advanced/hooks.go index d4a0c7e8e0..1026cebb22 100644 --- a/examples/go/clients/advanced/hooks.go +++ b/examples/go/clients/advanced/hooks.go @@ -107,6 +107,10 @@ func runHooksExample(ctx context.Context, evmPrivateKey, url string) error { fmt.Println("βœ… Request completed successfully with hooks\n") - return printResponse(resp, "Response with hooks") + if err := printResponse(resp, "Response with hooks"); err != nil { + return err + } + printPaymentDetails(resp.Header) + return nil } diff --git a/examples/go/clients/advanced/multi_network_priority.go b/examples/go/clients/advanced/multi_network_priority.go index b3cb6e1c3d..3eb32b9772 100644 --- a/examples/go/clients/advanced/multi_network_priority.go +++ b/examples/go/clients/advanced/multi_network_priority.go @@ -111,6 +111,10 @@ func runMultiNetworkPriorityExample(ctx context.Context, evmPrivateKey, url stri 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") + if err := printResponse(resp, "Response with multi-network priority"); err != nil { + return err + } + printPaymentDetails(resp.Header) + return nil } diff --git a/examples/go/clients/custom/main.go b/examples/go/clients/custom/main.go index ee28bf4510..8181a23f13 100644 --- a/examples/go/clients/custom/main.go +++ b/examples/go/clients/custom/main.go @@ -74,13 +74,18 @@ func main() { // Make the request with custom payment handling fmt.Println("πŸ”§ Using custom payment implementation (no wrapper)\n") - + resp, err := makeRequestWithPayment(ctx, x402Client, url) + if resp != nil { + defer resp.Body.Close() + } if err != nil { fmt.Printf("❌ Request failed: %v\n", err) + if resp != nil { + displayPaymentDetails(resp) + } os.Exit(1) } - defer resp.Body.Close() // Read and display response var responseData interface{} @@ -93,16 +98,33 @@ func main() { 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) - } + displayPaymentDetails(resp) +} + +// displayPaymentDetails extracts and prints payment settlement from response headers. +// Payment-response header is sent on both success and error. +func displayPaymentDetails(resp *http.Response) { + paymentHeader := resp.Header.Get("PAYMENT-RESPONSE") + if paymentHeader == "" { + paymentHeader = resp.Header.Get("X-PAYMENT-RESPONSE") + } + if paymentHeader == "" { + return + } + settleResp, err := extractSettlementResponse(paymentHeader) + if err != nil { + return + } + fmt.Println("\nπŸ’° Payment Settlement Details:") + fmt.Printf(" Success: %v\n", settleResp.Success) + if settleResp.ErrorReason != "" { + fmt.Printf(" ErrorReason: %s\n", settleResp.ErrorReason) + } + if settleResp.Transaction != "" { + 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 @@ -247,9 +269,8 @@ func makeRequestWithPayment(ctx context.Context, x402Client *x402.X402Client, ur // 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)) + return retryResp, fmt.Errorf("payment failed: status %d, body: %s", retryResp.StatusCode, string(errorBody)) } fmt.Println("βœ… Step 6: Payment successful!\n") diff --git a/examples/go/clients/http/main.go b/examples/go/clients/http/main.go index 8eab6c3446..5adbbad5f1 100644 --- a/examples/go/clients/http/main.go +++ b/examples/go/clients/http/main.go @@ -121,7 +121,13 @@ func makeRequest(client *x402.X402Client, url string) error { fmt.Println("\nπŸ’° Payment Details:") settleResp, err := extractPaymentResponse(resp.Header) if err == nil { - fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + fmt.Printf(" Success: %v\n", settleResp.Success) + if settleResp.ErrorReason != "" { + fmt.Printf(" ErrorReason: %s\n", settleResp.ErrorReason) + } + if settleResp.Transaction != "" { + fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + } fmt.Printf(" Network: %s\n", settleResp.Network) fmt.Printf(" Payer: %s\n", settleResp.Payer) } diff --git a/examples/go/clients/payment-identifier/main.go b/examples/go/clients/payment-identifier/main.go index 53121fd870..602df521a7 100644 --- a/examples/go/clients/payment-identifier/main.go +++ b/examples/go/clients/payment-identifier/main.go @@ -169,27 +169,29 @@ func main() { fmt.Printf("Making request to: %s\n\n", serverURL) startTime1 := time.Now() - resp1, err := makeRequest(ctx, wrappedClient, serverURL) + resp1, httpResp1, err := makeRequest(ctx, wrappedClient, serverURL) duration1 := time.Since(startTime1) if err != nil { fmt.Printf("Request failed: %v\n", err) os.Exit(1) } - fmt.Printf("Response (%v): %s\n\n", duration1, resp1) + fmt.Printf("Response (%v): %s\n", duration1, resp1) + printPaymentDetails(httpResp1) // Second request - replay the same signed payment (true retry) - fmt.Println("Second Request (retry with cached payment)") + fmt.Println("\nSecond Request (retry with cached payment)") fmt.Printf("Making request to: %s\n", serverURL) fmt.Println("Expected: Server returns cached response (same ID, same payload)") startTime2 := time.Now() - resp2, err := makeRequest(ctx, wrappedClient, serverURL) + resp2, httpResp2, err := makeRequest(ctx, wrappedClient, serverURL) duration2 := time.Since(startTime2) if err != nil { fmt.Printf("Request failed: %v\n", err) os.Exit(1) } - fmt.Printf("Response (%v): %s\n\n", duration2, resp2) + fmt.Printf("Response (%v): %s\n", duration2, resp2) + printPaymentDetails(httpResp2) // Summary fmt.Println("Summary") @@ -198,23 +200,52 @@ func main() { fmt.Printf(" Second request: %v\n", duration2) } -func makeRequest(ctx context.Context, client *http.Client, url string) (string, error) { +func makeRequest(ctx context.Context, client *http.Client, url string) (string, *http.Response, error) { req, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(`{"item": "widget"}`)) if err != nil { - return "", err + return "", nil, err } req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { - return "", err + return "", nil, err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { - return "", err + return "", resp, err } - return string(body), nil + return string(body), resp, nil +} + +// printPaymentDetails extracts and prints payment settlement from response headers. +func printPaymentDetails(resp *http.Response) { + paymentHeader := resp.Header.Get("PAYMENT-RESPONSE") + if paymentHeader == "" { + paymentHeader = resp.Header.Get("X-PAYMENT-RESPONSE") + } + if paymentHeader == "" { + return + } + decoded, err := base64.StdEncoding.DecodeString(paymentHeader) + if err != nil { + return + } + var settleResp x402.SettleResponse + if err := json.Unmarshal(decoded, &settleResp); err != nil { + return + } + fmt.Println("πŸ’° Payment Details:") + fmt.Printf(" Success: %v\n", settleResp.Success) + if settleResp.ErrorReason != "" { + fmt.Printf(" ErrorReason: %s\n", settleResp.ErrorReason) + } + if settleResp.Transaction != "" { + fmt.Printf(" Transaction: %s\n", settleResp.Transaction) + } + fmt.Printf(" Network: %s\n", settleResp.Network) + fmt.Printf(" Payer: %s\n", settleResp.Payer) } diff --git a/examples/python/clients/advanced/all_networks.py b/examples/python/clients/advanced/all_networks.py index 0305161e72..fa4158d010 100644 --- a/examples/python/clients/advanced/all_networks.py +++ b/examples/python/clients/advanced/all_networks.py @@ -93,18 +93,13 @@ async def main() -> None: print(f"Response body: {response.text}") # Extract and print payment response if present - if response.is_success: - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response.headers.get(name) - ) - print( - f"\nPayment response: {settle_response.model_dump_json(indent=2)}" - ) - except ValueError: - print("\nNo payment response header found") - else: - print(f"\nRequest failed (status: {response.status_code})") + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response.headers.get(name) + ) + print(f"\nPayment response: {settle_response.model_dump_json(indent=2)}") + except ValueError: + print("\nNo payment response header found") if __name__ == "__main__": diff --git a/examples/python/clients/advanced/builder_pattern.py b/examples/python/clients/advanced/builder_pattern.py index 80290c7184..88de409ce9 100644 --- a/examples/python/clients/advanced/builder_pattern.py +++ b/examples/python/clients/advanced/builder_pattern.py @@ -92,16 +92,14 @@ async def run_builder_pattern_example( print(f"Response status: {response.status_code}") print(f"Response body: {response.text}") - if response.is_success: - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response.headers.get(name) - ) - print( - f"\nπŸ’° Payment Details: {settle_response.model_dump_json(indent=2)}" - ) - except ValueError: - print("\nNo payment response header found") + # Extract and print payment response if present + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response.headers.get(name) + ) + print(f"\nπŸ’° Payment Details: {settle_response.model_dump_json(indent=2)}") + except ValueError: + print("\nNo payment response header found") async def main() -> None: diff --git a/examples/python/clients/advanced/hooks.py b/examples/python/clients/advanced/hooks.py index 633c1c2658..1ce5a73bd4 100644 --- a/examples/python/clients/advanced/hooks.py +++ b/examples/python/clients/advanced/hooks.py @@ -122,16 +122,14 @@ async def run_hooks_example(private_key: str, url: str) -> None: print(f"Response status: {response.status_code}") print(f"Response body: {response.text}") - if response.is_success: - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response.headers.get(name) - ) - print( - f"\nπŸ’° Payment Details: {settle_response.model_dump_json(indent=2)}" - ) - except ValueError: - print("\nNo payment response header found") + # Extract and print payment response if present + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response.headers.get(name) + ) + print(f"\nπŸ’° Payment Details: {settle_response.model_dump_json(indent=2)}") + except ValueError: + print("\nNo payment response header found") async def main() -> None: diff --git a/examples/python/clients/advanced/preferred_network.py b/examples/python/clients/advanced/preferred_network.py index 3cb7a42471..498aef00ac 100644 --- a/examples/python/clients/advanced/preferred_network.py +++ b/examples/python/clients/advanced/preferred_network.py @@ -129,16 +129,14 @@ async def run_preferred_network_example( print(f"\nResponse status: {response.status_code}") print(f"Response body: {response.text}") - if response.is_success: - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response.headers.get(name) - ) - print( - f"\nπŸ’° Payment Details: {settle_response.model_dump_json(indent=2)}" - ) - except ValueError: - print("\nNo payment response header found") + # Extract and print payment response if present + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response.headers.get(name) + ) + print(f"\nπŸ’° Payment Details: {settle_response.model_dump_json(indent=2)}") + except ValueError: + print("\nNo payment response header found") async def main() -> None: diff --git a/examples/python/clients/httpx/main.py b/examples/python/clients/httpx/main.py index b8e8ad0aaf..d0a6c26099 100644 --- a/examples/python/clients/httpx/main.py +++ b/examples/python/clients/httpx/main.py @@ -85,18 +85,13 @@ async def main() -> None: print(f"Response body: {response.text}") # Extract and print payment response if present - if response.is_success: - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response.headers.get(name) - ) - print( - f"\nPayment response: {settle_response.model_dump_json(indent=2)}" - ) - except ValueError: - print("\nNo payment response header found") - else: - print(f"\nRequest failed (status: {response.status_code})") + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response.headers.get(name) + ) + print(f"\nPayment response: {settle_response.model_dump_json(indent=2)}") + except ValueError: + print("\nNo payment response header found") if __name__ == "__main__": diff --git a/examples/python/clients/httpx/uv.lock b/examples/python/clients/httpx/uv.lock index 8316ef3fec..b5b3fbfc6b 100644 --- a/examples/python/clients/httpx/uv.lock +++ b/examples/python/clients/httpx/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -1744,7 +1744,7 @@ wheels = [ [[package]] name = "x402" -version = "2.1.0" +version = "2.2.0" source = { editable = "../../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/examples/python/clients/payment-identifier/main.py b/examples/python/clients/payment-identifier/main.py index 8de03d540a..a7238d45fc 100644 --- a/examples/python/clients/payment-identifier/main.py +++ b/examples/python/clients/payment-identifier/main.py @@ -82,14 +82,14 @@ async def before_payment_creation(context: PaymentCreationContext) -> None: print(f"Response ({duration1}ms): {response1.text}") - if response1.is_success: - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response1.headers.get(name) - ) - print(f"\nPayment settled on {settle_response.network}") - except ValueError: - pass + # Extract and print payment response if present + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response1.headers.get(name) + ) + print(f"\nPayment response: {settle_response.model_dump_json(indent=2)}") + except ValueError: + pass # Second request - same payment ID, should return from cache print("\n" + "=" * 52) @@ -105,14 +105,13 @@ async def before_payment_creation(context: PaymentCreationContext) -> None: print(f"Response ({duration2}ms): {response2.text}") - if response2.is_success: - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response2.headers.get(name) - ) - print("\nPayment settled (unexpected - should have been cached)") - except ValueError: - print("\nNo payment processed - response served from cache!") + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response2.headers.get(name) + ) + print(f"\nPayment response: {settle_response.model_dump_json(indent=2)}") + except ValueError: + print("\nNo payment processed - response served from cache!") # Summary print("\n" + "=" * 52) diff --git a/examples/python/clients/requests/main.py b/examples/python/clients/requests/main.py index 9447f15d8a..f3e88758ce 100644 --- a/examples/python/clients/requests/main.py +++ b/examples/python/clients/requests/main.py @@ -83,18 +83,13 @@ def main() -> None: print(f"Response body: {response.text}") # Extract and print payment response if present - if response.ok: # requests uses .ok - try: - settle_response = http_client.get_payment_settle_response( - lambda name: response.headers.get(name) - ) - print( - f"\nPayment response: {settle_response.model_dump_json(indent=2)}" - ) - except ValueError: - print("\nNo payment response header found") - else: - print(f"\nRequest failed (status: {response.status_code})") + try: + settle_response = http_client.get_payment_settle_response( + lambda name: response.headers.get(name) + ) + print(f"\nPayment response: {settle_response.model_dump_json(indent=2)}") + except ValueError: + print("\nNo payment response header found") if __name__ == "__main__": diff --git a/examples/python/clients/requests/uv.lock b/examples/python/clients/requests/uv.lock index 674ea277a6..0a7f7621cc 100644 --- a/examples/python/clients/requests/uv.lock +++ b/examples/python/clients/requests/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -1744,7 +1744,7 @@ wheels = [ [[package]] name = "x402" -version = "2.1.0" +version = "2.2.0" source = { editable = "../../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/examples/typescript/clients/advanced/all_networks.ts b/examples/typescript/clients/advanced/all_networks.ts index 61620e2c72..01c8b78fad 100644 --- a/examples/typescript/clients/advanced/all_networks.ts +++ b/examples/typescript/clients/advanced/all_networks.ts @@ -75,15 +75,10 @@ async function main(): Promise { const body = await response.json(); console.log("Response body:", body); - // Extract payment response if present - if (response.ok) { - const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => - response.headers.get(name), - ); - console.log("\nPayment response:", JSON.stringify(paymentResponse, null, 2)); - } else { - console.log(`\nNo payment settled (response status: ${response.status})`); - } + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => + response.headers.get(name), + ); + console.log("\nPayment response:", JSON.stringify(paymentResponse, null, 2)); } main().catch(error => { diff --git a/examples/typescript/clients/advanced/builder-pattern.ts b/examples/typescript/clients/advanced/builder-pattern.ts index 67c098145b..0a91bd122e 100644 --- a/examples/typescript/clients/advanced/builder-pattern.ts +++ b/examples/typescript/clients/advanced/builder-pattern.ts @@ -56,12 +56,10 @@ export async function runBuilderPatternExample( console.log("βœ… Request completed\n"); console.log("Response body:", body); - if (response.ok) { - const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => - response.headers.get(name), - ); - if (paymentResponse) { - console.log("\nπŸ’° Payment Details:", paymentResponse); - } + 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/axios/index.ts b/examples/typescript/clients/axios/index.ts index b3cfed0f18..b0d96c249d 100644 --- a/examples/typescript/clients/axios/index.ts +++ b/examples/typescript/clients/axios/index.ts @@ -39,14 +39,10 @@ async function main(): Promise { 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})`); - } + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse( + name => response.headers[name.toLowerCase()], + ); + console.log("\nPayment response:", paymentResponse); } main().catch(error => { diff --git a/examples/typescript/clients/fetch/index.ts b/examples/typescript/clients/fetch/index.ts index ef5670feb8..e8e5f68e54 100644 --- a/examples/typescript/clients/fetch/index.ts +++ b/examples/typescript/clients/fetch/index.ts @@ -38,14 +38,10 @@ async function main(): Promise { const body = await response.json(); console.log("Response body:", body); - if (response.ok) { - const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => - response.headers.get(name), - ); - console.log("\nPayment response:", JSON.stringify(paymentResponse, null, 2)); - } else { - console.log(`\nNo payment settled (response status: ${response.status})`); - } + const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => + response.headers.get(name), + ); + console.log("\nPayment response:", JSON.stringify(paymentResponse, null, 2)); } main().catch(error => { diff --git a/examples/typescript/clients/payment-identifier/index.ts b/examples/typescript/clients/payment-identifier/index.ts index c11c80201a..51196ffbaf 100644 --- a/examples/typescript/clients/payment-identifier/index.ts +++ b/examples/typescript/clients/payment-identifier/index.ts @@ -65,13 +65,11 @@ async function main(): Promise { console.log(`Response (${duration1}ms):`, JSON.stringify(body1, null, 2)); - if (response1.ok) { - const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => - response1.headers.get(name), - ); - if (paymentResponse) { - console.log(`\nπŸ’° Payment settled on ${paymentResponse.network}`); - } + const paymentResponse1 = new x402HTTPClient(client).getPaymentSettleResponse(name => + response1.headers.get(name), + ); + if (paymentResponse1) { + console.log(`\nπŸ’° Payment settled on ${paymentResponse1.network}`); } // Second request - same payment ID, should return from cache @@ -88,15 +86,13 @@ async function main(): Promise { console.log(`Response (${duration2}ms):`, JSON.stringify(body2, null, 2)); - if (response2.ok) { - const paymentResponse = new x402HTTPClient(client).getPaymentSettleResponse(name => - response2.headers.get(name), - ); - if (paymentResponse) { - console.log(`\nπŸ’° Payment settled (unexpected - should have been cached)`); - } else { - console.log(`\nβœ… No payment processed - response served from cache!`); - } + const paymentResponse2 = new x402HTTPClient(client).getPaymentSettleResponse(name => + response2.headers.get(name), + ); + if (paymentResponse2) { + console.log(`\nπŸ’° Payment settled (unexpected - should have been cached)`); + } else { + console.log(`\nβœ… No payment processed - response served from cache!`); } // Summary diff --git a/examples/typescript/clients/sign-in-with-x/index.ts b/examples/typescript/clients/sign-in-with-x/index.ts index 4659510f82..29fd94cc4f 100644 --- a/examples/typescript/clients/sign-in-with-x/index.ts +++ b/examples/typescript/clients/sign-in-with-x/index.ts @@ -79,8 +79,8 @@ async function demonstrateResource(path: string): Promise { const response1 = await fetchWithPayment(url); const body1 = await response1.json(); + logPaymentResponse(response1); if (response1.ok) { - logPaymentResponse(response1); console.log(" Response:", body1); } else if (body1.error) { console.log(" βœ— Payment failed:", body1.details || body1.error); @@ -91,8 +91,8 @@ async function demonstrateResource(path: string): Promise { const response2 = await fetchWithPayment(url); const body2 = await response2.json(); + const hasPayment = logPaymentResponse(response2); if (response2.ok) { - const hasPayment = logPaymentResponse(response2); if (!hasPayment) { console.log(" βœ“ Authenticated via SIWX (previously paid)"); } diff --git a/go/http/gin/middleware.go b/go/http/gin/middleware.go index e176e21fda..1ba25ad209 100644 --- a/go/http/gin/middleware.go +++ b/go/http/gin/middleware.go @@ -382,17 +382,22 @@ func handlePaymentVerified(c *gin.Context, server *x402http.HTTPServer, ctx cont // Check settlement success if !settleResult.Success { - errorReason := settleResult.ErrorReason - if errorReason == "" { - errorReason = "Settlement failed" + // Always set PAYMENT-RESPONSE header on settlement failure + for key, value := range settleResult.Headers { + c.Header(key, value) } - if config.ErrorHandler != nil { + switch { + case config.ErrorHandler != nil: + errorReason := settleResult.ErrorReason + if errorReason == "" { + errorReason = "Settlement failed" + } config.ErrorHandler(c, fmt.Errorf("settlement failed: %s", errorReason)) - } else { - c.JSON(http.StatusPaymentRequired, gin.H{ - "error": "Settlement failed", - "details": errorReason, - }) + case settleResult.Response != nil: + handlePaymentError(c, settleResult.Response, config) + default: + // Fallback if Response is nil + c.JSON(http.StatusPaymentRequired, map[string]interface{}{}) } return } diff --git a/go/http/gin/middleware_test.go b/go/http/gin/middleware_test.go index b67b02ecd1..4895b84c46 100644 --- a/go/http/gin/middleware_test.go +++ b/go/http/gin/middleware_test.go @@ -646,16 +646,18 @@ func TestPaymentMiddleware_Returns402WhenSettlementFails(t *testing.T) { t.Errorf("Expected status 402, got %d", w.Code) } + // Empty body by default on settlement failure var response map[string]interface{} if err := json.Unmarshal(w.Body.Bytes(), &response); err != nil { t.Fatalf("Failed to parse response: %v", err) } - - if response["error"] != "Settlement failed" { - t.Errorf("Expected error 'Settlement failed', got '%v'", response["error"]) + if len(response) != 0 { + t.Errorf("Expected empty body {}, got %v", response) } - if response["details"] != "Insufficient funds" { - t.Errorf("Expected details 'Insufficient funds', got '%v'", response["details"]) + + // AYMENT-RESPONSE header must be included on settlement failure + if w.Header().Get("PAYMENT-RESPONSE") == "" { + t.Error("Expected PAYMENT-RESPONSE header on settlement failure") } } @@ -737,6 +739,11 @@ func TestPaymentMiddleware_CustomErrorHandler(t *testing.T) { if response["custom_error"] == nil { t.Error("Expected custom_error in response") } + + // PAYMENT-RESPONSE header must be set even when using custom error handler + if w.Header().Get("PAYMENT-RESPONSE") == "" { + t.Error("Expected PAYMENT-RESPONSE header when using custom error handler") + } } func TestPaymentMiddleware_CustomSettlementHandler(t *testing.T) { diff --git a/go/http/server.go b/go/http/server.go index 27adda9873..ecc9660857 100644 --- a/go/http/server.go +++ b/go/http/server.go @@ -183,6 +183,9 @@ type ProcessSettleResult struct { Transaction string Network x402.Network Payer string + // Response contains HTTP instructions for the failure case (status 402, body, etc). + // Set when Success is false; nil when Success is true. + Response *HTTPResponseInstructions } // ============================================================================ @@ -617,25 +620,21 @@ func (s *x402HTTPResourceServer) ProcessSettlement(ctx context.Context, payload // Settle payment (type-safe, no marshal needed) settleResult, err := s.SettlePayment(ctx, payload, requirements) if err != nil { - return &ProcessSettleResult{ - Success: false, - ErrorReason: err.Error(), - } + return s.buildSettlementFailureResult(err.Error(), x402.Network(requirements.Network), "", nil) } if !settleResult.Success { - return &ProcessSettleResult{ - Success: false, - ErrorReason: settleResult.ErrorReason, - } + return s.buildSettlementFailureResult(settleResult.ErrorReason, settleResult.Network, settleResult.Payer, settleResult) } headers, err := s.createSettlementHeaders(settleResult) if err != nil { - return &ProcessSettleResult{ - Success: false, - ErrorReason: fmt.Sprintf("failed to create settlement headers: %v", err), - } + return s.buildSettlementFailureResult( + fmt.Sprintf("failed to create settlement headers: %v", err), + x402.Network(requirements.Network), + settleResult.Payer, + nil, + ) } return &ProcessSettleResult{ @@ -647,6 +646,47 @@ func (s *x402HTTPResourceServer) ProcessSettlement(ctx context.Context, payload } } +// buildSettlementFailureResult creates a ProcessSettleResult for settlement failure. +// It includes PAYMENT-RESPONSE header and empty body by default. +func (s *x402HTTPResourceServer) buildSettlementFailureResult(errorReason string, network x402.Network, payer string, settleResult *x402.SettleResponse) *ProcessSettleResult { + failureResponse := x402.SettleResponse{ + Success: false, + ErrorReason: errorReason, + Transaction: "", + Network: network, + Payer: payer, + } + if settleResult != nil { + failureResponse.Network = settleResult.Network + failureResponse.Payer = settleResult.Payer + } + + headers, err := s.createSettlementHeaders(&failureResponse) + if err != nil { + // Fallback: return minimal result without PAYMENT-RESPONSE if encoding fails + return &ProcessSettleResult{ + Success: false, + ErrorReason: errorReason, + Response: &HTTPResponseInstructions{ + Status: 402, + Headers: map[string]string{}, + Body: map[string]interface{}{}, + }, + } + } + + return &ProcessSettleResult{ + Success: false, + ErrorReason: errorReason, + Headers: headers, + Response: &HTTPResponseInstructions{ + Status: 402, + Headers: headers, + Body: map[string]interface{}{}, + }, + } +} + // ============================================================================ // Helper Methods // ============================================================================ diff --git a/go/http/server_test.go b/go/http/server_test.go index b5689a76db..e93c79e545 100644 --- a/go/http/server_test.go +++ b/go/http/server_test.go @@ -417,6 +417,59 @@ func TestProcessSettlement(t *testing.T) { } } +func TestProcessSettlement_Failure(t *testing.T) { + ctx := context.Background() + + mockClient := &mockFacilitatorClient{ + settle: func(ctx context.Context, payloadBytes []byte, requirementsBytes []byte) (*x402.SettleResponse, error) { + return &x402.SettleResponse{ + Success: false, + ErrorReason: "insufficient_funds", + Network: "eip155:1", + Payer: "0xpayer", + }, nil + }, + } + + server := Newx402HTTPResourceServer( + RoutesConfig{}, + x402.WithFacilitatorClient(mockClient), + ) + _ = server.Initialize(ctx) + + requirements := types.PaymentRequirements{ + Scheme: "exact", + Network: "eip155:1", + Asset: "USDC", + Amount: "1000000", + PayTo: "0xtest", + } + + payload := types.PaymentPayload{ + X402Version: 2, + Accepted: requirements, + Payload: map[string]interface{}{}, + } + + result := server.ProcessSettlement(ctx, payload, requirements) + if result.Success { + t.Fatal("Expected settlement failure") + } + if result.Headers == nil || result.Headers["PAYMENT-RESPONSE"] == "" { + t.Error("Expected PAYMENT-RESPONSE header on settlement failure") + } + if result.Response == nil { + t.Fatal("Expected Response to be set on settlement failure") + } + if result.Response.Status != 402 { + t.Errorf("Expected status 402, got %d", result.Response.Status) + } + body, ok := result.Response.Body.(map[string]interface{}) + if !ok || len(body) != 0 { + t.Errorf("Expected empty body {}, got %v", result.Response.Body) + } +} + func TestParseRoutePattern(t *testing.T) { tests := []struct { pattern string diff --git a/python/x402/changelog.d/1430.bugfix.md b/python/x402/changelog.d/1430.bugfix.md new file mode 100644 index 0000000000..3fcb3bf302 --- /dev/null +++ b/python/x402/changelog.d/1430.bugfix.md @@ -0,0 +1 @@ +Added dynamic function for servers to generate custom response for settlement failures defaulting to empty diff --git a/python/x402/http/__init__.py b/python/x402/http/__init__.py index bbb2c126d1..ba34300a4d 100644 --- a/python/x402/http/__init__.py +++ b/python/x402/http/__init__.py @@ -30,6 +30,7 @@ HTTPAdapter, HTTPProcessResult, HTTPRequestContext, + HTTPResponseBody, HTTPResponseInstructions, PaymentOption, PaywallConfig, @@ -38,8 +39,8 @@ RouteConfigurationError, RoutesConfig, RouteValidationError, + SettlementFailedResponseBody, UnpaidResponseBody, - UnpaidResponseResult, ) from .utils import ( decode_payment_required_header, @@ -115,8 +116,9 @@ "CompiledRoute", "DynamicPayTo", "DynamicPrice", + "HTTPResponseBody", + "SettlementFailedResponseBody", "UnpaidResponseBody", - "UnpaidResponseResult", "RouteValidationError", "RouteConfigurationError", # Utils diff --git a/python/x402/http/middleware/fastapi.py b/python/x402/http/middleware/fastapi.py index 9911f06493..a7b02d494a 100644 --- a/python/x402/http/middleware/fastapi.py +++ b/python/x402/http/middleware/fastapi.py @@ -327,15 +327,26 @@ async def middleware( settle_result = await http_server.process_settlement( result.payment_payload, result.payment_requirements, + context=context, ) if not settle_result.success: + # Use response from process_settlement (includes PAYMENT-RESPONSE + # header and empty body by default) + resp = settle_result.response + if resp is None: + return JSONResponse(content={}, status_code=402) + if resp.is_html: + return Response( + content=resp.body, + status_code=resp.status, + headers=resp.headers, + media_type="text/html", + ) return JSONResponse( - content={ - "error": "Settlement failed", - "details": settle_result.error_reason, - }, - status_code=402, + content=resp.body or {}, + status_code=resp.status, + headers=resp.headers, ) # Add settlement headers @@ -349,14 +360,8 @@ async def middleware( media_type=response.media_type, ) - except Exception as e: - return JSONResponse( - content={ - "error": "Settlement failed", - "details": str(e), - }, - status_code=402, - ) + except Exception: + return JSONResponse(content={}, status_code=402) # Fallthrough - should not happen return await call_next(request) diff --git a/python/x402/http/middleware/flask.py b/python/x402/http/middleware/flask.py index 7e0c7d1cd5..47eed5f503 100644 --- a/python/x402/http/middleware/flask.py +++ b/python/x402/http/middleware/flask.py @@ -418,6 +418,7 @@ def _wsgi_middleware( settle_result = self._http_server.process_settlement( result.payment_payload, result.payment_requirements, + context=context, ) if settle_result.success: @@ -425,32 +426,34 @@ def _wsgi_middleware( for key, value in settle_result.headers.items(): response_wrapper.add_header(key, value) else: - # Settlement failed - error_body = json.dumps( - { - "error": "Settlement failed", - "details": settle_result.error_reason, - } - ).encode("utf-8") - start_response( - "402 Payment Required", - [("Content-Type", "application/json")], - ) - return [error_body] - - except Exception as e: - # Settlement error - error_body = json.dumps( - { - "error": "Settlement failed", - "details": str(e), - } - ).encode("utf-8") + # Settlement failed - use response from process_settlement + # (includes PAYMENT-RESPONSE header and empty body by default) + response = settle_result.response + if response is None: + status = "402 Payment Required" + headers = [("Content-Type", "application/json")] + body = json.dumps({}).encode("utf-8") + else: + status = f"{response.status} Payment Required" + headers = list(response.headers.items()) + if response.is_html: + body = ( + response.body.encode("utf-8") + if isinstance(response.body, str) + else response.body + ) + else: + body = json.dumps(response.body or {}).encode("utf-8") + start_response(status, headers) + return [body] + + except Exception: + # Settlement error - return empty body with 402 start_response( "402 Payment Required", [("Content-Type", "application/json")], ) - return [error_body] + return [json.dumps({}).encode("utf-8")] # Send buffered response response_wrapper.send_response(body_chunks) diff --git a/python/x402/http/types.py b/python/x402/http/types.py index cf02da2f69..49d43cd972 100644 --- a/python/x402/http/types.py +++ b/python/x402/http/types.py @@ -115,6 +115,7 @@ class ProcessSettleResult: transaction: str | None = None network: str | None = None payer: str | None = None + response: HTTPResponseInstructions | None = None # Only set when success=False # ============================================================================ @@ -140,14 +141,20 @@ class PaywallConfig: @dataclass -class UnpaidResponseResult: - """Custom unpaid response body.""" +class HTTPResponseBody: + """Custom response body (used by unpaid and settlement-failed hooks).""" content_type: str body: Any -UnpaidResponseBody = Callable[[HTTPRequestContext], UnpaidResponseResult] +UnpaidResponseBody = Callable[[HTTPRequestContext], HTTPResponseBody] + + +SettlementFailedResponseBody = Callable[ + [HTTPRequestContext, ProcessSettleResult], + HTTPResponseBody | Awaitable[HTTPResponseBody], +] @dataclass @@ -172,6 +179,7 @@ class RouteConfig: mime_type: str | None = None custom_paywall_html: str | None = None unpaid_response_body: UnpaidResponseBody | None = None + settlement_failed_response_body: SettlementFailedResponseBody | None = None extensions: dict[str, Any] | None = None hook_timeout_seconds: float | None = None diff --git a/python/x402/http/x402_http_server.py b/python/x402/http/x402_http_server.py index 548b863912..cc6f3e852f 100644 --- a/python/x402/http/x402_http_server.py +++ b/python/x402/http/x402_http_server.py @@ -10,12 +10,14 @@ import inspect from typing import TYPE_CHECKING, Any -from ..schemas import PaymentPayload, PaymentRequirements +from ..schemas import PaymentPayload, PaymentRequirements, SettleResponse +from ..schemas.errors import SettleError from ..schemas.v1 import PaymentPayloadV1 from ..server import ResourceConfig from .types import ( HTTPProcessResult, HTTPRequestContext, + HTTPResponseInstructions, PaymentOption, PaywallConfig, ProcessSettleResult, @@ -125,6 +127,7 @@ async def process_settlement( self, payment_payload: PaymentPayload | PaymentPayloadV1, requirements: PaymentRequirements, + context: HTTPRequestContext | None = None, ) -> ProcessSettleResult: """Process settlement after successful response (async). @@ -133,9 +136,10 @@ async def process_settlement( Args: payment_payload: The verified payment payload. requirements: The matching payment requirements. + context: Optional HTTP request context for route config lookup and hooks. Returns: - ProcessSettleResult with headers if success. + ProcessSettleResult with headers if success, or response if failure. """ try: settle_response = await self._server.settle_payment( @@ -144,10 +148,18 @@ async def process_settlement( ) if not settle_response.success: - return ProcessSettleResult( + failure = ProcessSettleResult( success=False, error_reason=settle_response.error_reason or "Settlement failed", + headers=self._create_settlement_headers(settle_response, requirements), + transaction=settle_response.transaction, + network=settle_response.network, + payer=settle_response.payer, ) + failure.response = await self._build_settlement_failure_response_async( + failure, context + ) + return failure return ProcessSettleResult( success=True, @@ -157,8 +169,76 @@ async def process_settlement( payer=settle_response.payer, ) + except SettleError as e: + settle_response = SettleResponse( + success=False, + error_reason=e.error_reason, + error_message=e.error_message or e.error_reason, + transaction=e.transaction or "", + network=requirements.network, + payer=e.payer, + ) + failure = ProcessSettleResult( + success=False, + error_reason=e.error_reason, + headers=self._create_settlement_headers(settle_response, requirements), + transaction=settle_response.transaction, + network=settle_response.network, + payer=settle_response.payer, + ) + failure.response = await self._build_settlement_failure_response_async(failure, context) + return failure + except Exception as e: - return ProcessSettleResult(success=False, error_reason=str(e)) + settle_response = SettleResponse( + success=False, + error_reason=str(e), + error_message=str(e), + transaction="", + network=requirements.network, + ) + failure = ProcessSettleResult( + success=False, + error_reason=str(e), + headers=self._create_settlement_headers(settle_response, requirements), + transaction="", + network=requirements.network, + ) + failure.response = await self._build_settlement_failure_response_async(failure, context) + return failure + + async def _build_settlement_failure_response_async( + self, + failure: ProcessSettleResult, + context: HTTPRequestContext | None, + ) -> HTTPResponseInstructions: + """Build HTTPResponseInstructions for settlement failure (async). + + Awaits settlement_failed_response_body hook if it returns a coroutine. + """ + settlement_headers = failure.headers + route_config = self._get_route_config(context.path, context.method) if context else None + + custom_body = None + if route_config and route_config.settlement_failed_response_body: + hook_result = route_config.settlement_failed_response_body(context, failure) + if asyncio.iscoroutine(hook_result): + custom_body = await hook_result + else: + custom_body = hook_result + + content_type = custom_body.content_type if custom_body else "application/json" + body = custom_body.body if custom_body else {} + + return HTTPResponseInstructions( + status=402, + headers={ + "Content-Type": content_type, + **settlement_headers, + }, + body=body, + is_html=content_type.startswith("text/html"), + ) async def _build_payment_requirements_from_options( self, diff --git a/python/x402/http/x402_http_server_base.py b/python/x402/http/x402_http_server_base.py index 65e6fb889b..afb5afc575 100644 --- a/python/x402/http/x402_http_server_base.py +++ b/python/x402/http/x402_http_server_base.py @@ -18,8 +18,13 @@ ResourceInfo, SettleResponse, ) +from ..schemas.errors import SettleError from ..schemas.v1 import PaymentPayloadV1 -from .constants import PAYMENT_REQUIRED_HEADER, PAYMENT_SIGNATURE_HEADER +from .constants import ( + PAYMENT_REQUIRED_HEADER, + PAYMENT_RESPONSE_HEADER, + PAYMENT_SIGNATURE_HEADER, +) from .types import ( RESULT_NO_PAYMENT_REQUIRED, RESULT_PAYMENT_ERROR, @@ -175,6 +180,10 @@ def _parse_route_config(self, config: dict[str, Any]) -> RouteConfig: unpaid_response_body=config.get( "unpaidResponseBody", config.get("unpaid_response_body") ), + settlement_failed_response_body=config.get( + "settlementFailedResponseBody", + config.get("settlement_failed_response_body"), + ), extensions=config.get("extensions"), hook_timeout_seconds=config.get("hook_timeout_seconds"), ) @@ -402,6 +411,7 @@ def process_settlement( self, payment_payload: PaymentPayload | PaymentPayloadV1, requirements: PaymentRequirements, + context: HTTPRequestContext | None = None, ) -> ProcessSettleResult: """Process settlement after successful response. @@ -410,9 +420,10 @@ def process_settlement( Args: payment_payload: The verified payment payload. requirements: The matching payment requirements. + context: Optional HTTP request context for route config lookup and hooks. Returns: - ProcessSettleResult with headers if success. + ProcessSettleResult with headers if success, or response if failure. """ try: settle_response = self._server.settle_payment( @@ -421,10 +432,16 @@ def process_settlement( ) if not settle_response.success: - return ProcessSettleResult( + failure = ProcessSettleResult( success=False, error_reason=settle_response.error_reason or "Settlement failed", + headers=self._create_settlement_headers(settle_response, requirements), + transaction=settle_response.transaction, + network=settle_response.network, + payer=settle_response.payer, ) + failure.response = self._build_settlement_failure_response(failure, context) + return failure return ProcessSettleResult( success=True, @@ -434,8 +451,43 @@ def process_settlement( payer=settle_response.payer, ) + except SettleError as e: + settle_response = SettleResponse( + success=False, + error_reason=e.error_reason, + error_message=e.error_message or e.error_reason, + transaction=e.transaction or "", + network=requirements.network, + payer=e.payer, + ) + failure = ProcessSettleResult( + success=False, + error_reason=e.error_reason, + headers=self._create_settlement_headers(settle_response, requirements), + transaction=settle_response.transaction, + network=settle_response.network, + payer=settle_response.payer, + ) + failure.response = self._build_settlement_failure_response(failure, context) + return failure + except Exception as e: - return ProcessSettleResult(success=False, error_reason=str(e)) + settle_response = SettleResponse( + success=False, + error_reason=str(e), + error_message=str(e), + transaction="", + network=requirements.network, + ) + failure = ProcessSettleResult( + success=False, + error_reason=str(e), + headers=self._create_settlement_headers(settle_response, requirements), + transaction="", + network=requirements.network, + ) + failure.response = self._build_settlement_failure_response(failure, context) + return failure # ========================================================================= # Internal Methods @@ -507,12 +559,40 @@ def _create_settlement_headers( requirements: PaymentRequirements, ) -> dict[str, str]: """Create settlement response headers.""" - from .constants import PAYMENT_RESPONSE_HEADER - return { PAYMENT_RESPONSE_HEADER: encode_payment_response_header(settle_response), } + def _build_settlement_failure_response( + self, + failure: ProcessSettleResult, + context: HTTPRequestContext | None, + ) -> HTTPResponseInstructions: + """Build HTTPResponseInstructions for settlement failure. + + Uses settlement_failed_response_body hook if configured, otherwise defaults to empty body. + Merges settlement headers (including PAYMENT-RESPONSE) into the response. + """ + settlement_headers = failure.headers + route_config = self._get_route_config(context.path, context.method) if context else None + + custom_body = None + if route_config and route_config.settlement_failed_response_body: + custom_body = route_config.settlement_failed_response_body(context, failure) + + content_type = custom_body.content_type if custom_body else "application/json" + body = custom_body.body if custom_body else {} + + return HTTPResponseInstructions( + status=402, + headers={ + "Content-Type": content_type, + **settlement_headers, + }, + body=body, + is_html=content_type.startswith("text/html"), + ) + def _validate_route_configuration(self) -> list[RouteValidationError]: """Validate all payment options have registered schemes.""" errors: list[RouteValidationError] = [] diff --git a/python/x402/schemas/responses.py b/python/x402/schemas/responses.py index 6ff72c7569..bb5e5a7837 100644 --- a/python/x402/schemas/responses.py +++ b/python/x402/schemas/responses.py @@ -12,10 +12,12 @@ class VerifyRequest(BaseX402Model): """Request to verify a payment. Attributes: + x402_version: Protocol version (1 or 2). payment_payload: The payment payload to verify. payment_requirements: The requirements to verify against. """ + x402_version: int payment_payload: PaymentPayload payment_requirements: PaymentRequirements @@ -40,10 +42,12 @@ class SettleRequest(BaseX402Model): """Request to settle a payment. Attributes: + x402_version: Protocol version (1 or 2). payment_payload: The payment payload to settle. payment_requirements: The requirements for settlement. """ + x402_version: int payment_payload: PaymentPayload payment_requirements: PaymentRequirements diff --git a/python/x402/tests/unit/http/middleware/test_fastapi.py b/python/x402/tests/unit/http/middleware/test_fastapi.py index 91a0cb0764..f8ad826b51 100644 --- a/python/x402/tests/unit/http/middleware/test_fastapi.py +++ b/python/x402/tests/unit/http/middleware/test_fastapi.py @@ -2,13 +2,14 @@ from __future__ import annotations -from unittest.mock import MagicMock +from unittest.mock import AsyncMock, MagicMock, patch import pytest # Skip all tests if fastapi not installed pytest.importorskip("fastapi") -from fastapi import Request +from fastapi import FastAPI, Request +from fastapi.testclient import TestClient from starlette.datastructures import Headers, QueryParams from x402.http.middleware.fastapi import ( @@ -18,7 +19,10 @@ payment_middleware, ) from x402.http.types import ( + HTTPProcessResult, + HTTPResponseInstructions, PaymentOption, + ProcessSettleResult, RouteConfig, ) from x402.schemas import PaymentPayload, PaymentRequirements @@ -318,6 +322,132 @@ async def call_next(req): assert response == expected_response +# ============================================================================= +# Integration-style Tests +# ============================================================================= + + +class TestFastAPIMiddlewareIntegration: + """Integration-style tests for FastAPI payment middleware.""" + + def test_settlement_success_adds_headers(self): + """Test that settlement success adds PAYMENT-RESPONSE header.""" + app = FastAPI() + + @app.get("/api/protected") + def protected_route(): + return {"data": "Protected content"} + + mock_server = MagicMock() + routes = { + "GET /api/protected": RouteConfig( + accepts=PaymentOption( + scheme="exact", + pay_to="0x1234567890123456789012345678901234567890", + price="$0.01", + network="eip155:8453", + ), + ) + } + + payment_payload = make_v2_payload() + payment_requirements = make_payment_requirements() + + with patch("x402.http.middleware.fastapi.x402HTTPResourceServer") as mock_http_server: + mock_http_server_instance = MagicMock() + mock_http_server_instance.requires_payment.return_value = True + mock_http_server_instance.process_http_request = AsyncMock( + return_value=HTTPProcessResult( + type="payment-verified", + payment_payload=payment_payload, + payment_requirements=payment_requirements, + ) + ) + mock_http_server_instance.process_settlement = AsyncMock( + return_value=ProcessSettleResult( + success=True, + headers={"PAYMENT-RESPONSE": "settlement_encoded"}, + ) + ) + mock_http_server.return_value = mock_http_server_instance + + @app.middleware("http") + async def x402_middleware(request: Request, call_next): + return await payment_middleware( + routes, mock_server, sync_facilitator_on_start=False + )(request, call_next) + + with TestClient(app) as client: + response = client.get( + "/api/protected", + headers={"PAYMENT-SIGNATURE": "valid_payment"}, + ) + assert response.status_code == 200 + assert response.json() == {"data": "Protected content"} + assert "PAYMENT-RESPONSE" in response.headers + + def test_settlement_failure_returns_402(self): + """Test that settlement failure returns 402 with empty body and PAYMENT-RESPONSE header.""" + app = FastAPI() + + @app.get("/api/protected") + def protected_route(): + return {"data": "Protected content"} + + mock_server = MagicMock() + routes = { + "GET /api/protected": RouteConfig( + accepts=PaymentOption( + scheme="exact", + pay_to="0x1234567890123456789012345678901234567890", + price="$0.01", + network="eip155:8453", + ), + ) + } + + payment_payload = make_v2_payload() + payment_requirements = make_payment_requirements() + + with patch("x402.http.middleware.fastapi.x402HTTPResourceServer") as mock_http_server: + mock_http_server_instance = MagicMock() + mock_http_server_instance.requires_payment.return_value = True + mock_http_server_instance.process_http_request = AsyncMock( + return_value=HTTPProcessResult( + type="payment-verified", + payment_payload=payment_payload, + payment_requirements=payment_requirements, + ) + ) + mock_http_server_instance.process_settlement = AsyncMock( + return_value=ProcessSettleResult( + success=False, + error_reason="Insufficient funds", + response=HTTPResponseInstructions( + status=402, + headers={ + "Content-Type": "application/json", + "PAYMENT-RESPONSE": "base64encoded", + }, + body={}, + ), + ) + ) + mock_http_server.return_value = mock_http_server_instance + + @app.middleware("http") + async def x402_middleware(request: Request, call_next): + return await payment_middleware( + routes, mock_server, sync_facilitator_on_start=False + )(request, call_next) + + with TestClient(app) as client: + response = client.get("/api/protected") + assert response.status_code == 402 + assert response.json() == {} + assert "PAYMENT-RESPONSE" in response.headers + + # ============================================================================= # ASGI Middleware Class Tests # ============================================================================= diff --git a/python/x402/tests/unit/http/middleware/test_flask.py b/python/x402/tests/unit/http/middleware/test_flask.py index bf538ff210..6999b21a57 100644 --- a/python/x402/tests/unit/http/middleware/test_flask.py +++ b/python/x402/tests/unit/http/middleware/test_flask.py @@ -522,7 +522,7 @@ def protected_route(): assert "PAYMENT-RESPONSE" in response.headers def test_settlement_failure_returns_402(self): - """Test that settlement failure returns 402.""" + """Test that settlement failure returns 402 with empty body and PAYMENT-RESPONSE header.""" app = Flask(__name__) @app.route("/api/protected") @@ -546,6 +546,14 @@ def protected_route(): mock_http_server_instance.process_settlement.return_value = ProcessSettleResult( success=False, error_reason="Insufficient funds", + response=HTTPResponseInstructions( + status=402, + headers={ + "Content-Type": "application/json", + "PAYMENT-RESPONSE": "base64encoded", + }, + body={}, + ), ) mock_http_server.return_value = mock_http_server_instance @@ -555,5 +563,5 @@ def protected_route(): response = client.get("/api/protected") assert response.status_code == 402 data = json.loads(response.data) - assert data["error"] == "Settlement failed" - assert data["details"] == "Insufficient funds" + assert data == {} + assert "PAYMENT-RESPONSE" in response.headers diff --git a/specs/transports-v2/http.md b/specs/transports-v2/http.md index fb61bb87a4..a735f80032 100644 --- a/specs/transports-v2/http.md +++ b/specs/transports-v2/http.md @@ -18,9 +18,7 @@ HTTP/1.1 402 Payment Required Content-Type: application/json PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQQVlNRU5ULVNJR05BVFVSRSBoZWFkZXIgaXMgcmVxdWlyZWQiLCJyZXNvdXJjZSI6eyJ1cmwiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbS9wcmVtaXVtLWRhdGEiLCJkZXNjcmlwdGlvbiI6IkFjY2VzcyB0byBwcmVtaXVtIG1hcmtldCBkYXRhIiwibWltZVR5cGUiOiJhcHBsaWNhdGlvbi9qc29uIn0sImFjY2VwdHMiOlt7InNjaGVtZSI6ImV4YWN0IiwibmV0d29yayI6ImVpcDE1NTo4NDUzMiIsImFtb3VudCI6IjEwMDAwIiwiYXNzZXQiOiIweDAzNkNiRDUzODQyYzU0MjY2MzRlNzkyOTU0MWVDMjMxOGYzZENGN2UiLCJwYXlUbyI6IjB4MjA5NjkzQmM2YWZjMEM1MzI4YkEzNkZhRjAzQzUxNEVGMzEyMjg3QyIsIm1heFRpbWVvdXRTZWNvbmRzIjo2MCwiZXh0cmEiOnsibmFtZSI6IlVTREMiLCJ2ZXJzaW9uIjoiMiJ9fV19 -{ - "error": "Payment required" -} +{} ``` The base64 header decodes to: @@ -145,10 +143,18 @@ HTTP/1.1 402 Payment Required Content-Type: application/json PAYMENT-RESPONSE: eyJzdWNjZXNzIjpmYWxzZSwiZXJyb3JSZWFzb24iOiJpbnN1ZmZpY2llbnRfZnVuZHMiLCJ0cmFuc2FjdGlvbiI6IiIsIm5ldHdvcmsiOiJlaXAxNTU6ODQ1MzIiLCJwYXllciI6IjB4ODU3YjA2NTE5RTkxZTNBNTQ1Mzg3OTFiRGJiMEUyMjM3M2UzNmI2NiJ9 +{} +``` + +The base64 response header decodes to: + +```json { - "x402Version": 2, - "error": "Payment failed: insufficient funds", - "accepts": [...] + "success": false, + "errorReason": "insufficient_funds", + "transaction": "", + "network": "eip155:84532", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66" } ``` @@ -160,6 +166,10 @@ PAYMENT-RESPONSE: eyJzdWNjZXNzIjpmYWxzZSwiZXJyb3JSZWFzb24iOiJpbnN1ZmZpY2llbnRfZn | `PAYMENT-SIGNATURE` | Client β†’ Server | Base64-encoded `PaymentPayload` object | | `PAYMENT-RESPONSE` | Server β†’ Client | Base64-encoded `SettlementResponse` object | +## Response Body + +Response bodies are a server implementation concern. All x402 protocol information is communicated through headers (`PAYMENT-REQUIRED`, `PAYMENT-SIGNATURE`, `PAYMENT-RESPONSE`). + ## Error Handling HTTP transport maps x402 errors to standard HTTP status codes: diff --git a/typescript/.changeset/bold-mice-sink.md b/typescript/.changeset/bold-mice-sink.md new file mode 100644 index 0000000000..e83c6e0695 --- /dev/null +++ b/typescript/.changeset/bold-mice-sink.md @@ -0,0 +1,8 @@ +--- +'@x402/express': patch +'@x402/hono': patch +'@x402/next': patch +'@x402/core': patch +--- + +Added dynamic function for servers to generate custom response for settlement failures defaulting to empty diff --git a/typescript/packages/core/src/http/index.ts b/typescript/packages/core/src/http/index.ts index a464eacee8..8ff5882aa7 100644 --- a/typescript/packages/core/src/http/index.ts +++ b/typescript/packages/core/src/http/index.ts @@ -94,7 +94,8 @@ export { DynamicPayTo, DynamicPrice, UnpaidResponseBody, - UnpaidResponseResult, + HTTPResponseBody, + SettlementFailedResponseBody, ProcessSettleResultResponse, ProcessSettleSuccessResponse, ProcessSettleFailureResponse, diff --git a/typescript/packages/core/src/http/x402HTTPResourceServer.ts b/typescript/packages/core/src/http/x402HTTPResourceServer.ts index 1f7ed67997..668ab2e89e 100644 --- a/typescript/packages/core/src/http/x402HTTPResourceServer.ts +++ b/typescript/packages/core/src/http/x402HTTPResourceServer.ts @@ -80,9 +80,9 @@ export type DynamicPayTo = (context: HTTPRequestContext) => string | Promise Price | Promise; /** - * Result of the unpaid response callback containing content type and body. + * Result of response body callbacks containing content type and body. */ -export interface UnpaidResponseResult { +export interface HTTPResponseBody { /** * The content type for the response (e.g., 'application/json', 'text/plain'). */ @@ -100,7 +100,16 @@ export interface UnpaidResponseResult { */ export type UnpaidResponseBody = ( context: HTTPRequestContext, -) => UnpaidResponseResult | Promise; +) => HTTPResponseBody | Promise; + +/** + * Dynamic function to generate a custom response for settlement failures. + * Receives the HTTP request context and settle failure result, returns the content type and body. + */ +export type SettlementFailedResponseBody = ( + context: HTTPRequestContext, + settleResult: Omit, +) => HTTPResponseBody | Promise; /** * A single payment option for a route @@ -146,6 +155,16 @@ export interface RouteConfig { */ unpaidResponseBody?: UnpaidResponseBody; + /** + * Optional callback to generate a custom response for settlement failures. + * If not provided, defaults to { contentType: 'application/json', body: {} }. + * + * @param context - The HTTP request context + * @param settleResult - The settlement failure result + * @returns An object containing both contentType and body for the 402 response + */ + settlementFailedResponseBody?: SettlementFailedResponseBody; + // Extensions extensions?: Record; } @@ -235,6 +254,7 @@ export type ProcessSettleFailureResponse = SettleResponse & { errorReason: string; errorMessage?: string; headers: Record; + response: HTTPResponseInstructions; }; export type ProcessSettleResultResponse = @@ -560,14 +580,16 @@ export class x402HTTPResourceServer { ); if (!settleResponse.success) { - return { + const failure = { ...settleResponse, - success: false, + success: false as const, errorReason: settleResponse.errorReason || "Settlement failed", errorMessage: settleResponse.errorMessage || settleResponse.errorReason || "Settlement failed", headers: this.createSettlementHeaders(settleResponse), }; + const response = await this.buildSettlementFailureResponse(failure, transportContext); + return { ...failure, response }; } return { @@ -587,12 +609,14 @@ export class x402HTTPResourceServer { network: error.network, transaction: error.transaction, }; - return { + const failure = { ...settleResponse, success: false as const, errorReason, headers: this.createSettlementHeaders(settleResponse), }; + const response = await this.buildSettlementFailureResponse(failure, transportContext); + return { ...failure, response }; } const errorReason = error instanceof Error ? error.message : "Settlement failed"; const settleResponse: SettleResponse = { @@ -602,12 +626,14 @@ export class x402HTTPResourceServer { network: requirements.network as Network, transaction: "", }; - return { + const failure = { ...settleResponse, success: false as const, errorReason, headers: this.createSettlementHeaders(settleResponse), }; + const response = await this.buildSettlementFailureResponse(failure, transportContext); + return { ...failure, response }; } } @@ -622,6 +648,41 @@ export class x402HTTPResourceServer { return routeConfig !== undefined; } + /** + * Build HTTPResponseInstructions for settlement failure. + * Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body. + * + * @param failure - Settlement failure result with headers + * @param transportContext - Optional HTTP transport context for the request + * @returns HTTP response instructions for the 402 settlement failure response + */ + private async buildSettlementFailureResponse( + failure: Omit, + transportContext?: HTTPTransportContext, + ): Promise { + const settlementHeaders = failure.headers; + const routeConfig = transportContext + ? this.getRouteConfig(transportContext.request.path, transportContext.request.method) + : undefined; + + const customBody = routeConfig?.settlementFailedResponseBody + ? await routeConfig.settlementFailedResponseBody(transportContext!.request, failure) + : undefined; + + const contentType = customBody ? customBody.contentType : "application/json"; + const body = customBody ? customBody.body : {}; + + return { + status: 402, + headers: { + "Content-Type": contentType, + ...settlementHeaders, + }, + body, + isHtml: contentType.includes("text/html"), + }; + } + /** * Normalizes a RouteConfig's accepts field into an array of PaymentOptions * Handles both single PaymentOption and array formats @@ -754,7 +815,7 @@ export class x402HTTPResourceServer { isWebBrowser: boolean, paywallConfig?: PaywallConfig, customHtml?: string, - unpaidResponse?: UnpaidResponseResult, + unpaidResponse?: HTTPResponseBody, ): HTTPResponseInstructions { // Use 412 Precondition Failed for permit2_allowance_required error // This signals client needs to approve Permit2 before retrying diff --git a/typescript/packages/core/src/server/index.ts b/typescript/packages/core/src/server/index.ts index bf7f61eb84..412c94d733 100644 --- a/typescript/packages/core/src/server/index.ts +++ b/typescript/packages/core/src/server/index.ts @@ -17,7 +17,8 @@ export type { HTTPAdapter, RoutesConfig, UnpaidResponseBody, - UnpaidResponseResult, + HTTPResponseBody, + SettlementFailedResponseBody, ProcessSettleResultResponse, ProcessSettleSuccessResponse, ProcessSettleFailureResponse, diff --git a/typescript/packages/core/test/mocks/generic/MockFacilitatorClient.ts b/typescript/packages/core/test/mocks/generic/MockFacilitatorClient.ts index 1dda1e36cd..4cef0090b1 100644 --- a/typescript/packages/core/test/mocks/generic/MockFacilitatorClient.ts +++ b/typescript/packages/core/test/mocks/generic/MockFacilitatorClient.ts @@ -63,10 +63,13 @@ export class MockFacilitatorClient implements FacilitatorClient { payloadOrRequest: PaymentPayload | VerifyRequest, requirements?: PaymentRequirements, ): Promise { - const payload = "payload" in payloadOrRequest ? payloadOrRequest.payload : payloadOrRequest; + const payload = + "paymentPayload" in payloadOrRequest ? payloadOrRequest.paymentPayload : payloadOrRequest; const reqs = - requirements || - ("requirements" in payloadOrRequest ? payloadOrRequest.requirements : undefined)!; + requirements ?? + ("paymentRequirements" in payloadOrRequest + ? payloadOrRequest.paymentRequirements + : undefined)!; this.verifyCalls.push({ payload, requirements: reqs }); @@ -93,10 +96,13 @@ export class MockFacilitatorClient implements FacilitatorClient { payloadOrRequest: PaymentPayload | SettleRequest, requirements?: PaymentRequirements, ): Promise { - const payload = "payload" in payloadOrRequest ? payloadOrRequest.payload : payloadOrRequest; + const payload = + "paymentPayload" in payloadOrRequest ? payloadOrRequest.paymentPayload : payloadOrRequest; const reqs = - requirements || - ("requirements" in payloadOrRequest ? payloadOrRequest.requirements : undefined)!; + requirements ?? + ("paymentRequirements" in payloadOrRequest + ? payloadOrRequest.paymentRequirements + : undefined)!; this.settleCalls.push({ payload, requirements: reqs }); diff --git a/typescript/packages/http/express/src/index.test.ts b/typescript/packages/http/express/src/index.test.ts index 6085241d27..98c1c6be67 100644 --- a/typescript/packages/http/express/src/index.test.ts +++ b/typescript/packages/http/express/src/index.test.ts @@ -71,7 +71,12 @@ function setupMockHttpServer( processResult: HTTPProcessResult, settlementResult: | { success: true; headers: Record } - | { success: false; errorReason: string; headers: Record } = { + | { + success: false; + errorReason: string; + headers: Record; + response: { status: number; headers: Record; body?: unknown }; + } = { success: true, headers: {}, }, @@ -386,10 +391,7 @@ describe("paymentMiddleware", () => { await middleware(req, res, next); expect(res.status).toHaveBeenCalledWith(402); - expect(res.json).toHaveBeenCalledWith({ - error: "Settlement failed", - details: "Settlement rejected", - }); + expect(res.json).toHaveBeenCalledWith({}); }); it("returns 402 when settlement returns success: false", async () => { @@ -403,6 +405,14 @@ describe("paymentMiddleware", () => { success: false, errorReason: "Insufficient funds", headers: { "PAYMENT-RESPONSE": "settlement-failed-encoded" }, + response: { + status: 402, + headers: { + "Content-Type": "application/json", + "PAYMENT-RESPONSE": "settlement-failed-encoded", + }, + body: {}, + }, }, ); @@ -424,10 +434,7 @@ describe("paymentMiddleware", () => { expect(res.setHeader).toHaveBeenCalledWith("PAYMENT-RESPONSE", "settlement-failed-encoded"); expect(res.status).toHaveBeenCalledWith(402); - expect(res.json).toHaveBeenCalledWith({ - error: "Settlement failed", - details: "Insufficient funds", - }); + expect(res.json).toHaveBeenCalledWith({}); }); it("passes paywallConfig to processHTTPRequest", async () => { diff --git a/typescript/packages/http/express/src/index.ts b/typescript/packages/http/express/src/index.ts index 2da120c83f..74b67b7767 100644 --- a/typescript/packages/http/express/src/index.ts +++ b/typescript/packages/http/express/src/index.ts @@ -248,13 +248,15 @@ export function paymentMiddlewareFromHTTPServer( // If settlement fails, return an error and do not send the buffered response if (!settleResult.success) { bufferedCalls = []; - Object.entries(settleResult.headers).forEach(([key, value]) => { + const { response } = settleResult; + Object.entries(response.headers).forEach(([key, value]) => { res.setHeader(key, value); }); - res.status(402).json({ - error: "Settlement failed", - details: settleResult.errorReason, - }); + if (response.isHtml) { + res.status(response.status).send(response.body); + } else { + res.status(response.status).json(response.body ?? {}); + } return; } @@ -266,10 +268,7 @@ export function paymentMiddlewareFromHTTPServer( console.error(error); // If settlement fails, don't send the buffered response bufferedCalls = []; - res.status(402).json({ - error: "Settlement failed", - details: error instanceof Error ? error.message : "Unknown error", - }); + res.status(402).json({}); return; } finally { settled = true; diff --git a/typescript/packages/http/hono/src/index.test.ts b/typescript/packages/http/hono/src/index.test.ts index 8e34868fab..809a000584 100644 --- a/typescript/packages/http/hono/src/index.test.ts +++ b/typescript/packages/http/hono/src/index.test.ts @@ -71,7 +71,12 @@ function setupMockHttpServer( processResult: HTTPProcessResult, settlementResult: | { success: true; headers: Record } - | { success: false; errorReason: string; headers: Record } = { + | { + success: false; + errorReason: string; + headers: Record; + response: { status: number; headers: Record; body?: unknown }; + } = { success: true, headers: {}, }, @@ -388,13 +393,7 @@ describe("paymentMiddleware", () => { await middleware(context, next); - expect(context.json).toHaveBeenCalledWith( - { - error: "Settlement failed", - details: "Settlement rejected", - }, - 402, - ); + expect(context.json).toHaveBeenCalledWith({}, 402); }); it("returns 402 when settlement returns success: false", async () => { @@ -408,6 +407,14 @@ describe("paymentMiddleware", () => { success: false, errorReason: "Insufficient funds", headers: { "PAYMENT-RESPONSE": "settlement-failed-encoded" }, + response: { + status: 402, + headers: { + "Content-Type": "application/json", + "PAYMENT-RESPONSE": "settlement-failed-encoded", + }, + body: {}, + }, }, ); @@ -433,14 +440,10 @@ describe("paymentMiddleware", () => { await middleware(context, next); - expect(context.json).toHaveBeenCalledWith( - { - error: "Settlement failed", - details: "Insufficient funds", - }, - 402, - ); + expect(context.res?.status).toBe(402); expect(context.res?.headers.get("PAYMENT-RESPONSE")).toBe("settlement-failed-encoded"); + const body = await context.res?.json(); + expect(body).toEqual({}); }); it("passes paywallConfig to processHTTPRequest", async () => { diff --git a/typescript/packages/http/hono/src/index.ts b/typescript/packages/http/hono/src/index.ts index a62ad08f5d..22ef837f45 100644 --- a/typescript/packages/http/hono/src/index.ts +++ b/typescript/packages/http/hono/src/index.ts @@ -175,15 +175,13 @@ export function paymentMiddlewareFromHTTPServer( if (!settleResult.success) { // Settlement failed - do not return the protected resource - res = c.json( - { - error: "Settlement failed", - details: settleResult.errorReason, - }, - 402, - ); - Object.entries(settleResult.headers).forEach(([key, value]) => { - res.headers.set(key, value); + const { response } = settleResult; + const body = response.isHtml + ? String(response.body ?? "") + : JSON.stringify(response.body ?? {}); + res = new Response(body, { + status: response.status, + headers: response.headers, }); } else { // Settlement succeeded - add headers to response @@ -194,13 +192,7 @@ export function paymentMiddlewareFromHTTPServer( } catch (error) { console.error(error); // If settlement fails, return an error response - res = c.json( - { - error: "Settlement failed", - details: error instanceof Error ? error.message : "Unknown error", - }, - 402, - ); + res = c.json({}, 402); } // Restore the response (potentially modified with settlement headers) diff --git a/typescript/packages/http/next/src/index.test.ts b/typescript/packages/http/next/src/index.test.ts index 89aeea80c0..3c7b6c498f 100644 --- a/typescript/packages/http/next/src/index.test.ts +++ b/typescript/packages/http/next/src/index.test.ts @@ -87,7 +87,12 @@ function createMockHttpServer( processResult: HTTPProcessResult, settlementResult: | { success: true; headers: Record } - | { success: false; errorReason: string; headers: Record } = { + | { + success: false; + errorReason: string; + headers: Record; + response: { status: number; headers: Record; body?: unknown }; + } = { success: true, headers: {}, }, @@ -274,7 +279,7 @@ describe("paymentProxy", () => { expect(response.status).toBe(402); const body = await response.json(); - expect(body.error).toBe("Settlement failed"); + expect(body).toEqual({}); }); it("returns 402 when settlement returns success: false, not the resource", async () => { @@ -288,6 +293,14 @@ describe("paymentProxy", () => { success: false, errorReason: "Insufficient funds", headers: { "PAYMENT-RESPONSE": "settlement-failed-encoded" }, + response: { + status: 402, + headers: { + "Content-Type": "application/json", + "PAYMENT-RESPONSE": "settlement-failed-encoded", + }, + body: {}, + }, }, ); setupMockCreateHttpServer(mockServer); @@ -297,8 +310,7 @@ describe("paymentProxy", () => { expect(response.status).toBe(402); const body = await response.json(); - expect(body.error).toBe("Settlement failed"); - expect(body.details).toBe("Insufficient funds"); + expect(body).toEqual({}); expect(response.headers.get("PAYMENT-RESPONSE")).toBe("settlement-failed-encoded"); }); }); @@ -397,7 +409,7 @@ describe("withX402", () => { expect(handler).toHaveBeenCalled(); expect(response.status).toBe(402); const body = await response.json(); - expect(body.error).toBe("Settlement failed"); + expect(body).toEqual({}); }); it("returns 402 when settlement returns success: false, not the handler response", async () => { @@ -411,6 +423,14 @@ describe("withX402", () => { success: false, errorReason: "Insufficient funds", headers: { "PAYMENT-RESPONSE": "settlement-failed-encoded" }, + response: { + status: 402, + headers: { + "Content-Type": "application/json", + "PAYMENT-RESPONSE": "settlement-failed-encoded", + }, + body: {}, + }, }, ); setupMockCreateHttpServer(mockServer); @@ -422,8 +442,7 @@ describe("withX402", () => { expect(handler).toHaveBeenCalled(); expect(response.status).toBe(402); const body = await response.json(); - expect(body.error).toBe("Settlement failed"); - expect(body.details).toBe("Insufficient funds"); + expect(body).toEqual({}); expect(response.headers.get("PAYMENT-RESPONSE")).toBe("settlement-failed-encoded"); }); }); diff --git a/typescript/packages/http/next/src/utils.test.ts b/typescript/packages/http/next/src/utils.test.ts index aea7f2f2ea..d2d4a2797a 100644 --- a/typescript/packages/http/next/src/utils.test.ts +++ b/typescript/packages/http/next/src/utils.test.ts @@ -270,6 +270,14 @@ describe("handleSettlement", () => { transaction: "", network: "eip155:84532", headers: { "PAYMENT-RESPONSE": "settlement-failed-encoded" }, + response: { + status: 402, + headers: { + "Content-Type": "application/json", + "PAYMENT-RESPONSE": "settlement-failed-encoded", + }, + body: {}, + }, }); const response = new NextResponse("OK", { status: 200 }); @@ -281,9 +289,8 @@ describe("handleSettlement", () => { ); expect(result.status).toBe(402); - const body = (await result.json()) as { error: string; details: string }; - expect(body.error).toBe("Settlement failed"); - expect(body.details).toBe("Insufficient funds"); + const body = await result.json(); + expect(body).toEqual({}); expect(result.headers.get("PAYMENT-RESPONSE")).toBe("settlement-failed-encoded"); }); @@ -299,8 +306,7 @@ describe("handleSettlement", () => { ); expect(result.status).toBe(402); - const body = (await result.json()) as { error: string; details: string }; - expect(body.error).toBe("Settlement failed"); - expect(body.details).toBe("Settlement rejected"); + const body = await result.json(); + expect(body).toEqual({}); }); }); diff --git a/typescript/packages/http/next/src/utils.ts b/typescript/packages/http/next/src/utils.ts index 1b016b44ac..84fc5d4a1d 100644 --- a/typescript/packages/http/next/src/utils.ts +++ b/typescript/packages/http/next/src/utils.ts @@ -150,16 +150,12 @@ export async function handleSettlement( if (!result.success) { // Settlement failed - do not return the protected resource - return new NextResponse( - JSON.stringify({ - error: "Settlement failed", - details: result.errorReason, - }), - { - status: 402, - headers: { "Content-Type": "application/json", ...result.headers }, - }, - ); + const { response } = result; + const body = response.isHtml ? response.body : JSON.stringify(response.body ?? {}); + return new NextResponse(body, { + status: response.status, + headers: response.headers, + }); } // Settlement succeeded - add headers and return original response @@ -171,15 +167,9 @@ export async function handleSettlement( } catch (error) { console.error("Settlement failed:", error); // If settlement fails, return an error response - return new NextResponse( - JSON.stringify({ - error: "Settlement failed", - details: error instanceof Error ? error.message : "Unknown error", - }), - { - status: 402, - headers: { "Content-Type": "application/json" }, - }, - ); + return new NextResponse(JSON.stringify({}), { + status: 402, + headers: { "Content-Type": "application/json" }, + }); } } From f4313370c249b35a6a43bc8f18d9bebac17beb88 Mon Sep 17 00:00:00 2001 From: phdargen Date: Thu, 5 Mar 2026 11:07:18 +0900 Subject: [PATCH 025/129] Add assetTransferMethod and supportsEip2612 flag to defaultAssets (#1359) * set assetTransferMethod for defaultAsset * mock token fix * use moneyparser * py changes * go changes * fix get_asset_info * add SupportsEip2612 flag * add changelogs * fix tests --- e2e/scripts/permit2-approval.ts | 153 ++++++++++-------- e2e/servers/express/index.ts | 19 +-- e2e/servers/express/package.json | 2 +- e2e/servers/express/test.config.json | 26 +-- e2e/servers/hono/index.ts | 41 +++-- e2e/servers/hono/package.json | 2 +- e2e/servers/hono/test.config.json | 28 +--- e2e/servers/next/app/api/close/route.ts | 2 +- e2e/servers/next/app/api/health/route.ts | 2 +- .../app/api/protected-aptos-proxy/route.ts | 11 +- .../next/app/api/protected-proxy/route.ts | 1 - .../next/app/api/protected-svm-proxy/route.ts | 1 - .../app/api/protected-svm-withx402/route.ts | 1 - .../next/app/api/protected-withx402/route.ts | 1 - e2e/servers/next/next.config.ts | 3 +- e2e/servers/next/package.json | 2 +- e2e/servers/next/proxy.ts | 99 ++++-------- e2e/servers/next/test.config.json | 35 +--- e2e/servers/next/tsconfig.json | 14 +- go/go.mod | 3 +- go/mechanisms/evm/constants.go | 12 +- go/mechanisms/evm/exact/server/scheme.go | 37 +++-- go/mechanisms/evm/types.go | 10 +- python/x402/changelog.d/1359.bugfix.md | 1 + python/x402/mechanisms/evm/__init__.py | 2 - python/x402/mechanisms/evm/constants.py | 113 +++---------- python/x402/mechanisms/evm/exact/server.py | 64 ++++++-- python/x402/mechanisms/evm/utils.py | 59 ++++--- python/x402/mechanisms/evm/v1/constants.py | 52 ++++-- python/x402/mechanisms/evm/v1/utils.py | 58 ++----- python/x402/mechanisms/svm/utils.py | 14 +- .../tests/unit/mechanisms/evm/test_client.py | 8 +- .../unit/mechanisms/evm/test_facilitator.py | 26 +-- .../tests/unit/mechanisms/evm/test_index.py | 27 ++-- .../tests/unit/mechanisms/evm/test_server.py | 38 ++--- .../unit/mechanisms/evm/test_v1_utils.py | 20 ++- typescript/.changeset/red-geese-sit.md | 5 + .../evm/src/exact/server/DEFAULT_ASSET.md | 36 +++-- .../mechanisms/evm/src/exact/server/scheme.ts | 46 +++++- .../mechanisms/evm/test/unit/server.test.ts | 23 +++ 40 files changed, 519 insertions(+), 578 deletions(-) create mode 100644 python/x402/changelog.d/1359.bugfix.md create mode 100644 typescript/.changeset/red-geese-sit.md diff --git a/e2e/scripts/permit2-approval.ts b/e2e/scripts/permit2-approval.ts index bf19b93d6b..819068b055 100644 --- a/e2e/scripts/permit2-approval.ts +++ b/e2e/scripts/permit2-approval.ts @@ -28,9 +28,19 @@ config(); // Permit2 canonical address (same on all EVM chains) const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3'; -// Base Sepolia USDC -const USDC_ADDRESS = '0x036CbD53842c5426634e7929541eC2318f3dCF7e'; -const USDC_DECIMALS = 6; +// Known tokens on Base Sepolia +const TOKENS: Record = { + USDC: { + address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', + decimals: 6, + name: 'USDC', + }, + MockERC20: { + address: '0xeED520980fC7C7B4eB379B96d61CEdea2423005a', + decimals: 6, + name: 'MockERC20', + }, +}; // Maximum uint256 for unlimited approval const MAX_UINT256 = 2n ** 256n - 1n; @@ -80,93 +90,94 @@ Environment variables required: console.log(`\nπŸ”‘ Wallet: ${account.address}`); console.log(`πŸ“ Network: Base Sepolia`); - console.log(`πŸ’° Token: USDC (${USDC_ADDRESS})`); console.log(`πŸ” Permit2: ${PERMIT2_ADDRESS}\n`); - // Check current balance - const balance = await publicClient.readContract({ - address: USDC_ADDRESS, - abi: erc20Abi, - functionName: 'balanceOf', - args: [account.address], - }); - console.log(`πŸ’΅ USDC Balance: ${formatUnits(balance, USDC_DECIMALS)} USDC`); - - // Check current allowance - const currentAllowance = await publicClient.readContract({ - address: USDC_ADDRESS, - abi: erc20Abi, - functionName: 'allowance', - args: [account.address, PERMIT2_ADDRESS], - }); + // Display balance and allowance for all known tokens + const tokenStates: { name: string; address: `0x${string}`; decimals: number; balance: bigint; allowance: bigint }[] = []; + + for (const token of Object.values(TOKENS)) { + const balance = await publicClient.readContract({ + address: token.address, + abi: erc20Abi, + functionName: 'balanceOf', + args: [account.address], + }); + + const allowance = await publicClient.readContract({ + address: token.address, + abi: erc20Abi, + functionName: 'allowance', + args: [account.address, PERMIT2_ADDRESS], + }); - const formattedAllowance = - currentAllowance === MAX_UINT256 - ? 'unlimited' - : `${formatUnits(currentAllowance, USDC_DECIMALS)} USDC`; - console.log(`πŸ“‹ Current Permit2 Allowance: ${formattedAllowance}\n`); + tokenStates.push({ ...token, balance, allowance }); + + const formattedBalance = `${formatUnits(balance, token.decimals)} ${token.name}`; + const formattedAllowance = + allowance === MAX_UINT256 + ? 'unlimited' + : `${formatUnits(allowance, token.decimals)} ${token.name}`; + + console.log(`πŸ’° ${token.name} (${token.address})`); + console.log(` πŸ’΅ Balance: ${formattedBalance}`); + console.log(` πŸ“‹ Permit2 Allowance: ${formattedAllowance}`); + } + console.log(); if (action === 'revoke') { - // Revoke approval by setting allowance to 0 - if (currentAllowance === 0n) { - console.log('βœ… Permit2 approval is already revoked (allowance is 0)'); - process.exit(0); + for (const token of tokenStates) { + if (token.allowance === 0n) { + console.log(`βœ… ${token.name}: Permit2 approval already revoked (allowance is 0)`); + continue; + } + + console.log(`πŸ”„ ${token.name}: Revoking Permit2 approval...`); + + const hash = await walletClient.writeContract({ + address: token.address, + abi: erc20Abi, + functionName: 'approve', + args: [PERMIT2_ADDRESS, 0n], + }); + + console.log(` πŸ“ Transaction: ${hash}`); + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + + if (receipt.status === 'success') { + console.log(` βœ… Revoked (block ${receipt.blockNumber}, gas ${receipt.gasUsed})`); + } else { + console.error(` ❌ Revoke transaction failed`); + process.exit(1); + } } + return; + } - console.log('πŸ”„ Revoking Permit2 approval (setting allowance to 0)...'); + // action === 'approve' + for (const token of tokenStates) { + if (token.allowance === MAX_UINT256) { + console.log(`βœ… ${token.name}: Permit2 already has unlimited approval`); + continue; + } + + console.log(`πŸ”„ ${token.name}: Granting unlimited Permit2 approval...`); const hash = await walletClient.writeContract({ - address: USDC_ADDRESS, + address: token.address, abi: erc20Abi, functionName: 'approve', - args: [PERMIT2_ADDRESS, 0n], + args: [PERMIT2_ADDRESS, MAX_UINT256], }); - console.log(`πŸ“ Transaction submitted: ${hash}`); - console.log('⏳ Waiting for confirmation...'); - + console.log(` πŸ“ Transaction: ${hash}`); const receipt = await publicClient.waitForTransactionReceipt({ hash }); if (receipt.status === 'success') { - console.log(`\nβœ… Permit2 approval revoked successfully!`); - console.log(` Block: ${receipt.blockNumber}`); - console.log(` Gas used: ${receipt.gasUsed}`); + console.log(` βœ… Approved (block ${receipt.blockNumber}, gas ${receipt.gasUsed})`); } else { - console.error(`\n❌ Revoke transaction failed`); + console.error(` ❌ Transaction failed`); process.exit(1); } - return; - } - - // action === 'approve' - // Check if approval already exists - if (currentAllowance === MAX_UINT256) { - console.log('βœ… Permit2 already has unlimited approval'); - process.exit(0); - } - - // Grant unlimited approval - console.log('πŸ”„ Granting unlimited Permit2 approval...'); - - const hash = await walletClient.writeContract({ - address: USDC_ADDRESS, - abi: erc20Abi, - functionName: 'approve', - args: [PERMIT2_ADDRESS, MAX_UINT256], - }); - - console.log(`πŸ“ Transaction submitted: ${hash}`); - console.log('⏳ Waiting for confirmation...'); - - const receipt = await publicClient.waitForTransactionReceipt({ hash }); - - if (receipt.status === 'success') { - console.log(`\nβœ… Permit2 approval granted successfully!`); - console.log(` Block: ${receipt.blockNumber}`); - console.log(` Gas used: ${receipt.gasUsed}`); - } else { - console.error(`\n❌ Transaction failed`); - process.exit(1); } } diff --git a/e2e/servers/express/index.ts b/e2e/servers/express/index.ts index 013a168a6c..2dd496bfac 100644 --- a/e2e/servers/express/index.ts +++ b/e2e/servers/express/index.ts @@ -23,7 +23,8 @@ dotenv.config(); const PORT = process.env.PORT || "4021"; const EVM_NETWORK = (process.env.EVM_NETWORK || "eip155:84532") as `${string}:${string}`; -const SVM_NETWORK = (process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; +const SVM_NETWORK = (process.env.SVM_NETWORK || + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") as `${string}:${string}`; const EVM_PAYEE_ADDRESS = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; @@ -42,7 +43,6 @@ if (!SVM_PAYEE_ADDRESS) { process.exit(1); } - if (!facilitatorUrl) { console.error("❌ FACILITATOR_URL environment variable is required"); process.exit(1); @@ -70,7 +70,9 @@ if (STELLAR_PAYEE_ADDRESS) { // 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( + `Facilitator account: ${process.env.EVM_PRIVATE_KEY ? process.env.EVM_PRIVATE_KEY.substring(0, 10) + "..." : "not configured"}`, +); console.log(`Using remote facilitator at: ${facilitatorUrl}`); /** @@ -215,16 +217,9 @@ app.use( payTo: EVM_PAYEE_ADDRESS, scheme: "exact", network: EVM_NETWORK, + price: "$0.001", // Use pre-parsed price with assetTransferMethod to force Permit2 - price: { - amount: "1000", // 0.001 USDC (6 decimals) - asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // Base Sepolia USDC - extra: { - assetTransferMethod: "permit2", - name: "USDC", - version: "2", - }, - }, + extra: { assetTransferMethod: "permit2" }, }, extensions: { ...declareDiscoveryExtension({ diff --git a/e2e/servers/express/package.json b/e2e/servers/express/package.json index 8150f1dd95..4756535ea6 100644 --- a/e2e/servers/express/package.json +++ b/e2e/servers/express/package.json @@ -34,4 +34,4 @@ "tsx": "^4.7.0", "typescript": "^5.3.0" } -} \ No newline at end of file +} diff --git a/e2e/servers/express/test.config.json b/e2e/servers/express/test.config.json index d10b4b9f12..748b805a84 100644 --- a/e2e/servers/express/test.config.json +++ b/e2e/servers/express/test.config.json @@ -3,11 +3,7 @@ "type": "server", "language": "typescript", "x402Version": 2, - "extensions": [ - "bazaar", - "eip2612GasSponsoring", - "erc20ApprovalGasSponsoring" - ], + "extensions": ["bazaar", "eip2612GasSponsoring", "erc20ApprovalGasSponsoring"], "endpoints": [ { "path": "/protected", @@ -48,13 +44,6 @@ "requiresPayment": true, "protocolFamily": "aptos" }, - { - "path": "/protected-stellar", - "method": "GET", - "description": "Protected endpoint requiring payment on Stellar network", - "requiresPayment": true, - "protocolFamily": "stellar" - }, { "path": "/health", "method": "GET", @@ -69,16 +58,7 @@ } ], "environment": { - "required": [ - "PORT", - "EVM_PAYEE_ADDRESS", - "SVM_PAYEE_ADDRESS", - "FACILITATOR_URL" - ], - "optional": [ - "APTOS_PAYEE_ADDRESS", - "STELLAR_PAYEE_ADDRESS", - "STELLAR_NETWORK" - ] + "required": ["PORT", "EVM_PAYEE_ADDRESS", "SVM_PAYEE_ADDRESS", "FACILITATOR_URL"], + "optional": ["APTOS_PAYEE_ADDRESS"] } } diff --git a/e2e/servers/hono/index.ts b/e2e/servers/hono/index.ts index 1392834b22..3e29980b63 100644 --- a/e2e/servers/hono/index.ts +++ b/e2e/servers/hono/index.ts @@ -24,7 +24,8 @@ dotenv.config(); const PORT = process.env.PORT || "4023"; const EVM_NETWORK = (process.env.EVM_NETWORK || "eip155:84532") as `${string}:${string}`; -const SVM_NETWORK = (process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; +const SVM_NETWORK = (process.env.SVM_NETWORK || + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") as `${string}:${string}`; const EVM_PAYEE_ADDRESS = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; @@ -43,7 +44,6 @@ if (!SVM_PAYEE_ADDRESS) { process.exit(1); } - if (!facilitatorUrl) { console.error("❌ FACILITATOR_URL environment variable is required"); process.exit(1); @@ -82,10 +82,13 @@ console.log(`Using remote facilitator at: ${facilitatorUrl}`); */ app.use("/protected-aptos", async (c, next) => { if (!APTOS_PAYEE_ADDRESS) { - return c.json({ - error: "Aptos payments not configured", - message: "APTOS_PAYEE_ADDRESS environment variable is not set", - }, 501); + return c.json( + { + error: "Aptos payments not configured", + message: "APTOS_PAYEE_ADDRESS environment variable is not set", + }, + 501, + ); } await next(); }); @@ -199,15 +202,9 @@ app.use( payTo: EVM_PAYEE_ADDRESS, scheme: "exact", network: EVM_NETWORK, - price: { - amount: "1000", - asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", - extra: { - assetTransferMethod: "permit2", - name: "USDC", - version: "2", - }, - }, + price: "$0.001", + // Use pre-parsed price with assetTransferMethod to force Permit2 + extra: { assetTransferMethod: "permit2" }, }, extensions: { ...declareDiscoveryExtension({ @@ -287,7 +284,7 @@ app.use( * 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) => { +app.get("/protected", c => { return c.json({ message: "Protected endpoint accessed successfully", timestamp: new Date().toISOString(), @@ -300,7 +297,7 @@ app.get("/protected", (c) => { * 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) => { +app.get("/protected-svm", c => { return c.json({ message: "Protected endpoint accessed successfully", timestamp: new Date().toISOString(), @@ -314,7 +311,7 @@ app.get("/protected-svm", (c) => { * Clients must provide a valid payment signature to access this endpoint. * Note: 501 check is handled by pre-middleware guard above. */ -app.get("/protected-aptos", (c) => { +app.get("/protected-aptos", c => { return c.json({ message: "Protected endpoint accessed successfully", timestamp: new Date().toISOString(), @@ -324,7 +321,7 @@ app.get("/protected-aptos", (c) => { /** * Protected Permit2 endpoint - requires Permit2 payment with EIP-2612 gas sponsoring */ -app.get("/protected-permit2", (c) => { +app.get("/protected-permit2", c => { return c.json({ message: "Permit2 endpoint accessed successfully", timestamp: new Date().toISOString(), @@ -336,7 +333,7 @@ app.get("/protected-permit2", (c) => { /** * Protected Permit2 ERC-20 endpoint - requires Permit2 payment with ERC-20 approval gas sponsoring */ -app.get("/protected-permit2-erc20", (c) => { +app.get("/protected-permit2-erc20", c => { return c.json({ message: "Permit2 ERC-20 approval endpoint accessed successfully", timestamp: new Date().toISOString(), @@ -365,7 +362,7 @@ if (STELLAR_PAYEE_ADDRESS) { * * Used to verify the server is running and responsive. */ -app.get("/health", (c) => { +app.get("/health", c => { return c.json({ status: "ok", network: EVM_NETWORK, @@ -379,7 +376,7 @@ app.get("/health", (c) => { * * Allows graceful shutdown of the server during testing. */ -app.post("/close", (c) => { +app.post("/close", c => { console.log("Received shutdown request"); // Give time for response to be sent diff --git a/e2e/servers/hono/package.json b/e2e/servers/hono/package.json index 0e486907d3..ba14bf7e2d 100644 --- a/e2e/servers/hono/package.json +++ b/e2e/servers/hono/package.json @@ -35,4 +35,4 @@ "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 8f9cd44efc..dd4ecb8a89 100644 --- a/e2e/servers/hono/test.config.json +++ b/e2e/servers/hono/test.config.json @@ -3,11 +3,7 @@ "type": "server", "language": "typescript", "x402Version": 2, - "extensions": [ - "bazaar", - "eip2612GasSponsoring", - "erc20ApprovalGasSponsoring" - ], + "extensions": ["bazaar", "eip2612GasSponsoring", "erc20ApprovalGasSponsoring"], "endpoints": [ { "path": "/protected", @@ -48,13 +44,6 @@ "requiresPayment": true, "protocolFamily": "aptos" }, - { - "path": "/protected-stellar", - "method": "GET", - "description": "Protected endpoint requiring payment on Stellar network", - "requiresPayment": true, - "protocolFamily": "stellar" - }, { "path": "/health", "method": "GET", @@ -69,16 +58,7 @@ } ], "environment": { - "required": [ - "PORT", - "EVM_PAYEE_ADDRESS", - "SVM_PAYEE_ADDRESS", - "FACILITATOR_URL" - ], - "optional": [ - "APTOS_PAYEE_ADDRESS", - "STELLAR_PAYEE_ADDRESS", - "STELLAR_NETWORK" - ] + "required": ["PORT", "EVM_PAYEE_ADDRESS", "SVM_PAYEE_ADDRESS", "FACILITATOR_URL"], + "optional": ["APTOS_PAYEE_ADDRESS"] } -} \ No newline at end of file +} diff --git a/e2e/servers/next/app/api/close/route.ts b/e2e/servers/next/app/api/close/route.ts index d2132c17c3..94835fd216 100644 --- a/e2e/servers/next/app/api/close/route.ts +++ b/e2e/servers/next/app/api/close/route.ts @@ -20,4 +20,4 @@ export async function POST() { return NextResponse.json({ message: "Shutting down gracefully", }); -} \ No newline at end of file +} diff --git a/e2e/servers/next/app/api/health/route.ts b/e2e/servers/next/app/api/health/route.ts index 8a57257b35..1c3a28cfc3 100644 --- a/e2e/servers/next/app/api/health/route.ts +++ b/e2e/servers/next/app/api/health/route.ts @@ -12,4 +12,4 @@ export async function GET() { return NextResponse.json({ status: "healthy", }); -} \ No newline at end of file +} diff --git a/e2e/servers/next/app/api/protected-aptos-proxy/route.ts b/e2e/servers/next/app/api/protected-aptos-proxy/route.ts index 2b3a78839d..8b33590351 100644 --- a/e2e/servers/next/app/api/protected-aptos-proxy/route.ts +++ b/e2e/servers/next/app/api/protected-aptos-proxy/route.ts @@ -11,10 +11,13 @@ export const runtime = "nodejs"; */ export async function GET() { if (!APTOS_PAYEE_ADDRESS) { - return NextResponse.json({ - error: "Aptos payments not configured", - message: "APTOS_PAYEE_ADDRESS environment variable is not set", - }, { status: 501 }); + return NextResponse.json( + { + error: "Aptos payments not configured", + message: "APTOS_PAYEE_ADDRESS environment variable is not set", + }, + { status: 501 }, + ); } return NextResponse.json({ message: "Protected endpoint accessed successfully", diff --git a/e2e/servers/next/app/api/protected-proxy/route.ts b/e2e/servers/next/app/api/protected-proxy/route.ts index 739c214d86..294d181b3b 100644 --- a/e2e/servers/next/app/api/protected-proxy/route.ts +++ b/e2e/servers/next/app/api/protected-proxy/route.ts @@ -14,4 +14,3 @@ export async function GET() { 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 index f908c8c635..69007d6963 100644 --- a/e2e/servers/next/app/api/protected-svm-proxy/route.ts +++ b/e2e/servers/next/app/api/protected-svm-proxy/route.ts @@ -14,4 +14,3 @@ export async function GET() { 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 index 57b3736191..ea63bc43c2 100644 --- a/e2e/servers/next/app/api/protected-svm-withx402/route.ts +++ b/e2e/servers/next/app/api/protected-svm-withx402/route.ts @@ -45,4 +45,3 @@ export const GET = withX402( }, server, ); - diff --git a/e2e/servers/next/app/api/protected-withx402/route.ts b/e2e/servers/next/app/api/protected-withx402/route.ts index a7bbbb2f1c..5edb0c1e1d 100644 --- a/e2e/servers/next/app/api/protected-withx402/route.ts +++ b/e2e/servers/next/app/api/protected-withx402/route.ts @@ -46,4 +46,3 @@ export const GET = withX402( }, server, ); - diff --git a/e2e/servers/next/next.config.ts b/e2e/servers/next/next.config.ts index db0a372753..cb651cdc00 100644 --- a/e2e/servers/next/next.config.ts +++ b/e2e/servers/next/next.config.ts @@ -1,6 +1,5 @@ import type { NextConfig } from "next"; -const nextConfig: NextConfig = { -}; +const nextConfig: NextConfig = {}; export default nextConfig; diff --git a/e2e/servers/next/package.json b/e2e/servers/next/package.json index 27083854bd..e709f385b2 100644 --- a/e2e/servers/next/package.json +++ b/e2e/servers/next/package.json @@ -46,4 +46,4 @@ "tailwindcss": "^3.4.1", "typescript": "^5" } -} \ No newline at end of file +} diff --git a/e2e/servers/next/proxy.ts b/e2e/servers/next/proxy.ts index 5021a801da..356c63fb93 100644 --- a/e2e/servers/next/proxy.ts +++ b/e2e/servers/next/proxy.ts @@ -3,7 +3,6 @@ import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { ExactSvmScheme } from "@x402/svm/exact/server"; import { ExactAptosScheme } from "@x402/aptos/exact/server"; -import { ExactStellarScheme } from "@x402/stellar/exact/server"; import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; import { declareEip2612GasSponsoringExtension, @@ -13,11 +12,10 @@ import { 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 APTOS_PAYEE_ADDRESS = process.env.APTOS_PAYEE_ADDRESS as string; -export const STELLAR_PAYEE_ADDRESS = process.env.STELLAR_PAYEE_ADDRESS as string | undefined; export const EVM_NETWORK = (process.env.EVM_NETWORK || "eip155:84532") as `${string}:${string}`; -export const SVM_NETWORK = (process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; +export const SVM_NETWORK = (process.env.SVM_NETWORK || + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; export const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; -export const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") as `${string}:${string}`; const facilitatorUrl = process.env.FACILITATOR_URL; if (!facilitatorUrl) { @@ -37,17 +35,11 @@ server.register("solana:*", new ExactSvmScheme()); if (APTOS_PAYEE_ADDRESS) { server.register("aptos:*", new ExactAptosScheme()); } -if (STELLAR_PAYEE_ADDRESS) { - server.register("stellar:*", new ExactStellarScheme()); -} // Register Bazaar discovery extension server.registerExtension(bazaarResourceServerExtension); console.log(`Using remote facilitator at: ${facilitatorUrl}`); -if (STELLAR_PAYEE_ADDRESS) { - console.log(`Stellar Payee Address: ${STELLAR_PAYEE_ADDRESS}`); -} export const proxy = paymentProxy( { @@ -103,47 +95,40 @@ export const proxy = paymentProxy( }, ...(APTOS_PAYEE_ADDRESS ? { - "/api/protected-aptos-proxy": { - accepts: { - payTo: APTOS_PAYEE_ADDRESS, - scheme: "exact", - price: "$0.001", - network: APTOS_NETWORK, - }, - extensions: { - ...declareDiscoveryExtension({ - output: { - example: { - message: "Protected endpoint accessed successfully", - timestamp: "2024-01-01T00:00:00Z", - }, - schema: { - properties: { - message: { type: "string" }, - timestamp: { type: "string" }, + "/api/protected-aptos-proxy": { + accepts: { + payTo: APTOS_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: APTOS_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"], }, - required: ["message", "timestamp"], }, - }, - }), + }), + }, }, - }, - } + } : {}), "/api/protected-permit2-proxy": { accepts: { payTo: EVM_PAYEE_ADDRESS, scheme: "exact", network: EVM_NETWORK, - price: { - amount: "1000", - asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", - extra: { - assetTransferMethod: "permit2", - name: "USDC", - version: "2", - }, - }, + price: "$0.001", + extra: { assetTransferMethod: "permit2" }, }, extensions: { ...declareDiscoveryExtension({ @@ -183,35 +168,6 @@ export const proxy = paymentProxy( ...declareErc20ApprovalGasSponsoringExtension(), }, }, - ...(STELLAR_PAYEE_ADDRESS - ? { - "/api/protected-stellar-proxy": { - accepts: { - payTo: STELLAR_PAYEE_ADDRESS, - scheme: "exact", - price: "$0.001", - network: STELLAR_NETWORK, - }, - extensions: { - ...declareDiscoveryExtension({ - output: { - example: { - message: "Protected Stellar 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 ); @@ -223,6 +179,5 @@ export const config = { "/api/protected-aptos-proxy", "/api/protected-permit2-proxy", "/api/protected-permit2-erc20-proxy", - "/api/protected-stellar-proxy", ], }; diff --git a/e2e/servers/next/test.config.json b/e2e/servers/next/test.config.json index 07b63d174d..835d4329d3 100644 --- a/e2e/servers/next/test.config.json +++ b/e2e/servers/next/test.config.json @@ -3,11 +3,7 @@ "type": "server", "language": "typescript", "x402Version": 2, - "extensions": [ - "bazaar", - "eip2612GasSponsoring", - "erc20ApprovalGasSponsoring" - ], + "extensions": ["bazaar", "eip2612GasSponsoring", "erc20ApprovalGasSponsoring"], "endpoints": [ { "path": "/api/protected-proxy", @@ -48,13 +44,6 @@ "requiresPayment": true, "protocolFamily": "aptos" }, - { - "path": "/api/protected-stellar-proxy", - "method": "GET", - "description": "Protected endpoint using proxy middleware on Stellar", - "requiresPayment": true, - "protocolFamily": "stellar" - }, { "path": "/api/protected-withx402", "method": "GET", @@ -70,13 +59,6 @@ "requiresPayment": true, "protocolFamily": "svm" }, - { - "path": "/api/protected-stellar-withx402", - "method": "GET", - "description": "Protected endpoint using withX402 wrapper on Stellar", - "requiresPayment": true, - "protocolFamily": "stellar" - }, { "path": "/api/health", "method": "GET", @@ -91,16 +73,7 @@ } ], "environment": { - "required": [ - "PORT", - "EVM_PAYEE_ADDRESS", - "SVM_PAYEE_ADDRESS", - "FACILITATOR_URL" - ], - "optional": [ - "APTOS_PAYEE_ADDRESS", - "STELLAR_PAYEE_ADDRESS", - "STELLAR_NETWORK" - ] + "required": ["PORT", "EVM_PAYEE_ADDRESS", "SVM_PAYEE_ADDRESS", "FACILITATOR_URL"], + "optional": ["APTOS_PAYEE_ADDRESS"] } -} \ No newline at end of file +} diff --git a/e2e/servers/next/tsconfig.json b/e2e/servers/next/tsconfig.json index aa175a3f81..6a3c51ac3f 100644 --- a/e2e/servers/next/tsconfig.json +++ b/e2e/servers/next/tsconfig.json @@ -1,11 +1,7 @@ { "compilerOptions": { "target": "ES2022", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], + "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": false, @@ -23,9 +19,7 @@ } ], "paths": { - "@/*": [ - "./*" - ] + "@/*": ["./*"] } }, "include": [ @@ -36,7 +30,5 @@ ".next/types/**/*.ts", ".next/dev/types/**/*.ts" ], - "exclude": [ - "node_modules" - ] + "exclude": ["node_modules"] } diff --git a/go/go.mod b/go/go.mod index ee54c97400..c23cc41507 100644 --- a/go/go.mod +++ b/go/go.mod @@ -15,6 +15,8 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 ) +require github.com/google/uuid v1.6.0 + require ( filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -45,7 +47,6 @@ require ( github.com/goccy/go-json v0.10.4 // indirect github.com/goccy/go-yaml v1.18.0 // indirect github.com/google/jsonschema-go v0.4.2 // 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 diff --git a/go/mechanisms/evm/constants.go b/go/mechanisms/evm/constants.go index cb75136cf8..768a1cfa53 100644 --- a/go/mechanisms/evm/constants.go +++ b/go/mechanisms/evm/constants.go @@ -95,14 +95,16 @@ var ( Decimals: DefaultDecimals, }, }, - // MegaETH Mainnet + // MegaETH Mainnet (uses Permit2 instead of EIP-3009, supports EIP-2612) "eip155:4326": { ChainID: ChainIDMegaETH, DefaultAsset: AssetInfo{ - Address: "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7", // USDM (MegaUSD) - Name: "MegaUSD", - Version: "1", - Decimals: 18, + Address: "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7", // USDM (MegaUSD) + Name: "MegaUSD", + Version: "1", + Decimals: 18, + AssetTransferMethod: AssetTransferMethodPermit2, + SupportsEip2612: true, }, }, // Monad Mainnet diff --git a/go/mechanisms/evm/exact/server/scheme.go b/go/mechanisms/evm/exact/server/scheme.go index b31193d5b2..d72f4e4c35 100644 --- a/go/mechanisms/evm/exact/server/scheme.go +++ b/go/mechanisms/evm/exact/server/scheme.go @@ -176,6 +176,23 @@ func (s *ExactEvmScheme) defaultMoneyConversion(amount float64, network x402.Net return x402.AssetAmount{}, err } + if config.DefaultAsset.Address == "" { + return x402.AssetAmount{}, fmt.Errorf("no default stablecoin configured for network %s; use RegisterMoneyParser or specify an explicit AssetAmount", networkStr) + } + + // EIP-3009 tokens always need name/version for their transferWithAuthorization domain. + // Permit2 tokens only need them if the token supports EIP-2612 (for gasless permit signing). + // Omitting name/version for permit2 tokens signals the client to skip EIP-2612 and use ERC-20 approval gas sponsoring instead. + extra := map[string]interface{}{} + includeEip712Domain := config.DefaultAsset.AssetTransferMethod == "" || config.DefaultAsset.SupportsEip2612 + if includeEip712Domain { + extra["name"] = config.DefaultAsset.Name + extra["version"] = config.DefaultAsset.Version + } + if config.DefaultAsset.AssetTransferMethod != "" { + extra["assetTransferMethod"] = string(config.DefaultAsset.AssetTransferMethod) + } + // Check if amount appears to already be in smallest unit // (e.g., 1500000 for $1.50 USDC is likely already in smallest unit, not $1.5M) oneUnit := float64(1) @@ -188,7 +205,7 @@ func (s *ExactEvmScheme) defaultMoneyConversion(amount float64, network x402.Net return x402.AssetAmount{ Asset: config.DefaultAsset.Address, Amount: fmt.Sprintf("%.0f", amount), - Extra: make(map[string]interface{}), + Extra: extra, }, nil } @@ -202,7 +219,7 @@ func (s *ExactEvmScheme) defaultMoneyConversion(amount float64, network x402.Net return x402.AssetAmount{ Asset: config.DefaultAsset.Address, Amount: parsedAmount.String(), - Extra: make(map[string]interface{}), + Extra: extra, }, nil } @@ -247,13 +264,15 @@ func (s *ExactEvmScheme) EnhancePaymentRequirements( requirements.Extra = make(map[string]interface{}) } - // Add token name and version for EIP-712 signing - // ONLY add if not already present (client may have specified exact values) - if _, ok := requirements.Extra["name"]; !ok { - requirements.Extra["name"] = assetInfo.Name - } - if _, ok := requirements.Extra["version"]; !ok { - requirements.Extra["version"] = assetInfo.Version + // EIP-3009 tokens always need name/version; permit2 tokens only if they support EIP-2612 + includeEip712Domain := assetInfo.AssetTransferMethod == "" || assetInfo.SupportsEip2612 + if includeEip712Domain { + if _, ok := requirements.Extra["name"]; !ok { + requirements.Extra["name"] = assetInfo.Name + } + if _, ok := requirements.Extra["version"]; !ok { + requirements.Extra["version"] = assetInfo.Version + } } // Copy extensions from supportedKind if provided diff --git a/go/mechanisms/evm/types.go b/go/mechanisms/evm/types.go index 1de1a713b4..5c705196e4 100644 --- a/go/mechanisms/evm/types.go +++ b/go/mechanisms/evm/types.go @@ -274,10 +274,12 @@ type TransactionReceipt struct { // AssetInfo contains information about an ERC20 token type AssetInfo struct { - Address string - Name string - Version string - Decimals int + Address string + Name string + Version string + Decimals int + AssetTransferMethod AssetTransferMethod + SupportsEip2612 bool } // NetworkConfig contains network-specific configuration diff --git a/python/x402/changelog.d/1359.bugfix.md b/python/x402/changelog.d/1359.bugfix.md new file mode 100644 index 0000000000..ae54c75816 --- /dev/null +++ b/python/x402/changelog.d/1359.bugfix.md @@ -0,0 +1 @@ +Added assetTransferMethod and supportsEip2612 flag to defaultAssets diff --git a/python/x402/mechanisms/evm/__init__.py b/python/x402/mechanisms/evm/__init__.py index fbaa5786df..375436d273 100644 --- a/python/x402/mechanisms/evm/__init__.py +++ b/python/x402/mechanisms/evm/__init__.py @@ -91,7 +91,6 @@ # V1 legacy constants (re-exported for backward compatibility) from .v1.constants import ( - NETWORK_ALIASES, V1_NETWORK_CHAIN_IDS, V1_NETWORKS, ) @@ -113,7 +112,6 @@ "ERC6492_MAGIC_VALUE", "EIP1271_MAGIC_VALUE", "NETWORK_CONFIGS", - "NETWORK_ALIASES", "V1_NETWORKS", "V1_NETWORK_CHAIN_IDS", "ERR_INVALID_SIGNATURE", diff --git a/python/x402/mechanisms/evm/constants.py b/python/x402/mechanisms/evm/constants.py index 27bcca554e..2531b26b4d 100644 --- a/python/x402/mechanisms/evm/constants.py +++ b/python/x402/mechanisms/evm/constants.py @@ -50,8 +50,8 @@ ERR_TRANSACTION_FAILED = "transaction_failed" -class AssetInfo(TypedDict): - """Information about a token asset.""" +class _AssetInfoRequired(TypedDict): + """Required fields for a token asset.""" address: str name: str @@ -59,34 +59,27 @@ class AssetInfo(TypedDict): decimals: int -class NetworkConfig(TypedDict): - """Configuration for an EVM network.""" +class AssetInfo(_AssetInfoRequired, total=False): + """Information about a token asset.""" + + asset_transfer_method: str + supports_eip2612: bool + + +class _NetworkConfigRequired(TypedDict): + """Required fields for an EVM network configuration.""" chain_id: int + + +class NetworkConfig(_NetworkConfigRequired, total=False): + """Configuration for an EVM network.""" + default_asset: AssetInfo - supported_assets: dict[str, AssetInfo] # Network configurations NETWORK_CONFIGS: dict[str, NetworkConfig] = { - # Ethereum Mainnet - "eip155:1": { - "chain_id": 1, - "default_asset": { - "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - "supported_assets": { - "USDC": { - "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - }, - }, # Base Mainnet "eip155:8453": { "chain_id": 8453, @@ -96,14 +89,6 @@ class NetworkConfig(TypedDict): "version": "2", "decimals": 6, }, - "supported_assets": { - "USDC": { - "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - }, }, # Base Sepolia (Testnet) "eip155:84532": { @@ -114,52 +99,8 @@ class NetworkConfig(TypedDict): "version": "2", "decimals": 6, }, - "supported_assets": { - "USDC": { - "address": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", - "name": "USDC", - "version": "2", - "decimals": 6, - }, - }, }, - # Polygon Mainnet - "eip155:137": { - "chain_id": 137, - "default_asset": { - "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - "supported_assets": { - "USDC": { - "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - }, - }, - # Avalanche C-Chain - "eip155:43114": { - "chain_id": 43114, - "default_asset": { - "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - "supported_assets": { - "USDC": { - "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - }, - }, - # MegaETH Mainnet + # MegaETH Mainnet (uses Permit2 instead of EIP-3009, supports EIP-2612) "eip155:4326": { "chain_id": 4326, "default_asset": { @@ -167,14 +108,8 @@ class NetworkConfig(TypedDict): "name": "MegaUSD", "version": "1", "decimals": 18, - }, - "supported_assets": { - "USDM": { - "address": "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7", - "name": "MegaUSD", - "version": "1", - "decimals": 18, - }, + "asset_transfer_method": "permit2", + "supports_eip2612": True, }, }, # Monad Mainnet @@ -186,19 +121,11 @@ class NetworkConfig(TypedDict): "version": "2", "decimals": 6, }, - "supported_assets": { - "USDC": { - "address": "0x754704Bc059F8C67012fEd69BC8A327a5aafb603", - "name": "USD Coin", - "version": "2", - "decimals": 6, - }, - }, }, } # V1 legacy constants are in x402.mechanisms.evm.v1.constants -# (NETWORK_ALIASES, V1_NETWORKS, V1_NETWORK_CHAIN_IDS) +# (V1_NETWORKS, V1_NETWORK_CHAIN_IDS, V1_DEFAULT_ASSETS) # EIP-3009 ABIs TRANSFER_WITH_AUTHORIZATION_VRS_ABI = [ diff --git a/python/x402/mechanisms/evm/exact/server.py b/python/x402/mechanisms/evm/exact/server.py index 72d6743787..3534c1f348 100644 --- a/python/x402/mechanisms/evm/exact/server.py +++ b/python/x402/mechanisms/evm/exact/server.py @@ -105,6 +105,7 @@ def enhance_payment_requirements( - Fills in default asset if not specified - Adds EIP-712 domain parameters (name, version) to extra + - Adds assetTransferMethod to extra when present on the asset - Converts decimal amounts to smallest unit Args: @@ -119,42 +120,81 @@ def enhance_payment_requirements( # Default asset if not requirements.asset: - requirements.asset = config["default_asset"]["address"] - - asset_info = get_asset_info(str(requirements.network), requirements.asset) + default = config.get("default_asset") + if not default or not default.get("address"): + raise ValueError( + f"No default stablecoin configured for network {requirements.network}; " + "use register_money_parser or specify an explicit asset address" + ) + requirements.asset = default["address"] + + try: + asset_info = get_asset_info(str(requirements.network), requirements.asset) + except ValueError: + asset_info = None # Ensure amount is in smallest unit if "." in requirements.amount: + if asset_info is None: + raise ValueError( + f"Token {requirements.asset} is not a registered asset for network " + f"{requirements.network}; provide amount in atomic units" + ) requirements.amount = str(parse_amount(requirements.amount, asset_info["decimals"])) # Add EIP-712 domain params if requirements.extra is None: requirements.extra = {} - if "name" not in requirements.extra: - requirements.extra["name"] = asset_info["name"] - if "version" not in requirements.extra: - requirements.extra["version"] = asset_info["version"] + if asset_info is not None: + atm = asset_info.get("asset_transfer_method") + include_eip712_domain = not atm or asset_info.get("supports_eip2612", False) + + if include_eip712_domain: + if "name" not in requirements.extra: + requirements.extra["name"] = asset_info["name"] + if "version" not in requirements.extra: + requirements.extra["version"] = asset_info["version"] + if "assetTransferMethod" not in requirements.extra and atm: + requirements.extra["assetTransferMethod"] = atm return requirements def _default_money_conversion(self, amount: float, network: str) -> AssetAmount: - """Convert decimal amount to USDC AssetAmount. + """Convert decimal amount to network's default stablecoin AssetAmount. Args: amount: Decimal amount (e.g., 1.50). network: Network identifier. Returns: - AssetAmount in USDC. + AssetAmount for the network's default stablecoin. + + Raises: + ValueError: If no default stablecoin is configured for the network. """ config = get_network_config(network) - asset = config["default_asset"] + asset = config.get("default_asset") + + if not asset or not asset.get("address"): + raise ValueError( + f"No default stablecoin configured for network {network}; " + "use register_money_parser or specify an explicit AssetAmount" + ) - # Convert to smallest unit (6 decimals for USDC) token_amount = int(amount * (10 ** asset["decimals"])) + atm = asset.get("asset_transfer_method") + include_eip712_domain = not atm or asset.get("supports_eip2612", False) + + extra: dict = {} + if include_eip712_domain: + extra["name"] = asset["name"] + extra["version"] = asset["version"] + if atm: + extra["assetTransferMethod"] = atm + return AssetAmount( amount=str(token_amount), asset=asset["address"], - extra={"name": asset["name"], "version": asset["version"]}, + extra=extra, ) diff --git a/python/x402/mechanisms/evm/utils.py b/python/x402/mechanisms/evm/utils.py index d515f25833..223ca528d4 100644 --- a/python/x402/mechanisms/evm/utils.py +++ b/python/x402/mechanisms/evm/utils.py @@ -45,6 +45,9 @@ def get_evm_chain_id(network: str) -> int: def get_network_config(network: str) -> NetworkConfig: """Get configuration for a CAIP-2 network identifier (eip155:CHAIN_ID). + Returns a full config for known networks, or a minimal config (chain_id only) + for any valid but unknown eip155 network. + Args: network: Network identifier in CAIP-2 format. @@ -52,64 +55,60 @@ def get_network_config(network: str) -> NetworkConfig: Network configuration. Raises: - ValueError: If network is not configured. + ValueError: If the network format is invalid or not an eip155 network. """ if network in NETWORK_CONFIGS: return NETWORK_CONFIGS[network] - raise ValueError(f"No configuration for network: {network} (expected eip155:CHAIN_ID)") + if network.startswith("eip155:"): + try: + chain_id = int(network.split(":")[1]) + return {"chain_id": chain_id} + except (IndexError, ValueError) as e: + raise ValueError(f"Invalid CAIP-2 network format: {network}") from e + + raise ValueError(f"Unsupported network format: {network} (expected eip155:CHAIN_ID)") -def get_asset_info(network: str, asset_symbol_or_address: str) -> AssetInfo: - """Get asset info by symbol or address. +def get_asset_info(network: str, asset_address: str) -> AssetInfo: + """Get asset info by address. + + Returns the full default asset info if the address matches the network's default asset. Args: - network: Network identifier. - asset_symbol_or_address: Asset symbol (e.g., "USDC") or address. + network: Network identifier in CAIP-2 format. + asset_address: Asset contract address (0x...). Returns: Asset information. Raises: - ValueError: If asset is not found. + ValueError: If the address does not match any registered asset for the network. """ config = get_network_config(network) + default = config.get("default_asset") - # Check if it's an address - if asset_symbol_or_address.startswith("0x"): - # Search by address - for asset in config["supported_assets"].values(): - if asset["address"].lower() == asset_symbol_or_address.lower(): - return asset - # Return default with provided address if not found - return { - "address": asset_symbol_or_address, - "name": config["default_asset"]["name"], - "version": config["default_asset"]["version"], - "decimals": config["default_asset"]["decimals"], - } + if default and default["address"].lower() == asset_address.lower(): + return default - # Search by symbol - symbol = asset_symbol_or_address.upper() - if symbol in config["supported_assets"]: - return config["supported_assets"][symbol] - - raise ValueError(f"Asset {asset_symbol_or_address} not found on {network}") + raise ValueError(f"Token {asset_address} is not a registered asset for network {network}.") def is_valid_network(network: str) -> bool: - """Check if network is supported. + """Check if network is a valid eip155 network identifier. Args: network: Network identifier. Returns: - True if network is supported. + True if the network is a valid eip155:CHAIN_ID format. """ + if not network.startswith("eip155:"): + return False try: - get_network_config(network) + int(network.split(":")[1]) return True - except ValueError: + except (IndexError, ValueError): return False diff --git a/python/x402/mechanisms/evm/v1/constants.py b/python/x402/mechanisms/evm/v1/constants.py index f9c57d266e..a488ec0b3d 100644 --- a/python/x402/mechanisms/evm/v1/constants.py +++ b/python/x402/mechanisms/evm/v1/constants.py @@ -1,18 +1,48 @@ """V1 legacy network constants for EVM mechanisms.""" -# Network aliases (legacy names to CAIP-2) -NETWORK_ALIASES: dict[str, str] = { - "base": "eip155:8453", - "base-mainnet": "eip155:8453", - "base-sepolia": "eip155:84532", - "ethereum": "eip155:1", - "mainnet": "eip155:1", - "polygon": "eip155:137", - "avalanche": "eip155:43114", - "megaeth": "eip155:4326", - "monad": "eip155:143", +from ..constants import AssetInfo + +# Default assets keyed by v1 legacy network name. +V1_DEFAULT_ASSETS: dict[str, AssetInfo] = { + "ethereum": { + "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "name": "USD Coin", + "version": "2", + "decimals": 6, + }, + "base": { + "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "name": "USD Coin", + "version": "2", + "decimals": 6, + }, + "base-sepolia": { + "address": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "name": "USDC", + "version": "2", + "decimals": 6, + }, + "polygon": { + "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "name": "USD Coin", + "version": "2", + "decimals": 6, + }, + "avalanche": { + "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", + "name": "USD Coin", + "version": "2", + "decimals": 6, + }, + "monad": { + "address": "0x754704Bc059F8C67012fEd69BC8A327a5aafb603", + "name": "USD Coin", + "version": "2", + "decimals": 6, + }, } + # V1 supported networks (legacy name-based) V1_NETWORKS = [ "abstract", diff --git a/python/x402/mechanisms/evm/v1/utils.py b/python/x402/mechanisms/evm/v1/utils.py index e143f49dcb..7994e9a788 100644 --- a/python/x402/mechanisms/evm/v1/utils.py +++ b/python/x402/mechanisms/evm/v1/utils.py @@ -1,7 +1,7 @@ """V1 legacy network utilities for EVM mechanisms.""" -from ..constants import NETWORK_CONFIGS, AssetInfo -from .constants import NETWORK_ALIASES, V1_NETWORK_CHAIN_IDS +from ..constants import AssetInfo +from .constants import V1_DEFAULT_ASSETS, V1_NETWORK_CHAIN_IDS def get_evm_chain_id(network: str) -> int: @@ -16,62 +16,32 @@ def get_evm_chain_id(network: str) -> int: Raises: ValueError: If network is not a known v1 network. """ - if network in NETWORK_ALIASES: - caip2 = NETWORK_ALIASES[network] - return int(caip2.split(":")[1]) - if network in V1_NETWORK_CHAIN_IDS: return V1_NETWORK_CHAIN_IDS[network] raise ValueError(f"Unknown v1 network: {network}") -def get_asset_info(network: str, asset_symbol_or_address: str) -> AssetInfo: - """Get asset info for a v1 network. - - Normalizes the v1 network name to CAIP-2 and looks up in shared NETWORK_CONFIGS. +def get_asset_info(network: str, asset_address: str) -> AssetInfo: + """Get asset info for a v1 network by legacy network name. Args: - network: V1 network name. - asset_symbol_or_address: Asset symbol (e.g., "USDC") or address. + network: V1 legacy network name (e.g., "base", "polygon"). + asset_address: Asset contract address (0x...). Returns: Asset information. Raises: - ValueError: If asset is not found. + ValueError: If the network has no known default asset, or the address does not + match the registered asset for the network. """ - caip2_network = _normalize_to_caip2(network) - - if caip2_network not in NETWORK_CONFIGS: - raise ValueError(f"No configuration for v1 network: {network}") - - config = NETWORK_CONFIGS[caip2_network] - - if asset_symbol_or_address.startswith("0x"): - for asset in config["supported_assets"].values(): - if asset["address"].lower() == asset_symbol_or_address.lower(): - return asset - return { - "address": asset_symbol_or_address, - "name": config["default_asset"]["name"], - "version": config["default_asset"]["version"], - "decimals": config["default_asset"]["decimals"], - } + default = V1_DEFAULT_ASSETS.get(network) - symbol = asset_symbol_or_address.upper() - if symbol and symbol in config["supported_assets"]: - return config["supported_assets"][symbol] + if default is None: + raise ValueError(f"No default asset for v1 network: {network}") - return config["default_asset"] + if default["address"].lower() == asset_address.lower(): + return default - -def _normalize_to_caip2(network: str) -> str: - """Convert a v1 network name to CAIP-2 format.""" - if network in NETWORK_ALIASES: - return NETWORK_ALIASES[network] - - if network in V1_NETWORK_CHAIN_IDS: - return f"eip155:{V1_NETWORK_CHAIN_IDS[network]}" - - raise ValueError(f"Unknown v1 network: {network}") + raise ValueError(f"Token {asset_address} is not a registered asset for v1 network {network}.") diff --git a/python/x402/mechanisms/svm/utils.py b/python/x402/mechanisms/svm/utils.py index 76231190b6..37170f3bae 100644 --- a/python/x402/mechanisms/svm/utils.py +++ b/python/x402/mechanisms/svm/utils.py @@ -122,19 +122,17 @@ def get_asset_info(network: str, asset_address: str | None = None) -> AssetInfo: Returns: Asset information. + + Raises: + ValueError: If the address does not match the registered asset for the network. """ config = get_network_config(network) default_asset = config["default_asset"] - if asset_address and asset_address != default_asset["address"]: - # Return with provided address but default metadata - return { - "address": asset_address, - "name": default_asset["name"], - "decimals": default_asset["decimals"], - } + if not asset_address or asset_address == default_asset["address"]: + return default_asset - return default_asset + raise ValueError(f"Token {asset_address} is not a registered asset for network {network}.") def convert_to_token_amount(decimal_amount: str, decimals: int) -> str: diff --git a/python/x402/tests/unit/mechanisms/evm/test_client.py b/python/x402/tests/unit/mechanisms/evm/test_client.py index 179a80ae12..01dada6b10 100644 --- a/python/x402/tests/unit/mechanisms/evm/test_client.py +++ b/python/x402/tests/unit/mechanisms/evm/test_client.py @@ -8,9 +8,9 @@ pytest.skip("EVM client requires eth_account", allow_module_level=True) -from x402.mechanisms.evm import get_asset_info from x402.mechanisms.evm.exact import ExactEvmClientScheme from x402.mechanisms.evm.signers import EthAccountSigner +from x402.mechanisms.evm.utils import get_asset_info from x402.schemas import PaymentRequirements @@ -62,7 +62,7 @@ def test_should_accept_v2_requirements_with_amount_field(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", # USDC on Base amount="500000", # V2 uses 'amount' pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -86,7 +86,7 @@ def test_requirements_must_have_eip712_domain(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", # USDC on Base amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -162,7 +162,7 @@ def test_raw_local_account_can_sign_payload(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_asset_info(network, "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913")["address"], amount="500000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, diff --git a/python/x402/tests/unit/mechanisms/evm/test_facilitator.py b/python/x402/tests/unit/mechanisms/evm/test_facilitator.py index ba0157c505..6b40c3482c 100644 --- a/python/x402/tests/unit/mechanisms/evm/test_facilitator.py +++ b/python/x402/tests/unit/mechanisms/evm/test_facilitator.py @@ -1,6 +1,6 @@ """Tests for ExactEvmScheme facilitator.""" -from x402.mechanisms.evm import get_asset_info +from x402.mechanisms.evm import get_network_config from x402.mechanisms.evm.exact import ExactEvmFacilitatorScheme, ExactEvmSchemeConfig from x402.schemas import PaymentPayload, PaymentRequirements, ResourceInfo @@ -104,7 +104,7 @@ def test_should_reject_if_scheme_does_not_match(self): accepted=PaymentRequirements( scheme="wrong", # Wrong scheme network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -126,7 +126,7 @@ def test_should_reject_if_scheme_does_not_match(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -153,7 +153,7 @@ def test_should_reject_if_network_does_not_match(self): accepted=PaymentRequirements( scheme="exact", network="eip155:1", # Ethereum Mainnet - asset=get_asset_info("eip155:1", "USDC")["address"], + asset="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -175,7 +175,7 @@ def test_should_reject_if_network_does_not_match(self): requirements = PaymentRequirements( scheme="exact", network="eip155:8453", # Base Mainnet - asset=get_asset_info("eip155:8453", "USDC")["address"], + asset=get_network_config("eip155:8453")["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -204,7 +204,7 @@ def test_should_reject_if_eip712_domain_is_missing(self): accepted=PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -226,7 +226,7 @@ def test_should_reject_if_eip712_domain_is_missing(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -254,7 +254,7 @@ def test_should_reject_if_recipient_does_not_match(self): accepted=PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -276,7 +276,7 @@ def test_should_reject_if_recipient_does_not_match(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -304,7 +304,7 @@ def test_should_reject_if_amount_is_insufficient(self): accepted=PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -326,7 +326,7 @@ def test_should_reject_if_amount_is_insufficient(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -358,7 +358,7 @@ def test_should_fail_settlement_if_verification_fails(self): accepted=PaymentRequirements( scheme="wrong", # Wrong scheme network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, @@ -380,7 +380,7 @@ def test_should_fail_settlement_if_verification_fails(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x0987654321098765432109876543210987654321", max_timeout_seconds=3600, diff --git a/python/x402/tests/unit/mechanisms/evm/test_index.py b/python/x402/tests/unit/mechanisms/evm/test_index.py index 598834f135..a5d896da65 100644 --- a/python/x402/tests/unit/mechanisms/evm/test_index.py +++ b/python/x402/tests/unit/mechanisms/evm/test_index.py @@ -165,26 +165,26 @@ def test_should_return_config_for_supported_networks(self): assert config is not None assert config["chain_id"] == 8453 assert "default_asset" in config - assert "supported_assets" in config def test_should_reject_legacy_names(self): """Should reject legacy network names (use evm.v1.utils for v1).""" with pytest.raises(ValueError, match="expected eip155:CHAIN_ID"): get_network_config("base") - def test_should_raise_for_unsupported_networks(self): - """Should raise ValueError for unsupported networks.""" - with pytest.raises(ValueError, match="No configuration"): - get_network_config("eip155:99999") + def test_should_return_minimal_config_for_unknown_networks(self): + """Should return a minimal config with chain_id for valid but unconfigured networks.""" + config = get_network_config("eip155:99999") + assert config["chain_id"] == 99999 class TestGetAssetInfo: """Test get_asset_info function.""" def test_should_return_asset_info_by_symbol(self): - """Should return asset info by symbol.""" + """Should return asset info for known address (get_asset_info takes address, not symbol).""" network = "eip155:8453" - asset_info = get_asset_info(network, "USDC") + usdc_address = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" + asset_info = get_asset_info(network, usdc_address) assert asset_info["address"].startswith("0x") assert asset_info["name"] == "USD Coin" @@ -193,15 +193,16 @@ def test_should_return_asset_info_by_symbol(self): def test_should_return_asset_info_by_address(self): """Should return asset info by address.""" network = "eip155:8453" - usdc_address = get_asset_info(network, "USDC")["address"] + usdc_address = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" asset_info = get_asset_info(network, usdc_address) assert asset_info["address"].lower() == usdc_address.lower() def test_should_raise_for_unknown_asset(self): - """Should raise ValueError for unknown asset.""" - with pytest.raises(ValueError, match="Asset.*not found"): - get_asset_info("eip155:8453", "UNKNOWN") + """Should raise ValueError for an unregistered asset address.""" + unknown_address = "0x1234567890123456789012345678901234567890" + with pytest.raises(ValueError, match="not a registered asset"): + get_asset_info("eip155:8453", unknown_address) class TestIsValidNetwork: @@ -217,8 +218,8 @@ def test_should_return_false_for_legacy_names(self): assert is_valid_network("base") is False def test_should_return_false_for_unsupported_networks(self): - """Should return False for unsupported networks.""" - assert is_valid_network("eip155:99999") is False + """Should return False for non-eip155 or malformed networks; True for any valid eip155 format.""" + assert is_valid_network("eip155:99999") is True # Valid format, any chain ID assert is_valid_network("unknown-network") is False diff --git a/python/x402/tests/unit/mechanisms/evm/test_server.py b/python/x402/tests/unit/mechanisms/evm/test_server.py index 7365dbddde..0cbbd9741e 100644 --- a/python/x402/tests/unit/mechanisms/evm/test_server.py +++ b/python/x402/tests/unit/mechanisms/evm/test_server.py @@ -3,7 +3,6 @@ import pytest from x402.mechanisms.evm import ( - get_asset_info, get_network_config, ) from x402.mechanisms.evm.exact import ExactEvmServerScheme @@ -24,7 +23,7 @@ def test_should_parse_dollar_string_prices(self): result = server.parse_price("$0.10", network) assert result.amount == "100000" # 0.10 USDC = 100000 smallest units - assert result.asset == get_asset_info(network, "USDC")["address"] + assert result.asset == get_network_config(network)["default_asset"]["address"] assert result.extra == {"name": "USD Coin", "version": "2"} def test_should_parse_simple_number_string_prices(self): @@ -35,7 +34,7 @@ def test_should_parse_simple_number_string_prices(self): result = server.parse_price("0.10", network) assert result.amount == "100000" - assert result.asset == get_asset_info(network, "USDC")["address"] + assert result.asset == get_network_config(network)["default_asset"]["address"] def test_should_parse_number_prices(self): """Should parse number prices.""" @@ -45,7 +44,7 @@ def test_should_parse_number_prices(self): result = server.parse_price(0.1, network) assert result.amount == "100000" - assert result.asset == get_asset_info(network, "USDC")["address"] + assert result.asset == get_network_config(network)["default_asset"]["address"] def test_should_handle_larger_amounts(self): """Should handle larger amounts.""" @@ -68,15 +67,13 @@ def test_should_handle_whole_numbers(self): class TestEthereumMainnetNetwork: """Test Ethereum Mainnet network.""" - def test_should_use_ethereum_usdc_address(self): - """Should use Ethereum Mainnet USDC address.""" + def test_should_raise_for_network_without_default_stablecoin(self): + """Should raise ValueError when network has no default stablecoin configured.""" server = ExactEvmServerScheme() network = "eip155:1" - result = server.parse_price("1.00", network) - - assert result.asset == get_asset_info(network, "USDC")["address"] - assert result.amount == "1000000" + with pytest.raises(ValueError, match="No default stablecoin"): + server.parse_price("1.00", network) class TestBaseSepoliaNetwork: """Test Base Sepolia network.""" @@ -88,7 +85,7 @@ def test_should_use_sepolia_usdc_address(self): result = server.parse_price("1.00", network) - assert result.asset == get_asset_info(network, "USDC")["address"] + assert result.asset == get_network_config(network)["default_asset"]["address"] assert result.amount == "1000000" class TestPreParsedPriceObjects: @@ -151,7 +148,7 @@ def test_should_add_eip712_domain_to_payment_requirements(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x1234567890123456789012345678901234567890", max_timeout_seconds=3600, @@ -181,7 +178,7 @@ def test_should_preserve_existing_extra_fields(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="100000", pay_to="0x1234567890123456789012345678901234567890", max_timeout_seconds=3600, @@ -209,7 +206,7 @@ def test_should_convert_decimal_amounts_to_smallest_unit(self): requirements = PaymentRequirements( scheme="exact", network=network, - asset=get_asset_info(network, "USDC")["address"], + asset=get_network_config(network)["default_asset"]["address"], amount="1.5", # Decimal amount pay_to="0x1234567890123456789012345678901234567890", max_timeout_seconds=3600, @@ -286,7 +283,7 @@ def custom_parser(amount: float, network: str) -> AssetAmount | None: # Small amount should fall back to default (USDC) result2 = server.parse_price(50, network) - assert result2.asset == get_asset_info(network, "USDC")["address"] + assert result2.asset == get_network_config(network)["default_asset"]["address"] assert result2.amount == "50000000" # 50 * 1e6 def test_should_receive_decimal_number_not_raw_string(self): @@ -351,7 +348,7 @@ def null_parser(amount: float, network: str) -> AssetAmount | None: result = server.parse_price(1, network) # Should use default USDC - assert result.asset == get_asset_info(network, "USDC")["address"] + assert result.asset == get_network_config(network)["default_asset"]["address"] assert result.amount == "1000000" class TestMultipleParsersChainOfResponsibility: @@ -426,7 +423,7 @@ def test_should_use_default_if_all_parsers_return_null(self): result = server.parse_price(1, network) # Should use default USDC - assert result.asset == get_asset_info(network, "USDC")["address"] + assert result.asset == get_network_config(network)["default_asset"]["address"] assert result.amount == "1000000" class TestErrorHandling: @@ -552,7 +549,10 @@ def network_parser(amount: float, network: str) -> AssetAmount | None: assert sepolia_result.asset == "0xTestToken123456789012345678901234567890" mainnet_result = server.parse_price(10, "eip155:8453") - assert mainnet_result.asset == get_asset_info("eip155:8453", "USDC")["address"] + assert ( + mainnet_result.asset + == get_network_config("eip155:8453")["default_asset"]["address"] + ) def test_should_support_tiered_pricing(self): """Should support tiered pricing.""" @@ -588,7 +588,7 @@ def standard_parser(amount: float, network: str) -> AssetAmount | None: assert standard.extra.get("tier") == "standard" basic = server.parse_price(50, network) - assert basic.asset == get_asset_info(network, "USDC")["address"] + assert basic.asset == get_network_config(network)["default_asset"]["address"] class TestIntegrationWithParsePriceFlow: """Test integration with parsePrice flow.""" diff --git a/python/x402/tests/unit/mechanisms/evm/test_v1_utils.py b/python/x402/tests/unit/mechanisms/evm/test_v1_utils.py index 571fa7721f..1e5418b267 100644 --- a/python/x402/tests/unit/mechanisms/evm/test_v1_utils.py +++ b/python/x402/tests/unit/mechanisms/evm/test_v1_utils.py @@ -29,9 +29,11 @@ def test_should_resolve_monad(self): def test_should_resolve_avalanche(self): assert get_evm_chain_id("avalanche") == 43114 - def test_should_resolve_aliases(self): - assert get_evm_chain_id("base-mainnet") == 8453 - assert get_evm_chain_id("mainnet") == 1 + def test_should_reject_undefined_aliases(self): + with pytest.raises(ValueError, match="Unknown v1 network"): + get_evm_chain_id("base-mainnet") + with pytest.raises(ValueError, match="Unknown v1 network"): + get_evm_chain_id("mainnet") def test_should_reject_caip2_format(self): with pytest.raises(ValueError, match="Unknown v1 network"): @@ -46,7 +48,8 @@ class TestV1GetAssetInfo: """Test v1 get_asset_info function.""" def test_should_return_default_asset_for_base(self): - info = get_asset_info("base", "USDC") + usdc_address = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" + info = get_asset_info("base", usdc_address) assert info["address"].startswith("0x") assert info["decimals"] == 6 @@ -55,5 +58,10 @@ def test_should_return_asset_by_address(self): assert info["decimals"] == 6 def test_should_raise_for_unknown_v1_network(self): - with pytest.raises(ValueError, match="Unknown v1 network"): - get_asset_info("eip155:8453", "USDC") + with pytest.raises(ValueError, match="No default asset for v1 network"): + get_asset_info("eip155:8453", "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913") + + def test_should_raise_for_unregistered_asset_address(self): + unknown_address = "0x1234567890123456789012345678901234567890" + with pytest.raises(ValueError, match="not a registered asset"): + get_asset_info("base", unknown_address) diff --git a/typescript/.changeset/red-geese-sit.md b/typescript/.changeset/red-geese-sit.md new file mode 100644 index 0000000000..9e7f45f33d --- /dev/null +++ b/typescript/.changeset/red-geese-sit.md @@ -0,0 +1,5 @@ +--- +'@x402/evm': patch +--- + +Added assetTransferMethod and supportsEip2612 flag to defaultAssets diff --git a/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md b/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md index 2852c2f83e..e85fff8f39 100644 --- a/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md +++ b/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md @@ -10,24 +10,26 @@ When a server uses `price: "$0.10"` syntax (USD string pricing), x402 needs to k To add support for a new EVM chain, add an entry to the `stablecoins` map in `getDefaultAsset()`: ```typescript -const stablecoins: Record = { +const stablecoins: Record = { "eip155:8453": { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", name: "USD Coin", version: "2", - decimals: 6 - }, // Base mainnet USDC + decimals: 6, + }, // Base mainnet USDC (EIP-3009) // Add your chain here: "eip155:YOUR_CHAIN_ID": { address: "0xYOUR_STABLECOIN_ADDRESS", - name: "Token Name", // Must match EIP-712 domain name - version: "1", // Must match EIP-712 domain version - decimals: 6, // Token decimals (typically 6 for USDC) + name: "Token Name", // Must match EIP-712 domain name + version: "1", // Must match EIP-712 domain version + decimals: 6, // Token decimals (typically 6 for USDC) + // assetTransferMethod: "permit2", // Uncomment if token doesn't support EIP-3009 + // supportsEip2612: true, // Set if permit2 token implements EIP-2612 permit() }, }; ``` -### Required Fields +### Fields | Field | Description | |-------|-------------| @@ -35,6 +37,8 @@ const stablecoins: Record **Note**: Default assets should support EIP-3009 for the best user experience (no approval required). Tokens requiring Permit2 can be added via `registerMoneyParser` as shown above. +1. Obtain the correct EIP-712 domain `name` and `version` from the token contract +2. Check whether the token supports EIP-3009 (`transferWithAuthorization`): + - If yes: add the entry without `assetTransferMethod` (EIP-3009 is the default) + - If no: add `assetTransferMethod: "permit2"` to the entry so the client uses Permit2 automatically +3. For permit2 tokens, check whether the token supports EIP-2612 (`permit()`): + - If yes: add `supportsEip2612: true` so clients can use gasless EIP-2612 permits for Permit2 approval + - If no: omit `supportsEip2612` β€” clients will fall back to ERC-20 approval gas sponsoring +4. Add the entry to `getDefaultAsset()` in `scheme.ts` +5. Submit a PR with the chain name and rationale for the asset selection diff --git a/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts b/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts index e81c1bf120..f42d8e124b 100644 --- a/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts +++ b/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts @@ -140,12 +140,23 @@ export class ExactEvmScheme implements SchemeNetworkServer { const assetInfo = this.getDefaultAsset(network); const tokenAmount = this.convertToTokenAmount(amount.toString(), assetInfo.decimals); + // EIP-3009 tokens always need name/version for their transferWithAuthorization domain. + // Permit2 tokens only need them if the token supports EIP-2612 (for gasless permit signing). + // Omitting name/version for permit2 tokens signals the client to skip EIP-2612 and use + // ERC-20 approval gas sponsoring instead. + const includeEip712Domain = !assetInfo.assetTransferMethod || assetInfo.supportsEip2612; + return { amount: tokenAmount, asset: assetInfo.address, extra: { - name: assetInfo.name, - version: assetInfo.version, + ...(includeEip712Domain && { + name: assetInfo.name, + version: assetInfo.version, + }), + ...(assetInfo.assetTransferMethod && { + assetTransferMethod: assetInfo.assetTransferMethod, + }), }, }; } @@ -180,14 +191,25 @@ export class ExactEvmScheme implements SchemeNetworkServer { name: string; version: string; decimals: number; + assetTransferMethod?: string; + supportsEip2612?: boolean; } { - // Map of network to USDC info including EIP-712 domain parameters - // Each network has the right to determine its own default stablecoin that can be expressed as a USD string by calling servers - // NOTE: Currently only EIP-3009 supporting stablecoins can be used with this scheme - // Generic ERC20 support via EIP-2612/permit2 is planned, but not yet implemented. + // Map of network to stablecoin info including EIP-712 domain parameters. + // Each network has the right to determine its own default stablecoin that can be expressed as a USD string by calling servers. + // Tokens that don't support EIP-3009 should set assetTransferMethod: "permit2". + // For permit2 tokens, set supportsEip2612: true if the token implements EIP-2612 permit(). + // When supportsEip2612 is false/absent on a permit2 token, name/version are omitted from + // extra so the client skips the EIP-2612 path and falls back to ERC-20 approval gas sponsoring. const stablecoins: Record< string, - { address: string; name: string; version: string; decimals: number } + { + address: string; + name: string; + version: string; + decimals: number; + assetTransferMethod?: string; + supportsEip2612?: boolean; + } > = { "eip155:8453": { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", @@ -206,7 +228,15 @@ export class ExactEvmScheme implements SchemeNetworkServer { name: "MegaUSD", version: "1", decimals: 18, - }, // MegaETH mainnet USDM + assetTransferMethod: "permit2", + supportsEip2612: true, + }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612) + "eip155:143": { + address: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603", + name: "USD Coin", + version: "2", + decimals: 6, + }, // Monad mainnet USDC }; const assetInfo = stablecoins[network]; diff --git a/typescript/packages/mechanisms/evm/test/unit/server.test.ts b/typescript/packages/mechanisms/evm/test/unit/server.test.ts index 892abfd9e2..dec6b5f6b0 100644 --- a/typescript/packages/mechanisms/evm/test/unit/server.test.ts +++ b/typescript/packages/mechanisms/evm/test/unit/server.test.ts @@ -13,6 +13,7 @@ describe("ExactEvmScheme (Server)", () => { expect(result.amount).toBe("100000"); // 0.10 USDC = 100000 smallest units expect(result.asset).toBe("0x036CbD53842c5426634e7929541eC2318f3dCF7e"); expect(result.extra).toEqual({ name: "USDC", version: "2" }); + expect(result.extra).not.toHaveProperty("assetTransferMethod"); }); it("should parse simple number string prices", async () => { @@ -51,6 +52,28 @@ describe("ExactEvmScheme (Server)", () => { expect(result.asset).toBe("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"); expect(result.amount).toBe("1000000"); expect(result.extra).toEqual({ name: "USD Coin", version: "2" }); + expect(result.extra).not.toHaveProperty("assetTransferMethod"); + }); + }); + + describe("MegaETH network", () => { + const network = "eip155:4326"; + + it("should parse dollar string and include assetTransferMethod permit2", async () => { + const result = await server.parsePrice("$0.10", network); + expect(result.asset).toBe("0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7"); + expect(result.amount).toBe("100000000000000000"); // 0.10 * 10^18 + expect(result.extra).toEqual({ + name: "MegaUSD", + version: "1", + assetTransferMethod: "permit2", + }); + }); + + it("should produce correct 18-decimal amount", async () => { + const result = await server.parsePrice("1.00", network); + expect(result.amount).toBe("1000000000000000000"); // 1.00 * 10^18 + expect(result.extra).toHaveProperty("assetTransferMethod", "permit2"); }); }); From bfce5bb575478bb619ae25beff8827495cb61dfe Mon Sep 17 00:00:00 2001 From: Marcelo Salloum dos Santos Date: Wed, 4 Mar 2026 18:10:24 -0800 Subject: [PATCH 026/129] site: add Stellar testnet support to facilitator (#1452) --- typescript/pnpm-lock.yaml | 3 +++ typescript/site/app/facilitator/index.ts | 21 ++++++++++++++++++++- typescript/site/package.json | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/typescript/pnpm-lock.yaml b/typescript/pnpm-lock.yaml index 9af67e6ebc..6d8623cc6a 100644 --- a/typescript/pnpm-lock.yaml +++ b/typescript/pnpm-lock.yaml @@ -1374,6 +1374,9 @@ importers: '@x402/paywall': specifier: workspace:* version: link:../packages/http/paywall + '@x402/stellar': + specifier: workspace:* + version: link:../packages/mechanisms/stellar '@x402/svm': specifier: workspace:* version: link:../packages/mechanisms/svm diff --git a/typescript/site/app/facilitator/index.ts b/typescript/site/app/facilitator/index.ts index f1572eff0e..a8cb83ecfc 100644 --- a/typescript/site/app/facilitator/index.ts +++ b/typescript/site/app/facilitator/index.ts @@ -12,6 +12,8 @@ import { EIP2612_GAS_SPONSORING, createErc20ApprovalGasSponsoringExtension, } from "@x402/extensions"; +import { createEd25519Signer } from "@x402/stellar"; +import { ExactStellarScheme } from "@x402/stellar/exact/facilitator"; import { toFacilitatorSvmSigner } from "@x402/svm"; import { ExactSvmScheme } from "@x402/svm/exact/facilitator"; import { ExactSvmSchemeV1 } from "@x402/svm/exact/v1/facilitator"; @@ -20,7 +22,7 @@ import { privateKeyToAccount } from "viem/accounts"; import { baseSepolia } from "viem/chains"; /** - * Initialize and configure the x402 facilitator with EVM, SVM, and Aptos support + * Initialize and configure the x402 facilitator with EVM, SVM, Aptos, and Stellar support * This is called lazily on first use to support Next.js module loading * * @returns A configured x402Facilitator instance @@ -114,6 +116,23 @@ async function createFacilitator(): Promise { facilitator.register("aptos:2", new ExactAptosScheme(aptosSigner)); } + // Optionally register Stellar if configured + if (process.env.FACILITATOR_STELLAR_PRIVATE_KEY) { + const stellarSigners = process.env.FACILITATOR_STELLAR_PRIVATE_KEY.split(",") + .map(k => k.trim()) + .filter(k => k.length > 0) + .map(k => createEd25519Signer(k)); + + const feeBumpSigner = process.env.FACILITATOR_STELLAR_FEEBUMP_PRIVATE_KEY + ? createEd25519Signer(process.env.FACILITATOR_STELLAR_FEEBUMP_PRIVATE_KEY) + : undefined; + + facilitator.register( + "stellar:testnet", + new ExactStellarScheme(stellarSigners, { feeBumpSigner }), + ); + } + // Register gas sponsorship extensions for Permit2 support facilitator .registerExtension(EIP2612_GAS_SPONSORING) diff --git a/typescript/site/package.json b/typescript/site/package.json index 5efcd4a44c..7fb2786f95 100644 --- a/typescript/site/package.json +++ b/typescript/site/package.json @@ -27,6 +27,7 @@ "@x402/extensions": "workspace:*", "@x402/next": "workspace:*", "@x402/paywall": "workspace:*", + "@x402/stellar": "workspace:*", "@x402/svm": "workspace:*", "lottie-react": "^2.4.1", "motion": "^11.18.0", From 665c10c226564a65d6a2776f87946c86c0a824f3 Mon Sep 17 00:00:00 2001 From: Marcelo Salloum dos Santos Date: Wed, 4 Mar 2026 18:12:57 -0800 Subject: [PATCH 027/129] Fix: stellar fee bump signer should be listed in `getSigners()` (#1453) * fix(stellar): include feeBumpSigner in getSigners response The /facilitator/supported endpoint was not returning the feeBumpSigner address alongside regular signer addresses. This meant clients couldn't discover the fee bump signer via the supported endpoint. getSigners() now appends the feeBumpSigner address when configured, with a guard to prevent duplicates if it's also a regular signer. * refactor(stellar): unify getExtra and getSigners tests into facilitator-accessors Merge facilitator-getExtra.test.ts and facilitator-getSigners.test.ts into a single facilitator-accessors.test.ts, eliminating duplicate imports, mocks, and setup. --- .../stellar/src/exact/facilitator/scheme.ts | 8 +- .../test/unit/facilitator-accessors.test.ts | 197 ++++++++++++++++++ .../test/unit/facilitator-getExtra.test.ts | 89 -------- 3 files changed, 203 insertions(+), 91 deletions(-) create mode 100644 typescript/packages/mechanisms/stellar/test/unit/facilitator-accessors.test.ts delete mode 100644 typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts diff --git a/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts index 554302f430..ec90f599d5 100644 --- a/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts @@ -147,13 +147,17 @@ export class ExactStellarScheme implements SchemeNetworkFacilitator { /** * Get signer addresses used by this facilitator. - * For Stellar, returns all facilitator addresses. + * For Stellar, returns all facilitator addresses including the fee bump signer when configured. * * @param _ - The network identifier (unused for Stellar) * @returns Array containing all facilitator addresses */ getSigners(_: string): string[] { - return [...this.signingAddresses]; + const signers = [...this.signingAddresses]; + if (this.feeBumpSigner && !this.signingAddresses.has(this.feeBumpSigner.address)) { + signers.push(this.feeBumpSigner.address); + } + return signers; } /** diff --git a/typescript/packages/mechanisms/stellar/test/unit/facilitator-accessors.test.ts b/typescript/packages/mechanisms/stellar/test/unit/facilitator-accessors.test.ts new file mode 100644 index 0000000000..dbe5356b86 --- /dev/null +++ b/typescript/packages/mechanisms/stellar/test/unit/facilitator-accessors.test.ts @@ -0,0 +1,197 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { STELLAR_TESTNET_CAIP2 } from "../../src/constants"; +import { ExactStellarScheme } from "../../src/exact/facilitator/scheme"; +import { createEd25519Signer } from "../../src/signer"; +import * as stellarUtils from "../../src/utils"; + +vi.mock("../../src/utils", async () => { + const actual = await vi.importActual("../../src/utils"); + return { + ...actual, + getRpcClient: vi.fn(), + }; +}); + +describe("ExactStellarScheme - getExtra", () => { + const mockRpcClient = { + getLatestLedger: vi.fn(), + }; + let scheme: ExactStellarScheme; + + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockRpcClient as never); + }); + + it("should return areFeesSponsored", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer]); + + const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); + + expect(result).toEqual({ areFeesSponsored: true }); + expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); + }); + + it("should return consistent areFeesSponsored on each call", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer]); + + const result1 = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result1).toEqual({ areFeesSponsored: true }); + + const result2 = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result2).toEqual({ areFeesSponsored: true }); + + expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); + }); + + it("should use custom areFeesSponsored", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer], { areFeesSponsored: false }); + + const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result).toEqual({ areFeesSponsored: false }); + }); + + it("should return consistent areFeesSponsored with multiple signers", () => { + const signer1 = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + const signer2 = createEd25519Signer( + "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK", + STELLAR_TESTNET_CAIP2, + ); + + scheme = new ExactStellarScheme([signer1, signer2]); + + // Call getExtra multiple times to ensure consistency + for (let i = 0; i < 10; i++) { + const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); + expect(result).toEqual({ areFeesSponsored: true }); + } + + expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); + }); +}); + +describe("ExactStellarScheme - getSigners", () => { + const mockRpcClient = { + getLatestLedger: vi.fn(), + }; + + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockRpcClient as never); + }); + + it("should return all signer addresses with a single signer", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + const scheme = new ExactStellarScheme([signer]); + const signers = scheme.getSigners(STELLAR_TESTNET_CAIP2); + + expect(signers).toEqual([signer.address]); + }); + + it("should return all signer addresses with multiple signers", () => { + const signer1 = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + const signer2 = createEd25519Signer( + "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK", + STELLAR_TESTNET_CAIP2, + ); + + const scheme = new ExactStellarScheme([signer1, signer2]); + const signers = scheme.getSigners(STELLAR_TESTNET_CAIP2); + + expect(signers).toHaveLength(2); + expect(signers).toContain(signer1.address); + expect(signers).toContain(signer2.address); + }); + + it("should include feeBumpSigner address when configured", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + const feeBumpSigner = createEd25519Signer( + "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK", + STELLAR_TESTNET_CAIP2, + ); + + const scheme = new ExactStellarScheme([signer], { feeBumpSigner }); + const signers = scheme.getSigners(STELLAR_TESTNET_CAIP2); + + expect(signers).toHaveLength(2); + expect(signers).toContain(signer.address); + expect(signers).toContain(feeBumpSigner.address); + }); + + it("should not duplicate feeBumpSigner if it is also a regular signer", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + const scheme = new ExactStellarScheme([signer], { feeBumpSigner: signer }); + const signers = scheme.getSigners(STELLAR_TESTNET_CAIP2); + + expect(signers).toHaveLength(1); + expect(signers).toEqual([signer.address]); + }); + + it("should include feeBumpSigner with multiple regular signers", () => { + const signer1 = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + const signer2 = createEd25519Signer( + "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK", + STELLAR_TESTNET_CAIP2, + ); + const feeBumpSigner = createEd25519Signer( + "SACGSSH2Y7Q6P6BK3BBKGH5Z2RDSQQGD2XHOCDYQN7N6BU37HE2OLKMD", + STELLAR_TESTNET_CAIP2, + ); + + const scheme = new ExactStellarScheme([signer1, signer2], { feeBumpSigner }); + const signers = scheme.getSigners(STELLAR_TESTNET_CAIP2); + + expect(signers).toHaveLength(3); + expect(signers).toContain(signer1.address); + expect(signers).toContain(signer2.address); + expect(signers).toContain(feeBumpSigner.address); + }); + + it("should not include feeBumpSigner when not configured", () => { + const signer = createEd25519Signer( + "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", + STELLAR_TESTNET_CAIP2, + ); + + const scheme = new ExactStellarScheme([signer]); + const signers = scheme.getSigners(STELLAR_TESTNET_CAIP2); + + expect(signers).toHaveLength(1); + expect(signers).toEqual([signer.address]); + }); +}); diff --git a/typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts b/typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts deleted file mode 100644 index 84d34fbdc5..0000000000 --- a/typescript/packages/mechanisms/stellar/test/unit/facilitator-getExtra.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; -import { STELLAR_TESTNET_CAIP2 } from "../../src/constants"; -import { ExactStellarScheme } from "../../src/exact/facilitator/scheme"; -import { createEd25519Signer } from "../../src/signer"; -import * as stellarUtils from "../../src/utils"; - -vi.mock("../../src/utils", async () => { - const actual = await vi.importActual("../../src/utils"); - return { - ...actual, - getRpcClient: vi.fn(), - }; -}); - -describe("ExactStellarScheme - getExtra", () => { - const mockRpcClient = { - getLatestLedger: vi.fn(), - }; - let scheme: ExactStellarScheme; - - beforeEach(() => { - vi.clearAllMocks(); - vi.mocked(stellarUtils.getRpcClient).mockReturnValue(mockRpcClient as never); - }); - - it("should return areFeesSponsored", () => { - const signer = createEd25519Signer( - "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", - STELLAR_TESTNET_CAIP2, - ); - - scheme = new ExactStellarScheme([signer]); - - const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); - - expect(result).toEqual({ areFeesSponsored: true }); - expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); - }); - - it("should return consistent areFeesSponsored on each call", () => { - const signer = createEd25519Signer( - "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", - STELLAR_TESTNET_CAIP2, - ); - - scheme = new ExactStellarScheme([signer]); - - const result1 = scheme.getExtra(STELLAR_TESTNET_CAIP2); - expect(result1).toEqual({ areFeesSponsored: true }); - - const result2 = scheme.getExtra(STELLAR_TESTNET_CAIP2); - expect(result2).toEqual({ areFeesSponsored: true }); - - expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); - }); - - it("should use custom areFeesSponsored", () => { - const signer = createEd25519Signer( - "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", - STELLAR_TESTNET_CAIP2, - ); - - scheme = new ExactStellarScheme([signer], { areFeesSponsored: false }); - - const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); - expect(result).toEqual({ areFeesSponsored: false }); - }); - - it("should return consistent areFeesSponsored with multiple signers", () => { - const signer1 = createEd25519Signer( - "SDV3OZOPGIO6GQAVI7T6ZJ7NSNFB26JX6QZYCI64TBC7BAZY6FQVAXXK", - STELLAR_TESTNET_CAIP2, - ); - const signer2 = createEd25519Signer( - "SA6LFVPCYMDQILBRXQ2B2HRPK6DV2TX4FTQQQHWFPSCSY4H2RTCD3XAK", - STELLAR_TESTNET_CAIP2, - ); - - scheme = new ExactStellarScheme([signer1, signer2]); - - // Call getExtra multiple times to ensure consistency - for (let i = 0; i < 10; i++) { - const result = scheme.getExtra(STELLAR_TESTNET_CAIP2); - expect(result).toEqual({ areFeesSponsored: true }); - } - - expect(mockRpcClient.getLatestLedger).not.toHaveBeenCalled(); - }); -}); From 7cd93d8bf5f00386e5b0fcb424d7d4d9b0027b25 Mon Sep 17 00:00:00 2001 From: "Notorious D.E.V." Date: Fri, 6 Mar 2026 08:16:09 +0800 Subject: [PATCH 028/129] Add in-memory cache for in-flight Solana txs (#1468) * fix: add duplicate settlement mitigation for SVM across all SDKs Introduce an in-memory SettlementCache to prevent a race condition on Solana where the same payment transaction could be settled multiple times before on-chain confirmation. The cache is shared across V1 and V2 facilitator schemes so that cross-version duplicates are caught. - Add SettlementCache with 120s TTL in TypeScript, Python, and Go - Integrate cache check into facilitator settle paths (V1 and V2) - Add unit tests for duplicate detection in all three languages - Share cache across V1/V2 in Go facilitator example - Add duplicate settlement spec to scheme_exact_svm.md - Document SettlementCache in SVM READMEs for all three SDKs - Document the race condition in go/FACILITATOR.md Security section - Add merchant-facing guidance in docs/core-concepts/client-server.md and docs/core-concepts/facilitator.md for self-settling servers - Fix JSDoc lint errors in TypeScript settlement-cache.ts * refactor: optimize SettlementCache prune with early break on ordered entries Leverage insertion-order guarantees of Map (TS) and dict (Python) to break early once a non-expired entry is encountered, avoiding a full scan of the cache on every isDuplicate call. Go is left unchanged since map iteration order is not guaranteed. Also adds prune-specific unit tests for all three SDKs covering: - mixed expired/fresh entries - all expired - none expired - insertion-order early-break correctness (Python) * docs: add changelog entries for SVM duplicate settlement fix --- docs/core-concepts/client-server.md | 13 + docs/core-concepts/facilitator.md | 10 + examples/go/facilitator/basic/main.go | 6 +- .../added-svm-settlement-cache.yaml | 3 + go/FACILITATOR.md | 18 ++ go/mechanisms/svm/README.md | 18 ++ go/mechanisms/svm/constants.go | 4 + .../exact/facilitator/duplicate_tx_test.go | 54 +++++ go/mechanisms/svm/exact/facilitator/errors.go | 1 + go/mechanisms/svm/exact/facilitator/scheme.go | 24 +- .../exact/v1/facilitator/duplicate_tx_test.go | 116 +++++++++ .../svm/exact/v1/facilitator/errors.go | 1 + .../svm/exact/v1/facilitator/scheme.go | 24 +- go/mechanisms/svm/settlement_cache.go | 58 +++++ .../svm-duplicate-settlement.bugfix.md | 1 + python/x402/mechanisms/svm/README.md | 10 + python/x402/mechanisms/svm/__init__.py | 5 + python/x402/mechanisms/svm/constants.py | 5 + .../x402/mechanisms/svm/exact/facilitator.py | 23 +- python/x402/mechanisms/svm/exact/register.py | 10 +- .../mechanisms/svm/exact/v1/facilitator.py | 23 +- .../x402/mechanisms/svm/settlement_cache.py | 53 ++++ .../unit/mechanisms/svm/test_facilitator.py | 228 +++++++++++++++++- specs/schemes/exact/scheme_exact_svm.md | 19 ++ .../fix-svm-duplicate-settlement.md | 5 + typescript/packages/mechanisms/svm/README.md | 10 + .../packages/mechanisms/svm/src/constants.ts | 6 + .../svm/src/exact/facilitator/register.ts | 12 +- .../svm/src/exact/facilitator/scheme.ts | 24 +- .../svm/src/exact/v1/facilitator/scheme.ts | 24 +- .../packages/mechanisms/svm/src/index.ts | 3 + .../mechanisms/svm/src/settlement-cache.ts | 46 ++++ .../svm/test/unit/facilitator.test.ts | 210 ++++++++++++++++ .../svm/test/unit/v1/facilitator.test.ts | 89 +++++++ 34 files changed, 1137 insertions(+), 19 deletions(-) create mode 100644 go/.changes/unreleased/added-svm-settlement-cache.yaml create mode 100644 go/mechanisms/svm/exact/v1/facilitator/duplicate_tx_test.go create mode 100644 go/mechanisms/svm/settlement_cache.go create mode 100644 python/x402/changelog.d/svm-duplicate-settlement.bugfix.md create mode 100644 python/x402/mechanisms/svm/settlement_cache.py create mode 100644 typescript/.changeset/fix-svm-duplicate-settlement.md create mode 100644 typescript/packages/mechanisms/svm/src/settlement-cache.ts diff --git a/docs/core-concepts/client-server.md b/docs/core-concepts/client-server.md index b914c52f99..ecb76c4434 100644 --- a/docs/core-concepts/client-server.md +++ b/docs/core-concepts/client-server.md @@ -48,6 +48,19 @@ Servers can include: Servers do not need to manage client identities or maintain session state. Verification and settlement are handled per request. +#### Duplicate Settlement on Solana + +If your server settles payments directly on Solana (without delegating to a facilitator), be aware of a race condition: the same signed payment transaction can be submitted multiple times before the first submission is confirmed on-chain. Solana's RPC will return "success" for each submission, since the network deduplicates at the consensus level. A malicious client can exploit this to obtain access to multiple resources while only paying once. + +To mitigate this, servers that settle Solana payments themselves **must** maintain a short-lived, in-memory cache of transaction payloads currently being settled: + +1. After verification succeeds, derive a cache key from the transaction payload (e.g., the base64-encoded transaction string). +2. If the key is already present in the cache, reject the settlement with a `"duplicate_settlement"` error. +3. If the key is not present, insert it into the cache and proceed with settlement. +4. Evict entries older than 120 seconds (approximately twice the Solana blockhash lifetime). + +If you are using a facilitator, the x402 SVM libraries already include built-in duplicate settlement protection via a `SettlementCache`. See the [Exact SVM Scheme Specification](/specs/schemes/exact/scheme_exact_svm#duplicate-settlement-mitigation-recommended) for full details. + ### Communication Flow The typical flow between a client and a server in the x402 protocol is as follows: diff --git a/docs/core-concepts/facilitator.md b/docs/core-concepts/facilitator.md index 854d85f54f..0d9a537569 100644 --- a/docs/core-concepts/facilitator.md +++ b/docs/core-concepts/facilitator.md @@ -51,6 +51,16 @@ Multiple facilitators are live in production, supporting various networks includ 11. `Facilitator server` returns a `Payment Execution Response` to the resource server. 12. `Resource server` returns a response to the `Client` with a `PAYMENT-RESPONSE` header containing the `Settlement Response` as Base64-encoded JSON. On success, this is a `200 OK` with the requested resource. On failure, this is a `402 Payment Required` with error details. +### Duplicate Settlement (Solana) + +On Solana, a race condition can occur when the same payment transaction is submitted to a facilitator's `/settle` endpoint multiple times before the first submission is confirmed on-chain. Because Solana's RPC returns "success" for duplicate submissions (the network deduplicates at the consensus level), the facilitator may return a successful settlement response for each call. A malicious client could exploit this to access multiple resources while only paying once. + +To mitigate this, the x402 SVM mechanism packages include a built-in `SettlementCache` β€” a short-lived, in-memory cache that detects and rejects duplicate settlement attempts for the same transaction payload. The cache requires no external storage and entries are automatically evicted after 120 seconds (approximately twice the Solana blockhash lifetime). + +This protection is enabled by default when using the standard SVM facilitator registration helpers in TypeScript and Python. In Go, a shared `SettlementCache` instance should be passed to both V1 and V2 SVM facilitator schemes during registration. + +**If you are a merchant settling payments directly (without a facilitator), you must implement equivalent duplicate detection yourself.** See the [Exact SVM Scheme Specification](/specs/schemes/exact/scheme_exact_svm#duplicate-settlement-mitigation-recommended) for the full specification. + ### Summary The facilitator acts as an independent verification and settlement layer within the x402 protocol. It helps servers confirm payments and submit transactions onchain without requiring direct blockchain infrastructure. diff --git a/examples/go/facilitator/basic/main.go b/examples/go/facilitator/basic/main.go index 589373b230..c9ead5daa9 100644 --- a/examples/go/facilitator/basic/main.go +++ b/examples/go/facilitator/basic/main.go @@ -11,6 +11,7 @@ import ( 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" + 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" "github.com/gin-gonic/gin" @@ -61,8 +62,9 @@ func main() { 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)) + settlementCache := svmmech.NewSettlementCache() + facilitator.Register([]x402.Network{svmNetwork}, svm.NewExactSvmScheme(svmSigner, settlementCache)) + facilitator.RegisterV1([]x402.Network{"solana-devnet"}, svmv1.NewExactSvmSchemeV1(svmSigner, settlementCache)) } facilitator.OnAfterVerify(func(ctx x402.FacilitatorVerifyResultContext) error { diff --git a/go/.changes/unreleased/added-svm-settlement-cache.yaml b/go/.changes/unreleased/added-svm-settlement-cache.yaml new file mode 100644 index 0000000000..b2e32aa4f4 --- /dev/null +++ b/go/.changes/unreleased/added-svm-settlement-cache.yaml @@ -0,0 +1,3 @@ +kind: added +body: Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window +time: 2026-03-05T13:35:00.000000+09:00 diff --git a/go/FACILITATOR.md b/go/FACILITATOR.md index a45222c8d4..c45409332d 100644 --- a/go/FACILITATOR.md +++ b/go/FACILITATOR.md @@ -382,6 +382,24 @@ Facilitator signers need to: - Monitor for unusual patterns - Set transaction value limits +#### Duplicate Settlement (Solana / SVM) + +A race condition exists on Solana where the same payment transaction can be submitted to the `/settle` endpoint multiple times before the first submission is confirmed on-chain. Because Solana's RPC returns "success" for duplicate transaction submissions (the network deduplicates at the consensus level), the facilitator could return `success` to each caller. A malicious client can exploit this to obtain access to multiple resources while only paying once. + +The SVM mechanism packages include a built-in `SettlementCache` that mitigates this. When registering SVM facilitator schemes, pass a shared cache instance to both V1 and V2 schemes: + +```go +import svm "github.com/coinbase/x402/go/mechanisms/svm" + +cache := svm.NewSettlementCache() +v2Scheme := facilitator.NewExactSvmScheme(signer, cache) +v1Scheme := v1facilitator.NewExactSvmSchemeV1(signer, cache) +``` + +The cache rejects concurrent settlement attempts for the same transaction payload with a `duplicate_settlement` error. Entries are evicted after 120 seconds (approximately twice the Solana blockhash lifetime). + +See the [Exact SVM Scheme Specification](../specs/schemes/exact/scheme_exact_svm.md#duplicate-settlement-mitigation-recommended) for full details. + ### High Availability - Run multiple facilitator instances diff --git a/go/mechanisms/svm/README.md b/go/mechanisms/svm/README.md index 1a15759d59..2b05f7ace4 100644 --- a/go/mechanisms/svm/README.md +++ b/go/mechanisms/svm/README.md @@ -69,6 +69,24 @@ The **exact** scheme implements fixed-amount payments: - **Fees**: Rent and transaction fees paid by facilitator - **Confirmation**: On-chain settlement with transaction signature +## Duplicate Settlement Protection + +This package includes a built-in `SettlementCache` that prevents a known race condition on Solana where the same payment transaction could be settled multiple times before on-chain confirmation. The `NewExactSvmScheme` facilitator constructor accepts an optional `*SettlementCache` parameter β€” when the same cache instance is passed to both V1 and V2 facilitator schemes, cross-version duplicate detection is enabled. + +The cache rejects concurrent `/settle` calls that carry the same transaction payload, returning a `duplicate_settlement` error for the second and subsequent attempts. Entries are automatically evicted after 120 seconds (approximately twice the Solana blockhash lifetime). + +```go +import svm "github.com/coinbase/x402/go/mechanisms/svm" + +cache := svm.NewSettlementCache() + +// Share the same cache across V1 and V2 schemes +v2Scheme := facilitator.NewExactSvmScheme(signer, cache) +v1Scheme := v1facilitator.NewExactSvmSchemeV1(signer, cache) +``` + +For full details on the race condition and mitigation strategy, see the [Exact SVM Scheme Specification](../../specs/schemes/exact/scheme_exact_svm.md#duplicate-settlement-mitigation-recommended). + ## Future Schemes This directory currently contains only the **exact** scheme implementation. As new payment schemes are developed for Solana networks, they will be added here alongside the exact implementation: diff --git a/go/mechanisms/svm/constants.go b/go/mechanisms/svm/constants.go index b0ed5d8f21..597f8f23e1 100644 --- a/go/mechanisms/svm/constants.go +++ b/go/mechanisms/svm/constants.go @@ -44,6 +44,10 @@ const ( // ConfirmRetryDelay is the base delay between confirmation attempts ConfirmRetryDelay = 1 * time.Second + // SettlementTTL is how long a transaction is held in the duplicate settlement cache. + // Covers the Solana blockhash lifetime (~60-90s) with margin. + SettlementTTL = 120 * time.Second + // CAIP-2 network identifiers (V2) SolanaMainnetCAIP2 = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" SolanaDevnetCAIP2 = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" diff --git a/go/mechanisms/svm/exact/facilitator/duplicate_tx_test.go b/go/mechanisms/svm/exact/facilitator/duplicate_tx_test.go index 430eb420fa..5c96be2ba3 100644 --- a/go/mechanisms/svm/exact/facilitator/duplicate_tx_test.go +++ b/go/mechanisms/svm/exact/facilitator/duplicate_tx_test.go @@ -2,6 +2,7 @@ package facilitator import ( "testing" + "time" "github.com/coinbase/x402/go/mechanisms/svm" "github.com/stretchr/testify/assert" @@ -32,3 +33,56 @@ func TestErrorCodesForMitigationPlanning(t *testing.T) { assert.Equal(t, "invalid_exact_solana_payload_transaction_instructions_length", err) }) } + +func TestDuplicateSettlementCache(t *testing.T) { + t.Run("should reject duplicate transaction", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["txBase64A=="] = time.Now() + cache.Mu().Unlock() + + assert.True(t, cache.IsDuplicate("txBase64A=="), "same transaction key should be detected as duplicate") + }) + + t.Run("should not conflict with distinct transactions", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["txBase64A=="] = time.Now() + cache.Mu().Unlock() + + assert.False(t, cache.IsDuplicate("txBase64B=="), "different transaction key should not be a duplicate") + }) + + t.Run("should prune expired entries", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["expiredTx=="] = time.Now().Add(-150 * time.Second) + cache.Entries()["freshTx=="] = time.Now() + cache.Mu().Unlock() + + // IsDuplicate triggers pruning internally + assert.False(t, cache.IsDuplicate("newTx=="), "new tx should not be a duplicate") + + cache.Mu().Lock() + _, expiredExists := cache.Entries()["expiredTx=="] + _, freshExists := cache.Entries()["freshTx=="] + cache.Mu().Unlock() + + assert.False(t, expiredExists, "expired entry should be pruned") + assert.True(t, freshExists, "fresh entry should survive pruning") + }) + + t.Run("duplicate settlement error constant is correct", func(t *testing.T) { + assert.Equal(t, "duplicate_settlement", ErrDuplicateSettlement) + }) + + t.Run("constructor wires the shared cache into the scheme", func(t *testing.T) { + cache := svm.NewSettlementCache() + scheme := NewExactSvmScheme(nil, cache) + assert.Same(t, cache, scheme.settlementCache, + "scheme should hold the exact cache instance that was injected") + }) +} diff --git a/go/mechanisms/svm/exact/facilitator/errors.go b/go/mechanisms/svm/exact/facilitator/errors.go index b4c4309f9c..9142123ac7 100644 --- a/go/mechanisms/svm/exact/facilitator/errors.go +++ b/go/mechanisms/svm/exact/facilitator/errors.go @@ -30,4 +30,5 @@ const ( ErrFeePayerMismatch = "invalid_exact_solana_fee_payer_mismatch" ErrTransactionFailed = "invalid_exact_solana_transaction_failed" ErrTransactionConfirmationFailed = "invalid_exact_solana_transaction_confirmation_failed" + ErrDuplicateSettlement = "duplicate_settlement" ) diff --git a/go/mechanisms/svm/exact/facilitator/scheme.go b/go/mechanisms/svm/exact/facilitator/scheme.go index 8ba6a02181..7c846dbf85 100644 --- a/go/mechanisms/svm/exact/facilitator/scheme.go +++ b/go/mechanisms/svm/exact/facilitator/scheme.go @@ -18,13 +18,23 @@ import ( // ExactSvmScheme implements the SchemeNetworkFacilitator interface for SVM (Solana) exact payments (V2) type ExactSvmScheme struct { - signer svm.FacilitatorSvmSigner + signer svm.FacilitatorSvmSigner + settlementCache *svm.SettlementCache } -// NewExactSvmScheme creates a new ExactSvmScheme -func NewExactSvmScheme(signer svm.FacilitatorSvmSigner) *ExactSvmScheme { +// NewExactSvmScheme creates a new ExactSvmScheme. +// An optional SettlementCache may be provided to share deduplication state +// across V1 and V2 instances; if nil a new cache is created. +func NewExactSvmScheme(signer svm.FacilitatorSvmSigner, cache ...*svm.SettlementCache) *ExactSvmScheme { + var c *svm.SettlementCache + if len(cache) > 0 && cache[0] != nil { + c = cache[0] + } else { + c = svm.NewSettlementCache() + } return &ExactSvmScheme{ - signer: signer, + signer: signer, + settlementCache: c, } } @@ -244,6 +254,12 @@ func (f *ExactSvmScheme) Settle( return nil, x402.NewSettleError(ErrInvalidPayloadTransaction, verifyResp.Payer, network, "", err.Error()) } + // Duplicate settlement check: reject if this transaction is already being settled. + txKey := solanaPayload.Transaction + if f.settlementCache.IsDuplicate(txKey) { + return nil, x402.NewSettleError(ErrDuplicateSettlement, verifyResp.Payer, network, "", "duplicate transaction") + } + // Decode transaction tx, err := svm.DecodeTransaction(solanaPayload.Transaction) if err != nil { diff --git a/go/mechanisms/svm/exact/v1/facilitator/duplicate_tx_test.go b/go/mechanisms/svm/exact/v1/facilitator/duplicate_tx_test.go new file mode 100644 index 0000000000..68fabf6d6f --- /dev/null +++ b/go/mechanisms/svm/exact/v1/facilitator/duplicate_tx_test.go @@ -0,0 +1,116 @@ +package facilitator + +import ( + "testing" + "time" + + "github.com/coinbase/x402/go/mechanisms/svm" + "github.com/stretchr/testify/assert" +) + +func TestDuplicateSettlementCacheV1(t *testing.T) { + t.Run("should reject duplicate transaction", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["txBase64A=="] = time.Now() + cache.Mu().Unlock() + + assert.True(t, cache.IsDuplicate("txBase64A=="), "same transaction key should be detected as duplicate") + }) + + t.Run("should not conflict with distinct transactions", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["txBase64A=="] = time.Now() + cache.Mu().Unlock() + + assert.False(t, cache.IsDuplicate("txBase64B=="), "different transaction key should not be a duplicate") + }) + + t.Run("should prune expired entries", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["expiredTx=="] = time.Now().Add(-150 * time.Second) + cache.Entries()["freshTx=="] = time.Now() + cache.Mu().Unlock() + + // IsDuplicate triggers pruning internally + assert.False(t, cache.IsDuplicate("newTx=="), "new tx should not be a duplicate") + + cache.Mu().Lock() + _, expiredExists := cache.Entries()["expiredTx=="] + _, freshExists := cache.Entries()["freshTx=="] + cache.Mu().Unlock() + + assert.False(t, expiredExists, "expired entry should be pruned") + assert.True(t, freshExists, "fresh entry should survive pruning") + }) + + t.Run("duplicate settlement error constant is correct", func(t *testing.T) { + assert.Equal(t, "duplicate_settlement", ErrDuplicateSettlement) + }) + + t.Run("constructor wires the shared cache into the scheme", func(t *testing.T) { + cache := svm.NewSettlementCache() + scheme := NewExactSvmSchemeV1(nil, cache) + assert.Same(t, cache, scheme.settlementCache, + "scheme should hold the exact cache instance that was injected") + }) + + t.Run("should prune only expired entries and keep fresh ones", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["expired-1"] = time.Now().Add(-150 * time.Second) + cache.Entries()["expired-2"] = time.Now().Add(-130 * time.Second) + cache.Entries()["fresh-1"] = time.Now() + cache.Entries()["fresh-2"] = time.Now() + cache.Mu().Unlock() + + // Trigger prune + cache.IsDuplicate("trigger") + + cache.Mu().Lock() + _, expired1 := cache.Entries()["expired-1"] + _, expired2 := cache.Entries()["expired-2"] + _, fresh1 := cache.Entries()["fresh-1"] + _, fresh2 := cache.Entries()["fresh-2"] + _, trigger := cache.Entries()["trigger"] + cache.Mu().Unlock() + + assert.False(t, expired1, "expired entry should be pruned") + assert.False(t, expired2, "expired entry should be pruned") + assert.True(t, fresh1, "fresh entry should survive pruning") + assert.True(t, fresh2, "fresh entry should survive pruning") + assert.True(t, trigger, "newly inserted entry should be present") + }) + + t.Run("should prune all entries when all expired", func(t *testing.T) { + cache := svm.NewSettlementCache() + + cache.Mu().Lock() + cache.Entries()["old-1"] = time.Now().Add(-200 * time.Second) + cache.Entries()["old-2"] = time.Now().Add(-200 * time.Second) + cache.Entries()["old-3"] = time.Now().Add(-200 * time.Second) + cache.Mu().Unlock() + + assert.False(t, cache.IsDuplicate("old-1"), "expired entry should not be a duplicate") + assert.False(t, cache.IsDuplicate("old-2"), "expired entry should not be a duplicate") + assert.False(t, cache.IsDuplicate("old-3"), "expired entry should not be a duplicate") + }) + + t.Run("should not prune any entries when all fresh", func(t *testing.T) { + cache := svm.NewSettlementCache() + + assert.False(t, cache.IsDuplicate("new-1")) + assert.False(t, cache.IsDuplicate("new-2")) + assert.False(t, cache.IsDuplicate("new-3")) + + assert.True(t, cache.IsDuplicate("new-1"), "fresh entry should still be cached") + assert.True(t, cache.IsDuplicate("new-2"), "fresh entry should still be cached") + assert.True(t, cache.IsDuplicate("new-3"), "fresh entry should still be cached") + }) +} diff --git a/go/mechanisms/svm/exact/v1/facilitator/errors.go b/go/mechanisms/svm/exact/v1/facilitator/errors.go index 761f88c01a..980162f4c1 100644 --- a/go/mechanisms/svm/exact/v1/facilitator/errors.go +++ b/go/mechanisms/svm/exact/v1/facilitator/errors.go @@ -31,4 +31,5 @@ const ( ErrFeePayerMismatch = "invalid_exact_solana_fee_payer_mismatch" ErrTransactionFailed = "invalid_exact_solana_transaction_failed" ErrTransactionConfirmationFailed = "invalid_exact_solana_transaction_confirmation_failed" + ErrDuplicateSettlement = "duplicate_settlement" ) diff --git a/go/mechanisms/svm/exact/v1/facilitator/scheme.go b/go/mechanisms/svm/exact/v1/facilitator/scheme.go index b8282bcddc..1d289c980d 100644 --- a/go/mechanisms/svm/exact/v1/facilitator/scheme.go +++ b/go/mechanisms/svm/exact/v1/facilitator/scheme.go @@ -19,13 +19,23 @@ import ( // ExactSvmSchemeV1 implements the SchemeNetworkFacilitator interface for SVM (Solana) exact payments (V1) type ExactSvmSchemeV1 struct { - signer svm.FacilitatorSvmSigner + signer svm.FacilitatorSvmSigner + settlementCache *svm.SettlementCache } -// NewExactSvmSchemeV1 creates a new ExactSvmSchemeV1 -func NewExactSvmSchemeV1(signer svm.FacilitatorSvmSigner) *ExactSvmSchemeV1 { +// NewExactSvmSchemeV1 creates a new ExactSvmSchemeV1. +// An optional SettlementCache may be provided to share deduplication state +// across V1 and V2 instances; if nil a new cache is created. +func NewExactSvmSchemeV1(signer svm.FacilitatorSvmSigner, cache ...*svm.SettlementCache) *ExactSvmSchemeV1 { + var c *svm.SettlementCache + if len(cache) > 0 && cache[0] != nil { + c = cache[0] + } else { + c = svm.NewSettlementCache() + } return &ExactSvmSchemeV1{ - signer: signer, + signer: signer, + settlementCache: c, } } @@ -241,6 +251,12 @@ func (f *ExactSvmSchemeV1) Settle( return nil, x402.NewSettleError(ErrInvalidPayloadTransaction, verifyResp.Payer, network, "", err.Error()) } + // Duplicate settlement check: reject if this transaction is already being settled. + txKey := svmPayload.Transaction + if f.settlementCache.IsDuplicate(txKey) { + return nil, x402.NewSettleError(ErrDuplicateSettlement, verifyResp.Payer, network, "", "duplicate transaction") + } + // Decode transaction tx, err := svm.DecodeTransaction(svmPayload.Transaction) if err != nil { diff --git a/go/mechanisms/svm/settlement_cache.go b/go/mechanisms/svm/settlement_cache.go new file mode 100644 index 0000000000..f18731eecb --- /dev/null +++ b/go/mechanisms/svm/settlement_cache.go @@ -0,0 +1,58 @@ +package svm + +import ( + "sync" + "time" +) + +// SettlementCache is a thread-safe in-memory cache for deduplicating concurrent +// settlement requests. A single instance should be shared across V1 and V2 +// facilitator scheme instances so that a transaction submitted through one +// protocol version is also blocked on the other. +type SettlementCache struct { + mu sync.Mutex + entries map[string]time.Time +} + +// NewSettlementCache creates a new, empty SettlementCache. +func NewSettlementCache() *SettlementCache { + return &SettlementCache{ + entries: make(map[string]time.Time), + } +} + +// IsDuplicate returns true if key is already pending settlement (duplicate). +// Otherwise it records the key as newly pending and returns false. +// Callers should reject the settlement when this returns true. +func (c *SettlementCache) IsDuplicate(key string) bool { + c.mu.Lock() + defer c.mu.Unlock() + + c.prune() + + if _, exists := c.entries[key]; exists { + return true + } + c.entries[key] = time.Now() + return false +} + +// Entries returns a snapshot of the underlying map β€” use only in tests. +func (c *SettlementCache) Entries() map[string]time.Time { + return c.entries +} + +// Mu returns the mutex β€” use only in tests. +func (c *SettlementCache) Mu() *sync.Mutex { + return &c.mu +} + +// prune removes entries older than the settlement TTL. Caller must hold mu. +func (c *SettlementCache) prune() { + cutoff := time.Now().Add(-SettlementTTL) + for key, ts := range c.entries { + if ts.Before(cutoff) { + delete(c.entries, key) + } + } +} diff --git a/python/x402/changelog.d/svm-duplicate-settlement.bugfix.md b/python/x402/changelog.d/svm-duplicate-settlement.bugfix.md new file mode 100644 index 0000000000..4d3892721c --- /dev/null +++ b/python/x402/changelog.d/svm-duplicate-settlement.bugfix.md @@ -0,0 +1 @@ +Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window diff --git a/python/x402/mechanisms/svm/README.md b/python/x402/mechanisms/svm/README.md index 02c02e9a55..ab82614002 100644 --- a/python/x402/mechanisms/svm/README.md +++ b/python/x402/mechanisms/svm/README.md @@ -121,3 +121,13 @@ The Exact scheme creates a partially-signed transaction: Automatic ATA derivation for source and destination addresses. +## Duplicate Settlement Protection + +This package includes a built-in `SettlementCache` that prevents a known race condition on Solana where the same payment transaction could be settled multiple times before on-chain confirmation. When the facilitator scheme is registered via `register_exact_svm_facilitator()`, a single `SettlementCache` instance is automatically shared across both V1 and V2 scheme versions. + +The cache rejects concurrent `/settle` calls that carry the same transaction payload, returning a `duplicate_settlement` error for the second and subsequent attempts. Entries are automatically evicted after 120 seconds (approximately twice the Solana blockhash lifetime). + +**No additional configuration is required** β€” duplicate settlement protection is enabled by default when using the standard registration helpers. + +For full details on the race condition and mitigation strategy, see the [Exact SVM Scheme Specification](../../../../specs/schemes/exact/scheme_exact_svm.md#duplicate-settlement-mitigation-recommended). + diff --git a/python/x402/mechanisms/svm/__init__.py b/python/x402/mechanisms/svm/__init__.py index fb9c6c0d31..08947a3ffc 100644 --- a/python/x402/mechanisms/svm/__init__.py +++ b/python/x402/mechanisms/svm/__init__.py @@ -52,6 +52,9 @@ NetworkConfig, ) +# Settlement cache (shared across V1/V2 facilitator instances) +from .settlement_cache import SettlementCache + # Signer protocols from .signer import ClientSvmSigner, FacilitatorSvmSigner @@ -139,6 +142,8 @@ "ExactSvmPayloadV1", "ExactSvmPayloadV2", "TransactionInfo", + # Settlement cache + "SettlementCache", # Signer protocols "ClientSvmSigner", "FacilitatorSvmSigner", diff --git a/python/x402/mechanisms/svm/constants.py b/python/x402/mechanisms/svm/constants.py index f82443afcb..bbe8748428 100644 --- a/python/x402/mechanisms/svm/constants.py +++ b/python/x402/mechanisms/svm/constants.py @@ -85,6 +85,11 @@ ERR_FEE_PAYER_TRANSFERRING = "invalid_exact_svm_payload_transaction_fee_payer_transferring_funds" ERR_SIMULATION_FAILED = "transaction_simulation_failed" ERR_TRANSACTION_FAILED = "transaction_failed" +ERR_DUPLICATE_SETTLEMENT = "duplicate_settlement" + +# How long a transaction is held in the duplicate settlement cache (seconds). +# Covers the Solana blockhash lifetime (~60-90s) with margin. +SETTLEMENT_TTL_SECONDS = 120.0 class AssetInfo(TypedDict): diff --git a/python/x402/mechanisms/svm/exact/facilitator.py b/python/x402/mechanisms/svm/exact/facilitator.py index cc0e0cecd4..94a87419e5 100644 --- a/python/x402/mechanisms/svm/exact/facilitator.py +++ b/python/x402/mechanisms/svm/exact/facilitator.py @@ -1,5 +1,7 @@ """SVM facilitator implementation for the Exact payment scheme (V2).""" +from __future__ import annotations + import random from typing import Any @@ -20,6 +22,7 @@ from ..constants import ( COMPUTE_BUDGET_PROGRAM_ADDRESS, ERR_AMOUNT_INSUFFICIENT, + ERR_DUPLICATE_SETTLEMENT, ERR_FEE_PAYER_MISSING, ERR_FEE_PAYER_NOT_MANAGED, ERR_FEE_PAYER_TRANSFERRING, @@ -44,6 +47,7 @@ TOKEN_2022_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, ) +from ..settlement_cache import SettlementCache from ..signer import FacilitatorSvmSigner from ..types import ExactSvmPayload from ..utils import ( @@ -66,13 +70,19 @@ class ExactSvmScheme: scheme = SCHEME_EXACT caip_family = "solana:*" - def __init__(self, signer: FacilitatorSvmSigner): + def __init__( + self, + signer: FacilitatorSvmSigner, + settlement_cache: SettlementCache | None = None, + ): """Create ExactSvmScheme facilitator. Args: signer: SVM signer for verification and settlement. + settlement_cache: Optional shared settlement cache (one is created if omitted). """ self._signer = signer + self._settlement_cache = settlement_cache or SettlementCache() def get_extra(self, network: Network) -> dict[str, Any] | None: """Get mechanism-specific extra data for the supported kinds endpoint. @@ -362,6 +372,17 @@ def settle( transaction="", ) + # Duplicate settlement check: reject if this transaction is already being settled. + tx_key = svm_payload.transaction + if self._settlement_cache.is_duplicate(tx_key): + return SettleResponse( + success=False, + error_reason=ERR_DUPLICATE_SETTLEMENT, + network=network, + payer=verify_result.payer or "", + transaction="", + ) + signature = "" try: # Extract feePayer from requirements (already validated in verify) diff --git a/python/x402/mechanisms/svm/exact/register.py b/python/x402/mechanisms/svm/exact/register.py index 39ce7ce3eb..afb4b16c56 100644 --- a/python/x402/mechanisms/svm/exact/register.py +++ b/python/x402/mechanisms/svm/exact/register.py @@ -111,6 +111,9 @@ def register_exact_svm_facilitator( - V2: Specified networks - V1: All supported SVM networks + A single settlement cache is shared across V1 and V2 so that a duplicate + transaction submitted through one protocol version is also caught by the other. + Args: facilitator: x402Facilitator instance. signer: SVM signer for verification/settlement. @@ -119,17 +122,20 @@ def register_exact_svm_facilitator( Returns: Facilitator for chaining. """ + from ..settlement_cache import SettlementCache from .facilitator import ExactSvmScheme as ExactSvmFacilitatorScheme from .v1.facilitator import ExactSvmSchemeV1 as ExactSvmFacilitatorSchemeV1 - scheme = ExactSvmFacilitatorScheme(signer) + settlement_cache = SettlementCache() + + scheme = ExactSvmFacilitatorScheme(signer, settlement_cache) if isinstance(networks, str): networks = [networks] facilitator.register(networks, scheme) # Register V1 - v1_scheme = ExactSvmFacilitatorSchemeV1(signer) + v1_scheme = ExactSvmFacilitatorSchemeV1(signer, settlement_cache) facilitator.register_v1(V1_NETWORKS, v1_scheme) return facilitator diff --git a/python/x402/mechanisms/svm/exact/v1/facilitator.py b/python/x402/mechanisms/svm/exact/v1/facilitator.py index e6c2cd0b9d..389ac2f9a9 100644 --- a/python/x402/mechanisms/svm/exact/v1/facilitator.py +++ b/python/x402/mechanisms/svm/exact/v1/facilitator.py @@ -1,5 +1,7 @@ """SVM facilitator implementation for Exact payment scheme (V1 legacy).""" +from __future__ import annotations + import random from typing import Any @@ -15,6 +17,7 @@ from ...constants import ( COMPUTE_BUDGET_PROGRAM_ADDRESS, ERR_AMOUNT_INSUFFICIENT, + ERR_DUPLICATE_SETTLEMENT, ERR_FEE_PAYER_MISSING, ERR_FEE_PAYER_NOT_MANAGED, ERR_FEE_PAYER_TRANSFERRING, @@ -39,6 +42,7 @@ TOKEN_2022_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS, ) +from ...settlement_cache import SettlementCache from ...signer import FacilitatorSvmSigner from ...types import ExactSvmPayload from ...utils import ( @@ -64,13 +68,19 @@ class ExactSvmSchemeV1: scheme = SCHEME_EXACT caip_family = "solana:*" - def __init__(self, signer: FacilitatorSvmSigner): + def __init__( + self, + signer: FacilitatorSvmSigner, + settlement_cache: SettlementCache | None = None, + ): """Create ExactSvmSchemeV1 facilitator. Args: signer: SVM signer for verification/settlement. + settlement_cache: Optional shared settlement cache (one is created if omitted). """ self._signer = signer + self._settlement_cache = settlement_cache or SettlementCache() def get_extra(self, network: Network) -> dict[str, Any] | None: """Get mechanism-specific extra data. @@ -340,6 +350,17 @@ def settle( transaction="", ) + # Duplicate settlement check: reject if this transaction is already being settled. + tx_key = svm_payload.transaction + if self._settlement_cache.is_duplicate(tx_key): + return SettleResponse( + success=False, + error_reason=ERR_DUPLICATE_SETTLEMENT, + network=network, + payer=verify_result.payer or "", + transaction="", + ) + try: extra = requirements.extra or {} fee_payer = extra["feePayer"] diff --git a/python/x402/mechanisms/svm/settlement_cache.py b/python/x402/mechanisms/svm/settlement_cache.py new file mode 100644 index 0000000000..2d839eb6a8 --- /dev/null +++ b/python/x402/mechanisms/svm/settlement_cache.py @@ -0,0 +1,53 @@ +"""Thread-safe in-memory cache for deduplicating concurrent settlement requests. + +A single instance should be shared across V1 and V2 facilitator scheme +instances so that a transaction submitted through one protocol version is +also deduplicated on the other. +""" + +import threading +import time + +from .constants import SETTLEMENT_TTL_SECONDS + + +class SettlementCache: + """In-memory cache for deduplicating concurrent settlement requests. + + Thread-safe: all public methods acquire an internal lock. + """ + + def __init__(self) -> None: + self._entries: dict[str, float] = {} + self._lock = threading.Lock() + + def is_duplicate(self, key: str) -> bool: + """Return ``True`` if *key* is already pending settlement (duplicate). + + When ``False`` the key is recorded as newly pending. + Callers should reject the settlement when this returns ``True``. + """ + with self._lock: + self._prune() + if key in self._entries: + return True + self._entries[key] = time.monotonic() + return False + + # Exposed for testing (e.g. backdating entries to simulate TTL expiry). + @property + def entries(self) -> dict[str, float]: + """Direct access to the underlying dict β€” use only in tests.""" + return self._entries + + def _prune(self) -> None: + """Remove entries older than the settlement TTL. Caller must hold _lock.""" + cutoff = time.monotonic() - SETTLEMENT_TTL_SECONDS + expired = [] + for k, ts in self._entries.items(): + if ts < cutoff: + expired.append(k) + else: + break + for k in expired: + del self._entries[k] diff --git a/python/x402/tests/unit/mechanisms/svm/test_facilitator.py b/python/x402/tests/unit/mechanisms/svm/test_facilitator.py index 49a27701a6..d5eadf5eb1 100644 --- a/python/x402/tests/unit/mechanisms/svm/test_facilitator.py +++ b/python/x402/tests/unit/mechanisms/svm/test_facilitator.py @@ -1,12 +1,14 @@ """Tests for ExactSvmScheme facilitator.""" +from unittest.mock import patch + from x402.mechanisms.svm import ( SOLANA_DEVNET_CAIP2, SOLANA_MAINNET_CAIP2, USDC_DEVNET_ADDRESS, ) from x402.mechanisms.svm.exact import ExactSvmFacilitatorScheme -from x402.schemas import PaymentPayload, PaymentRequirements, ResourceInfo +from x402.schemas import PaymentPayload, PaymentRequirements, ResourceInfo, VerifyResponse class MockFacilitatorSigner: @@ -292,6 +294,154 @@ def test_get_signers_returns_signer_addresses(self): assert result == addresses +class TestDuplicateSettlementCache: + """Test duplicate settlement cache in settle method.""" + + def _make_payload(self, transaction: str) -> PaymentPayload: + return PaymentPayload( + x402_version=2, + resource=ResourceInfo( + url="http://example.com/protected", + description="Test resource", + mime_type="application/json", + ), + accepted=PaymentRequirements( + scheme="exact", + network=SOLANA_DEVNET_CAIP2, + asset=USDC_DEVNET_ADDRESS, + amount="100000", + pay_to="PayToAddress11111111111111111111111111", + max_timeout_seconds=3600, + extra={"feePayer": "FeePayer1111111111111111111111111111"}, + ), + payload={"transaction": transaction}, + ) + + def _make_requirements(self) -> PaymentRequirements: + return PaymentRequirements( + scheme="exact", + network=SOLANA_DEVNET_CAIP2, + asset=USDC_DEVNET_ADDRESS, + amount="100000", + pay_to="PayToAddress11111111111111111111111111", + max_timeout_seconds=3600, + extra={"feePayer": "FeePayer1111111111111111111111111111"}, + ) + + def test_should_reject_duplicate_settlement(self): + """Second settle call with the same transaction should be rejected.""" + signer = MockFacilitatorSigner() + facilitator = ExactSvmFacilitatorScheme(signer) + requirements = self._make_requirements() + payload = self._make_payload("sameTransactionBase64==") + + with patch.object( + facilitator, + "verify", + return_value=VerifyResponse(is_valid=True, payer="PayerAddress"), + ): + result1 = facilitator.settle(payload, requirements) + assert result1.success is True + + result2 = facilitator.settle(payload, requirements) + assert result2.success is False + assert result2.error_reason == "duplicate_settlement" + + def test_should_allow_distinct_transactions(self): + """Two different transactions should both settle successfully.""" + signer = MockFacilitatorSigner() + facilitator = ExactSvmFacilitatorScheme(signer) + requirements = self._make_requirements() + + with patch.object( + facilitator, + "verify", + return_value=VerifyResponse(is_valid=True, payer="PayerAddress"), + ): + result1 = facilitator.settle(self._make_payload("transactionA=="), requirements) + assert result1.success is True + + result2 = facilitator.settle(self._make_payload("transactionB=="), requirements) + assert result2.success is True + + def test_should_evict_cache_entries_after_ttl(self): + """Cache entries should be pruned after TTL so they no longer block locally. + + NOTE: In production the Solana RPC would still reject a re-submitted + transaction that already landed on-chain. This test only verifies that + the in-memory cache correctly prunes expired entries. + """ + signer = MockFacilitatorSigner() + facilitator = ExactSvmFacilitatorScheme(signer) + requirements = self._make_requirements() + payload = self._make_payload("expiringTransaction==") + + with patch.object( + facilitator, + "verify", + return_value=VerifyResponse(is_valid=True, payer="PayerAddress"), + ): + result1 = facilitator.settle(payload, requirements) + assert result1.success is True + + # Simulate TTL expiration by backdating the cache entry + for key in facilitator._settlement_cache.entries: + facilitator._settlement_cache.entries[key] -= 121.0 + + result2 = facilitator.settle(payload, requirements) + assert result2.success is True + + def test_shared_cache_blocks_cross_version_duplicates(self): + """V1 and V2 sharing a cache should catch cross-version duplicates.""" + from x402.mechanisms.svm.exact.v1.facilitator import ( + ExactSvmSchemeV1 as ExactSvmFacilitatorSchemeV1, + ) + from x402.mechanisms.svm.settlement_cache import SettlementCache + from x402.schemas.v1 import PaymentPayloadV1, PaymentRequirementsV1 + + signer = MockFacilitatorSigner() + shared_cache = SettlementCache() + v2 = ExactSvmFacilitatorScheme(signer, shared_cache) + v1 = ExactSvmFacilitatorSchemeV1(signer, shared_cache) + + # Settle via V2 first + with patch.object( + v2, + "verify", + return_value=VerifyResponse(is_valid=True, payer="PayerAddress"), + ): + result1 = v2.settle( + self._make_payload("crossVersionTx=="), + self._make_requirements(), + ) + assert result1.success is True + + # Same tx via V1 should be rejected by the shared cache + v1_payload = PaymentPayloadV1( + scheme="exact", + network="solana-devnet", + payload={"transaction": "crossVersionTx=="}, + ) + v1_requirements = PaymentRequirementsV1( + scheme="exact", + network="solana-devnet", + asset=USDC_DEVNET_ADDRESS, + max_amount_required="100000", + pay_to="PayToAddress11111111111111111111111111", + max_timeout_seconds=3600, + resource="https://example.com", + extra={"feePayer": "FeePayer1111111111111111111111111111"}, + ) + with patch.object( + v1, + "verify", + return_value=VerifyResponse(is_valid=True, payer="PayerAddress"), + ): + result2 = v1.settle(v1_payload, v1_requirements) + assert result2.success is False + assert result2.error_reason == "duplicate_settlement" + + class TestVerifyFeePayer: """Test fee payer verification in verify method.""" @@ -333,3 +483,79 @@ def test_should_reject_if_fee_payer_not_managed(self): assert result.is_valid is False assert result.invalid_reason == "fee_payer_not_managed_by_facilitator" + + +class TestSettlementCachePruneOptimization: + """Verify the early-break prune optimization preserves insertion-order semantics.""" + + def test_prunes_only_expired_entries_preserves_fresh_ones(self): + """Entries older than TTL are pruned; newer entries survive.""" + from x402.mechanisms.svm.settlement_cache import SettlementCache + + cache = SettlementCache() + + cache.is_duplicate("tx-a") + cache.is_duplicate("tx-b") + cache.is_duplicate("tx-c") + + # Backdate tx-a past TTL (121s), leave tx-b and tx-c fresh + base = cache.entries["tx-a"] + cache.entries["tx-a"] = base - 121.0 + + assert cache.is_duplicate("tx-a") is False, "expired entry should have been pruned" + assert cache.is_duplicate("tx-b") is True, "fresh entry should still be cached" + assert cache.is_duplicate("tx-c") is True, "fresh entry should still be cached" + + def test_prunes_all_entries_when_all_expired(self): + """When every entry is expired, all should be pruned.""" + from x402.mechanisms.svm.settlement_cache import SettlementCache + + cache = SettlementCache() + + cache.is_duplicate("tx-1") + cache.is_duplicate("tx-2") + cache.is_duplicate("tx-3") + + for k in list(cache.entries): + cache.entries[k] -= 121.0 + + assert cache.is_duplicate("tx-1") is False + assert cache.is_duplicate("tx-2") is False + assert cache.is_duplicate("tx-3") is False + + def test_prunes_nothing_when_all_fresh(self): + """When no entries are expired, none should be pruned.""" + from x402.mechanisms.svm.settlement_cache import SettlementCache + + cache = SettlementCache() + + cache.is_duplicate("tx-x") + cache.is_duplicate("tx-y") + cache.is_duplicate("tx-z") + + assert cache.is_duplicate("tx-x") is True + assert cache.is_duplicate("tx-y") is True + assert cache.is_duplicate("tx-z") is True + + def test_early_break_preserves_ordered_entries(self): + """Insertion-order iteration means the break fires at the first fresh entry.""" + from x402.mechanisms.svm.settlement_cache import SettlementCache + + cache = SettlementCache() + + # Insert A, B, C in order with small gaps + cache.is_duplicate("tx-old-1") + cache.is_duplicate("tx-old-2") + cache.is_duplicate("tx-fresh") + + # Expire only the first two + for k in ("tx-old-1", "tx-old-2"): + cache.entries[k] -= 121.0 + + # Trigger prune + cache.is_duplicate("tx-new") + + assert "tx-old-1" not in cache.entries, "first expired entry should be pruned" + assert "tx-old-2" not in cache.entries, "second expired entry should be pruned" + assert "tx-fresh" in cache.entries, "fresh entry after expired ones should survive" + assert "tx-new" in cache.entries, "newly inserted entry should be present" diff --git a/specs/schemes/exact/scheme_exact_svm.md b/specs/schemes/exact/scheme_exact_svm.md index bdf1e5e235..f2537d60d7 100644 --- a/specs/schemes/exact/scheme_exact_svm.md +++ b/specs/schemes/exact/scheme_exact_svm.md @@ -143,3 +143,22 @@ A facilitator verifying an `exact`-scheme SVM payment MUST enforce all of the fo - The `amount` in TransferChecked MUST equal `PaymentRequirements.amount` exactly. These checks are security-critical to ensure the fee payer cannot be tricked into transferring their own funds or sponsoring unintended actions. Implementations MAY introduce stricter limits (e.g., lower compute price caps) but MUST NOT relax the above constraints. + +## Duplicate Settlement Mitigation (RECOMMENDED) + +### Vulnerability + +A race condition exists in the settlement flow: if the same payment transaction is submitted to the facilitator's `/settle` endpoint multiple times before the first submission is confirmed on-chain, each call may return a successful response. + +Although Solana's transaction deduplication ensures the transfer only executes once on-chain, the RPC returns "success", and hence the facilitator could return `success` to each caller. A malicious client can exploit this to obtain access to multiple resources while only paying once. + +### Recommended Mitigation + +Merchants and/or Facilitators SHOULD maintain a short-term, in-memory cache of transaction payloads that are currently being settled. Before proceeding with settlement, the merchant/facilitator checks whether the transaction has already been seen: + +1. After verification succeeds, derive a cache key from the transaction payload (e.g., the base64-encoded transaction string). +2. If the key is already present in the cache, reject the settlement with a `"duplicate_settlement"` error. +3. If the key is not present, insert it into the cache and proceed with signing and submission. +4. Evict entries older than 120 seconds (approximately twice the Solana blockhash lifetime of ~60–90 seconds). After this window, the transaction's blockhash will have expired and it cannot land on-chain regardless. + +This approach requires no external storage or long-lived state β€” only an in-process map with time-based eviction. It preserves the facilitator's otherwise stateless design while closing the duplicate settlement attack vector. \ No newline at end of file diff --git a/typescript/.changeset/fix-svm-duplicate-settlement.md b/typescript/.changeset/fix-svm-duplicate-settlement.md new file mode 100644 index 0000000000..c51c768c3b --- /dev/null +++ b/typescript/.changeset/fix-svm-duplicate-settlement.md @@ -0,0 +1,5 @@ +--- +'@x402/svm': patch +--- + +Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window diff --git a/typescript/packages/mechanisms/svm/README.md b/typescript/packages/mechanisms/svm/README.md index e026809d7a..01601da1fa 100644 --- a/typescript/packages/mechanisms/svm/README.md +++ b/typescript/packages/mechanisms/svm/README.md @@ -174,6 +174,16 @@ The exact payment scheme uses SPL Token `TransferChecked` instruction with: - Source/destination ATAs (Associated Token Accounts) - Partial signing (client signs, facilitator completes and submits) +## Duplicate Settlement Protection + +This package includes a built-in `SettlementCache` that prevents a known race condition on Solana where the same payment transaction could be settled multiple times before on-chain confirmation. When the facilitator scheme is registered via `registerExactSvmScheme`, a single `SettlementCache` instance is automatically shared across both V1 and V2 scheme versions. + +The cache rejects concurrent `/settle` calls that carry the same transaction payload, returning a `duplicate_settlement` error for the second and subsequent attempts. Entries are automatically evicted after 120 seconds (approximately twice the Solana blockhash lifetime). + +**No additional configuration is required** β€” duplicate settlement protection is enabled by default when using the standard registration helpers. + +For full details on the race condition and mitigation strategy, see the [Exact SVM Scheme Specification](../../../../specs/schemes/exact/scheme_exact_svm.md#duplicate-settlement-mitigation-recommended). + ## Development ```bash diff --git a/typescript/packages/mechanisms/svm/src/constants.ts b/typescript/packages/mechanisms/svm/src/constants.ts index 15a5463e8a..ea79bb3b86 100644 --- a/typescript/packages/mechanisms/svm/src/constants.ts +++ b/typescript/packages/mechanisms/svm/src/constants.ts @@ -42,6 +42,12 @@ export const DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1; export const MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 5_000_000; // 5 lamports export const DEFAULT_COMPUTE_UNIT_LIMIT = 20_000; +/** + * How long a transaction is held in the duplicate settlement cache (ms). + * Covers the Solana blockhash lifetime (~60-90s) with margin. + */ +export const SETTLEMENT_TTL_MS = 120_000; + /** * Solana address validation regex (base58, 32-44 characters) */ diff --git a/typescript/packages/mechanisms/svm/src/exact/facilitator/register.ts b/typescript/packages/mechanisms/svm/src/exact/facilitator/register.ts index 7055142191..25d18c6881 100644 --- a/typescript/packages/mechanisms/svm/src/exact/facilitator/register.ts +++ b/typescript/packages/mechanisms/svm/src/exact/facilitator/register.ts @@ -1,5 +1,6 @@ import { x402Facilitator } from "@x402/core/facilitator"; import { Network } from "@x402/core/types"; +import { SettlementCache } from "../../settlement-cache"; import { FacilitatorSvmSigner } from "../../signer"; import { ExactSvmScheme } from "./scheme"; import { ExactSvmSchemeV1 } from "../v1/facilitator/scheme"; @@ -47,11 +48,18 @@ export function registerExactSvmScheme( facilitator: x402Facilitator, config: SvmFacilitatorConfig, ): x402Facilitator { + // Share a single settlement cache across V1 and V2 so that a duplicate + // transaction submitted through one protocol version is also caught by the other. + const settlementCache = new SettlementCache(); + // Register V2 scheme with specified networks - facilitator.register(config.networks, new ExactSvmScheme(config.signer)); + facilitator.register(config.networks, new ExactSvmScheme(config.signer, settlementCache)); // Register all V1 networks - facilitator.registerV1(NETWORKS as Network[], new ExactSvmSchemeV1(config.signer)); + facilitator.registerV1( + NETWORKS as Network[], + new ExactSvmSchemeV1(config.signer, settlementCache), + ); return facilitator; } diff --git a/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts index 73568a278a..9ea1acef26 100644 --- a/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/svm/src/exact/facilitator/scheme.ts @@ -29,6 +29,7 @@ import { MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS, MEMO_PROGRAM_ADDRESS, } from "../../constants"; +import { SettlementCache } from "../../settlement-cache"; import type { FacilitatorSvmSigner } from "../../signer"; import type { ExactSvmPayloadV2 } from "../../types"; import { decodeTransactionFromPayload, getTokenPayerFromTransaction } from "../../utils"; @@ -40,13 +41,21 @@ export class ExactSvmScheme implements SchemeNetworkFacilitator { readonly scheme = "exact"; readonly caipFamily = "solana:*"; + private readonly settlementCache: SettlementCache; + /** * Creates a new ExactSvmFacilitator instance. * * @param signer - The SVM RPC client for facilitator operations + * @param settlementCache - Optional shared settlement cache (one is created if omitted) * @returns ExactSvmFacilitator instance */ - constructor(private readonly signer: FacilitatorSvmSigner) {} + constructor( + private readonly signer: FacilitatorSvmSigner, + settlementCache?: SettlementCache, + ) { + this.settlementCache = settlementCache ?? new SettlementCache(); + } /** * Get mechanism-specific extra data for the supported kinds endpoint. @@ -348,6 +357,19 @@ export class ExactSvmScheme implements SchemeNetworkFacilitator { }; } + // Duplicate settlement check: reject if this transaction is already being settled. + // Must occur before any async work so concurrent calls for the same tx are caught. + const txKey = exactSvmPayload.transaction; + if (this.settlementCache.isDuplicate(txKey)) { + return { + success: false, + network: payload.accepted.network, + transaction: "", + errorReason: "duplicate_settlement", + payer: valid.payer || "", + }; + } + try { // Extract feePayer from requirements (already validated in verify) const feePayer = requirements.extra.feePayer as Address; diff --git a/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts b/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts index 82e338cbc9..297eaf6ae8 100644 --- a/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/svm/src/exact/v1/facilitator/scheme.ts @@ -30,6 +30,7 @@ import { MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS, MEMO_PROGRAM_ADDRESS, } from "../../../constants"; +import { SettlementCache } from "../../../settlement-cache"; import type { FacilitatorSvmSigner } from "../../../signer"; import type { ExactSvmPayloadV1 } from "../../../types"; import { decodeTransactionFromPayload, getTokenPayerFromTransaction } from "../../../utils"; @@ -41,13 +42,21 @@ export class ExactSvmSchemeV1 implements SchemeNetworkFacilitator { readonly scheme = "exact"; readonly caipFamily = "solana:*"; + private readonly settlementCache: SettlementCache; + /** * Creates a new ExactSvmFacilitatorV1 instance. * * @param signer - The SVM RPC client for facilitator operations + * @param settlementCache - Optional shared settlement cache (one is created if omitted) * @returns ExactSvmFacilitatorV1 instance */ - constructor(private readonly signer: FacilitatorSvmSigner) {} + constructor( + private readonly signer: FacilitatorSvmSigner, + settlementCache?: SettlementCache, + ) { + this.settlementCache = settlementCache ?? new SettlementCache(); + } /** * Get mechanism-specific extra data for the supported kinds endpoint. @@ -352,6 +361,19 @@ export class ExactSvmSchemeV1 implements SchemeNetworkFacilitator { }; } + // Duplicate settlement check: reject if this transaction is already being settled. + // Must occur before any async work so concurrent calls for the same tx are caught. + const txKey = exactSvmPayload.transaction; + if (this.settlementCache.isDuplicate(txKey)) { + return { + success: false, + network: payloadV1.network, + transaction: "", + errorReason: "duplicate_settlement", + payer: valid.payer || "", + }; + } + try { // Extract feePayer from requirements (already validated in verify) const feePayer = requirements.extra.feePayer as Address; diff --git a/typescript/packages/mechanisms/svm/src/index.ts b/typescript/packages/mechanisms/svm/src/index.ts index 3f1e736fd9..ef5eca0f76 100644 --- a/typescript/packages/mechanisms/svm/src/index.ts +++ b/typescript/packages/mechanisms/svm/src/index.ts @@ -20,6 +20,9 @@ export type { // Export payload types export type { ExactSvmPayloadV1, ExactSvmPayloadV2 } from "./types"; +// Export settlement cache (shared across V1/V2 facilitator instances) +export { SettlementCache } from "./settlement-cache"; + // Export constants export * from "./constants"; diff --git a/typescript/packages/mechanisms/svm/src/settlement-cache.ts b/typescript/packages/mechanisms/svm/src/settlement-cache.ts new file mode 100644 index 0000000000..a8941b4510 --- /dev/null +++ b/typescript/packages/mechanisms/svm/src/settlement-cache.ts @@ -0,0 +1,46 @@ +import { SETTLEMENT_TTL_MS } from "./constants"; + +/** + * In-memory cache for deduplicating concurrent settlement requests. + * + * A single instance should be shared across V1 and V2 facilitator scheme + * instances so that a transaction submitted through one protocol version is + * also blocked on the other. Because Node.js is single-threaded, no lock + * is required β€” the cache check + insert must simply occur before the first + * `await` in the settle path. + */ +export class SettlementCache { + private readonly entries = new Map(); + + /** + * Returns `true` if `key` is already pending settlement (duplicate), + * or `false` after recording it as newly pending. + * + * Callers should reject the settlement when this returns `true`. + * + * @param key - The unique identifier for the settlement (typically the transaction signature). + * @returns `true` if the key was already present (duplicate); `false` otherwise. + */ + isDuplicate(key: string): boolean { + this.prune(); + if (this.entries.has(key)) { + return true; + } + this.entries.set(key, Date.now()); + return false; + } + + /** + * Remove entries older than the settlement TTL. + */ + private prune(): void { + const cutoff = Date.now() - SETTLEMENT_TTL_MS; + for (const [key, timestamp] of this.entries) { + if (timestamp < cutoff) { + this.entries.delete(key); + } else { + break; + } + } + } +} diff --git a/typescript/packages/mechanisms/svm/test/unit/facilitator.test.ts b/typescript/packages/mechanisms/svm/test/unit/facilitator.test.ts index 5d27bb523f..cb7fe1f535 100644 --- a/typescript/packages/mechanisms/svm/test/unit/facilitator.test.ts +++ b/typescript/packages/mechanisms/svm/test/unit/facilitator.test.ts @@ -1,7 +1,10 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { ExactSvmScheme } from "../../src/exact/facilitator/scheme"; +import { ExactSvmSchemeV1 } from "../../src/exact/v1/facilitator/scheme"; +import { SettlementCache } from "../../src/settlement-cache"; import type { FacilitatorSvmSigner } from "../../src/signer"; import type { PaymentRequirements, PaymentPayload } from "@x402/core/types"; +import type { PaymentPayloadV1, PaymentRequirementsV1 } from "@x402/core/types/v1"; import { USDC_DEVNET_ADDRESS, SOLANA_DEVNET_CAIP2 } from "../../src/constants"; describe("ExactSvmScheme", () => { @@ -255,4 +258,211 @@ describe("ExactSvmScheme", () => { expect(result.network).toBe(SOLANA_DEVNET_CAIP2); }); }); + + describe("duplicate settlement cache", () => { + function makePayload(transaction: string): PaymentPayload { + return { + x402Version: 2, + resource: { + url: "http://example.com/protected", + description: "Test resource", + mimeType: "application/json", + }, + accepted: { + scheme: "exact", + network: SOLANA_DEVNET_CAIP2, + asset: USDC_DEVNET_ADDRESS, + amount: "100000", + payTo: "PayToAddress11111111111111111111111111", + maxTimeoutSeconds: 3600, + extra: { feePayer: "FeePayer1111111111111111111111111111" }, + }, + payload: { transaction }, + }; + } + + const requirements: PaymentRequirements = { + scheme: "exact", + network: SOLANA_DEVNET_CAIP2, + asset: USDC_DEVNET_ADDRESS, + amount: "100000", + payTo: "PayToAddress11111111111111111111111111", + maxTimeoutSeconds: 3600, + extra: { feePayer: "FeePayer1111111111111111111111111111" }, + }; + + function setupSettleMocks(facilitator: ExactSvmScheme) { + vi.spyOn(facilitator, "verify").mockResolvedValue({ + isValid: true, + payer: "PayerAddress", + }); + (mockSigner as Record).signTransaction = vi + .fn() + .mockResolvedValue("signedTx"); + (mockSigner as Record).sendTransaction = vi + .fn() + .mockResolvedValue("txSignature123"); + (mockSigner as Record).confirmTransaction = vi + .fn() + .mockResolvedValue(undefined); + } + + it("should reject duplicate settlement of the same transaction", async () => { + const facilitator = new ExactSvmScheme(mockSigner); + setupSettleMocks(facilitator); + + const payload = makePayload("sameTransactionBase64=="); + + const result1 = await facilitator.settle(payload, requirements); + expect(result1.success).toBe(true); + + const result2 = await facilitator.settle(payload, requirements); + expect(result2.success).toBe(false); + expect(result2.errorReason).toBe("duplicate_settlement"); + }); + + it("should allow settlement of distinct transactions", async () => { + const facilitator = new ExactSvmScheme(mockSigner); + setupSettleMocks(facilitator); + + const result1 = await facilitator.settle(makePayload("transactionA=="), requirements); + expect(result1.success).toBe(true); + + const result2 = await facilitator.settle(makePayload("transactionB=="), requirements); + expect(result2.success).toBe(true); + }); + + it("should evict cache entries after TTL", async () => { + vi.useFakeTimers(); + try { + const facilitator = new ExactSvmScheme(mockSigner); + setupSettleMocks(facilitator); + + const payload = makePayload("expiringTransaction=="); + + const result1 = await facilitator.settle(payload, requirements); + expect(result1.success).toBe(true); + + // Advance past the 120s TTL + vi.advanceTimersByTime(121_000); + + const result2 = await facilitator.settle(payload, requirements); + expect(result2.success).toBe(true); + } finally { + vi.useRealTimers(); + } + }); + + it("should block cross-version duplicate when sharing a cache", async () => { + const sharedCache = new SettlementCache(); + const v2 = new ExactSvmScheme(mockSigner, sharedCache); + const v1 = new ExactSvmSchemeV1(mockSigner, sharedCache); + + // Mock V2 settle flow + vi.spyOn(v2, "verify").mockResolvedValue({ + isValid: true, + payer: "PayerAddress", + }); + (mockSigner as Record).signTransaction = vi + .fn() + .mockResolvedValue("signedTx"); + (mockSigner as Record).sendTransaction = vi + .fn() + .mockResolvedValue("txSignature123"); + (mockSigner as Record).confirmTransaction = vi + .fn() + .mockResolvedValue(undefined); + + // Settle via V2 first + const v2Result = await v2.settle(makePayload("crossVersionTx=="), requirements); + expect(v2Result.success).toBe(true); + + // Mock V1 verify + vi.spyOn(v1, "verify").mockResolvedValue({ + isValid: true, + payer: "PayerAddress", + }); + + // Same tx via V1 should be rejected + const v1Payload: PaymentPayloadV1 = { + x402Version: 1, + scheme: "exact", + network: "solana-devnet", + payload: { transaction: "crossVersionTx==" }, + }; + const v1Requirements: PaymentRequirementsV1 = { + scheme: "exact", + network: "solana-devnet", + asset: USDC_DEVNET_ADDRESS, + maxAmountRequired: "100000", + payTo: "PayToAddress11111111111111111111111111", + maxTimeoutSeconds: 3600, + extra: { feePayer: "FeePayer1111111111111111111111111111" }, + }; + + const v1Result = await v1.settle(v1Payload as never, v1Requirements as never); + expect(v1Result.success).toBe(false); + expect(v1Result.errorReason).toBe("duplicate_settlement"); + }); + }); +}); + +describe("SettlementCache prune optimization", () => { + it("should prune only expired entries and preserve non-expired ones", () => { + vi.useFakeTimers(); + try { + const cache = new SettlementCache(); + + // Insert three entries 10s apart + cache.isDuplicate("tx-a"); + vi.advanceTimersByTime(10_000); + cache.isDuplicate("tx-b"); + vi.advanceTimersByTime(10_000); + cache.isDuplicate("tx-c"); + + // Advance so tx-a and tx-b are expired (> 120s old) but tx-c is not + vi.advanceTimersByTime(101_000); // total: tx-a=121s, tx-b=111s, tx-c=101s + + // tx-a should be expired, tx-b and tx-c should still be cached + // Trigger prune via a new isDuplicate call + expect(cache.isDuplicate("tx-a")).toBe(false); // expired, re-inserted as new + expect(cache.isDuplicate("tx-b")).toBe(true); // still cached + expect(cache.isDuplicate("tx-c")).toBe(true); // still cached + } finally { + vi.useRealTimers(); + } + }); + + it("should prune all entries when all are expired", () => { + vi.useFakeTimers(); + try { + const cache = new SettlementCache(); + + cache.isDuplicate("tx-1"); + cache.isDuplicate("tx-2"); + cache.isDuplicate("tx-3"); + + vi.advanceTimersByTime(121_000); + + // All expired β€” none should be detected as duplicates + expect(cache.isDuplicate("tx-1")).toBe(false); + expect(cache.isDuplicate("tx-2")).toBe(false); + expect(cache.isDuplicate("tx-3")).toBe(false); + } finally { + vi.useRealTimers(); + } + }); + + it("should not prune any entries when none are expired", () => { + const cache = new SettlementCache(); + + cache.isDuplicate("tx-x"); + cache.isDuplicate("tx-y"); + cache.isDuplicate("tx-z"); + + // All still fresh β€” all should be detected as duplicates + expect(cache.isDuplicate("tx-x")).toBe(true); + expect(cache.isDuplicate("tx-y")).toBe(true); + expect(cache.isDuplicate("tx-z")).toBe(true); + }); }); diff --git a/typescript/packages/mechanisms/svm/test/unit/v1/facilitator.test.ts b/typescript/packages/mechanisms/svm/test/unit/v1/facilitator.test.ts index ac5a1c3f76..0502996217 100644 --- a/typescript/packages/mechanisms/svm/test/unit/v1/facilitator.test.ts +++ b/typescript/packages/mechanisms/svm/test/unit/v1/facilitator.test.ts @@ -204,4 +204,93 @@ describe("ExactSvmSchemeV1", () => { expect(result.network).toBe("solana-devnet"); }); }); + + describe("duplicate settlement cache", () => { + function makePayload(transaction: string): PaymentPayloadV1 { + return { + x402Version: 1, + scheme: "exact", + network: "solana-devnet", + payload: { transaction }, + }; + } + + const requirements: PaymentRequirementsV1 = { + scheme: "exact", + network: "solana-devnet", + asset: USDC_DEVNET_ADDRESS, + maxAmountRequired: "100000", + payTo: "PayToAddress11111111111111111111111111", + maxTimeoutSeconds: 3600, + extra: { feePayer: "FeePayer1111111111111111111111111111" }, + }; + + function setupSettleMocks(facilitator: ExactSvmSchemeV1) { + vi.spyOn(facilitator, "verify").mockResolvedValue({ + isValid: true, + payer: "PayerAddress", + }); + (mockSigner as Record).signTransaction = vi + .fn() + .mockResolvedValue("signedTx"); + (mockSigner as Record).sendTransaction = vi + .fn() + .mockResolvedValue("txSignature123"); + (mockSigner as Record).confirmTransaction = vi + .fn() + .mockResolvedValue(undefined); + } + + it("should reject duplicate settlement of the same transaction", async () => { + const facilitator = new ExactSvmSchemeV1(mockSigner); + setupSettleMocks(facilitator); + + const payload = makePayload("sameTransactionBase64=="); + + const result1 = await facilitator.settle(payload as never, requirements as never); + expect(result1.success).toBe(true); + + const result2 = await facilitator.settle(payload as never, requirements as never); + expect(result2.success).toBe(false); + expect(result2.errorReason).toBe("duplicate_settlement"); + }); + + it("should allow settlement of distinct transactions", async () => { + const facilitator = new ExactSvmSchemeV1(mockSigner); + setupSettleMocks(facilitator); + + const result1 = await facilitator.settle( + makePayload("transactionA==") as never, + requirements as never, + ); + expect(result1.success).toBe(true); + + const result2 = await facilitator.settle( + makePayload("transactionB==") as never, + requirements as never, + ); + expect(result2.success).toBe(true); + }); + + it("should evict cache entries after TTL", async () => { + vi.useFakeTimers(); + try { + const facilitator = new ExactSvmSchemeV1(mockSigner); + setupSettleMocks(facilitator); + + const payload = makePayload("expiringTransaction=="); + + const result1 = await facilitator.settle(payload as never, requirements as never); + expect(result1.success).toBe(true); + + // Advance past the 120s TTL + vi.advanceTimersByTime(121_000); + + const result2 = await facilitator.settle(payload as never, requirements as never); + expect(result2.success).toBe(true); + } finally { + vi.useRealTimers(); + } + }); + }); }); From 3e1d0517f75732de3f0e8b5acd08810f4d8e2968 Mon Sep 17 00:00:00 2001 From: phdargen Date: Fri, 6 Mar 2026 09:36:48 +0900 Subject: [PATCH 029/129] fix stellar e2e config (#1467) * fix stellar e2e config * fix stellar next e2e --- e2e/servers/express/test.config.json | 9 +- e2e/servers/hono/test.config.json | 9 +- e2e/servers/next/proxy.ts | 37 +++ e2e/servers/next/test.config.json | 16 +- e2e/test.ts | 397 ++++++++++++++------------- 5 files changed, 267 insertions(+), 201 deletions(-) diff --git a/e2e/servers/express/test.config.json b/e2e/servers/express/test.config.json index 748b805a84..4f2cd84042 100644 --- a/e2e/servers/express/test.config.json +++ b/e2e/servers/express/test.config.json @@ -44,6 +44,13 @@ "requiresPayment": true, "protocolFamily": "aptos" }, + { + "path": "/protected-stellar", + "method": "GET", + "description": "Protected endpoint requiring payment on Stellar network", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/health", "method": "GET", @@ -59,6 +66,6 @@ ], "environment": { "required": ["PORT", "EVM_PAYEE_ADDRESS", "SVM_PAYEE_ADDRESS", "FACILITATOR_URL"], - "optional": ["APTOS_PAYEE_ADDRESS"] + "optional": ["APTOS_PAYEE_ADDRESS", "STELLAR_PAYEE_ADDRESS"] } } diff --git a/e2e/servers/hono/test.config.json b/e2e/servers/hono/test.config.json index dd4ecb8a89..3eddf60e4e 100644 --- a/e2e/servers/hono/test.config.json +++ b/e2e/servers/hono/test.config.json @@ -44,6 +44,13 @@ "requiresPayment": true, "protocolFamily": "aptos" }, + { + "path": "/protected-stellar", + "method": "GET", + "description": "Protected endpoint requiring payment on Stellar network", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/health", "method": "GET", @@ -59,6 +66,6 @@ ], "environment": { "required": ["PORT", "EVM_PAYEE_ADDRESS", "SVM_PAYEE_ADDRESS", "FACILITATOR_URL"], - "optional": ["APTOS_PAYEE_ADDRESS"] + "optional": ["APTOS_PAYEE_ADDRESS", "STELLAR_PAYEE_ADDRESS"] } } diff --git a/e2e/servers/next/proxy.ts b/e2e/servers/next/proxy.ts index 356c63fb93..02a4797382 100644 --- a/e2e/servers/next/proxy.ts +++ b/e2e/servers/next/proxy.ts @@ -3,6 +3,7 @@ import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { ExactSvmScheme } from "@x402/svm/exact/server"; import { ExactAptosScheme } from "@x402/aptos/exact/server"; +import { ExactStellarScheme } from "@x402/stellar/exact/server"; import { bazaarResourceServerExtension, declareDiscoveryExtension } from "@x402/extensions/bazaar"; import { declareEip2612GasSponsoringExtension, @@ -12,10 +13,13 @@ import { 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 APTOS_PAYEE_ADDRESS = process.env.APTOS_PAYEE_ADDRESS as string; +export const STELLAR_PAYEE_ADDRESS = process.env.STELLAR_PAYEE_ADDRESS as string | undefined; export const EVM_NETWORK = (process.env.EVM_NETWORK || "eip155:84532") as `${string}:${string}`; export const SVM_NETWORK = (process.env.SVM_NETWORK || "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1") as `${string}:${string}`; export const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; +export const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || + "stellar:testnet") as `${string}:${string}`; const facilitatorUrl = process.env.FACILITATOR_URL; if (!facilitatorUrl) { @@ -35,6 +39,9 @@ server.register("solana:*", new ExactSvmScheme()); if (APTOS_PAYEE_ADDRESS) { server.register("aptos:*", new ExactAptosScheme()); } +if (STELLAR_PAYEE_ADDRESS) { + server.register("stellar:*", new ExactStellarScheme()); +} // Register Bazaar discovery extension server.registerExtension(bazaarResourceServerExtension); @@ -122,6 +129,35 @@ export const proxy = paymentProxy( }, } : {}), + ...(STELLAR_PAYEE_ADDRESS + ? { + "/api/protected-stellar-proxy": { + accepts: { + payTo: STELLAR_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: STELLAR_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-permit2-proxy": { accepts: { payTo: EVM_PAYEE_ADDRESS, @@ -177,6 +213,7 @@ export const config = { "/api/protected-proxy", "/api/protected-svm-proxy", "/api/protected-aptos-proxy", + "/api/protected-stellar-proxy", "/api/protected-permit2-proxy", "/api/protected-permit2-erc20-proxy", ], diff --git a/e2e/servers/next/test.config.json b/e2e/servers/next/test.config.json index 835d4329d3..7347eb089c 100644 --- a/e2e/servers/next/test.config.json +++ b/e2e/servers/next/test.config.json @@ -44,6 +44,13 @@ "requiresPayment": true, "protocolFamily": "aptos" }, + { + "path": "/api/protected-stellar-proxy", + "method": "GET", + "description": "Protected Stellar endpoint using proxy middleware", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/api/protected-withx402", "method": "GET", @@ -59,6 +66,13 @@ "requiresPayment": true, "protocolFamily": "svm" }, + { + "path": "/api/protected-stellar-withx402", + "method": "GET", + "description": "Protected Stellar endpoint using withX402 wrapper", + "requiresPayment": true, + "protocolFamily": "stellar" + }, { "path": "/api/health", "method": "GET", @@ -74,6 +88,6 @@ ], "environment": { "required": ["PORT", "EVM_PAYEE_ADDRESS", "SVM_PAYEE_ADDRESS", "FACILITATOR_URL"], - "optional": ["APTOS_PAYEE_ADDRESS"] + "optional": ["APTOS_PAYEE_ADDRESS", "STELLAR_PAYEE_ADDRESS"] } } diff --git a/e2e/test.ts b/e2e/test.ts index e3e2d37eb5..c08b83a266 100644 --- a/e2e/test.ts +++ b/e2e/test.ts @@ -648,13 +648,14 @@ async function runTest() { const facilitatorConfig = facilitatorName ? uniqueFacilitators.get(facilitatorName)?.config : undefined; const facilitatorSupportsAptos = facilitatorConfig?.protocolFamilies?.includes('aptos') ?? false; + const facilitatorSupportsStellar = facilitatorConfig?.protocolFamilies?.includes('stellar') ?? false; const serverConfig: ServerConfig = { port, evmPayTo: serverEvmAddress!, svmPayTo: serverSvmAddress!, aptosPayTo: facilitatorSupportsAptos ? (serverAptosAddress || '') : '', - stellarPayTo: serverStellarAddress || '', + stellarPayTo: facilitatorSupportsStellar ? (serverStellarAddress || '') : '', networks, facilitatorUrl, }; @@ -698,230 +699,230 @@ async function runTest() { } } } finally { - cLog.verboseLog(` πŸ›‘ Stopping ${serverName} (finished combo)`); - await serverProxy.stop(); -} + cLog.verboseLog(` πŸ›‘ Stopping ${serverName} (finished combo)`); + await serverProxy.stop(); + } -return results; + return results; } -// ── Unified execution: concurrency=1 for sequential, N for parallel ── -const effectiveConcurrency = parsedArgs.parallel ? parsedArgs.concurrency : 1; -const evmLock = parsedArgs.parallel ? new FacilitatorLock() : null; -const semaphore = new Semaphore(effectiveConcurrency); + // ── Unified execution: concurrency=1 for sequential, N for parallel ── + const effectiveConcurrency = parsedArgs.parallel ? parsedArgs.concurrency : 1; + const evmLock = parsedArgs.parallel ? new FacilitatorLock() : null; + const semaphore = new Semaphore(effectiveConcurrency); -let globalTestNumber = 0; -const nextTestNumber = () => ++globalTestNumber; + let globalTestNumber = 0; + const nextTestNumber = () => ++globalTestNumber; -const comboPromises = serverFacilitatorCombos.map(async (combo) => { - const release = await semaphore.acquire(); - try { - return await executeCombo(combo, evmLock, nextTestNumber); - } finally { - release(); - } -}); + const comboPromises = serverFacilitatorCombos.map(async (combo) => { + const release = await semaphore.acquire(); + try { + return await executeCombo(combo, evmLock, nextTestNumber); + } finally { + release(); + } + }); -testResults = (await Promise.all(comboPromises)).flat(); + testResults = (await Promise.all(comboPromises)).flat(); -// 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, -})); + // 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()); + const serversArray = Array.from(uniqueServers.values()); -// Build a serverNameβ†’port map for discovery validation (first combo per server). -const discoveryServerPorts = new Map(); -for (const combo of serverFacilitatorCombos) { - if (!discoveryServerPorts.has(combo.serverName)) { - discoveryServerPorts.set(combo.serverName, combo.port); + // Build a serverNameβ†’port map for discovery validation (first combo per server). + const discoveryServerPorts = new Map(); + for (const combo of serverFacilitatorCombos) { + if (!discoveryServerPorts.has(combo.serverName)) { + discoveryServerPorts.set(combo.serverName, combo.port); + } } -} -// 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, - discoveryServerPorts, - facilitatorServerMap - ); -} + // 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, + discoveryServerPorts, + facilitatorServerMap + ); + } -// Clean up facilitators (servers already stopped in test loop for both modes) -log('\n🧹 Cleaning up...'); + // Clean up facilitators (servers already stopped in test loop for both modes) + log('\n🧹 Cleaning up...'); -// 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(''); -log('πŸ“Š Test Summary'); -log('=============='); -log(`🌐 Network: ${networkMode} (${getNetworkModeDescription(networkMode)})`); -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:'); + // 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(''); - passedTests.forEach(test => { - log(` #${test.testNumber.toString().padStart(2, ' ')}: ${test.client} β†’ ${test.server} β†’ ${test.endpoint}`); - log(` Facilitator: ${test.facilitator}`); - if (test.network) { - log(` Network: ${test.network}`); - } - if (test.transaction) { - log(` Tx: ${test.transaction}`); - } - }); + log('πŸ“Š Test Summary'); + log('=============='); + log(`🌐 Network: ${networkMode} (${getNetworkModeDescription(networkMode)})`); + log(`βœ… Passed: ${passed}`); + log(`❌ Failed: ${failed}`); + log(`πŸ“ˆ Total: ${passed + failed}`); log(''); -} -if (failedTests.length > 0) { - log('❌ FAILED TESTS:'); + // Detailed results table + log('πŸ“‹ Detailed Test Results'); + log('========================'); log(''); - failedTests.forEach(test => { - log(` #${test.testNumber.toString().padStart(2, ' ')}: ${test.client} β†’ ${test.server} β†’ ${test.endpoint}`); - log(` Facilitator: ${test.facilitator}`); - if (test.network) { - log(` Network: ${test.network}`); - } - log(` Error: ${test.error || 'Unknown error'}`); + + // 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 => { + log(` #${test.testNumber.toString().padStart(2, ' ')}: ${test.client} β†’ ${test.server} β†’ ${test.endpoint}`); + log(` Facilitator: ${test.facilitator}`); + if (test.network) { + log(` Network: ${test.network}`); + } + if (test.transaction) { + log(` Tx: ${test.transaction}`); + } + }); + 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}`); + if (test.network) { + log(` Network: ${test.network}`); + } + 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 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 = 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); - -if (Object.keys(protocolBreakdown).length > 1) { - log('πŸ“Š Protocol Family Breakdown:'); - Object.entries(protocolBreakdown).forEach(([protocol, stats]) => { + // 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; - log(` ${protocol.toUpperCase()}: βœ… ${stats.passed} / ❌ ${stats.failed} / πŸ“ˆ ${total} total`); + const passRate = total > 0 ? Math.round((stats.passed / total) * 100) : 0; + log(` ${server.padEnd(20)} βœ… ${stats.passed} / ❌ ${stats.failed} (${passRate}%)`); }); log(''); -} -// Write structured JSON output if requested -if (parsedArgs.outputJson) { - const breakdown = (results: DetailedTestResult[], key: keyof DetailedTestResult) => - results.reduce((acc, test) => { - const k = String(test[key]); - if (!acc[k]) acc[k] = { passed: 0, failed: 0 }; - if (test.passed) acc[k].passed++; - else acc[k].failed++; - return acc; - }, {} as Record); - - const jsonOutput = { - summary: { - total: passed + failed, - passed, - failed, - networkMode, - }, - results: testResults, - breakdowns: { - byFacilitator: breakdown(testResults, 'facilitator'), - byServer: breakdown(testResults, 'server'), - byClient: breakdown(testResults, 'client'), - byProtocolFamily: breakdown(testResults, 'protocolFamily'), - }, - }; + // 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(''); - writeFileSync(parsedArgs.outputJson, JSON.stringify(jsonOutput, null, 2)); - log(`πŸ“„ JSON results written to ${parsedArgs.outputJson}`); -} + // Protocol family breakdown + 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); + + if (Object.keys(protocolBreakdown).length > 1) { + log('πŸ“Š Protocol Family Breakdown:'); + Object.entries(protocolBreakdown).forEach(([protocol, stats]) => { + const total = stats.passed + stats.failed; + log(` ${protocol.toUpperCase()}: βœ… ${stats.passed} / ❌ ${stats.failed} / πŸ“ˆ ${total} total`); + }); + log(''); + } -// Close logger -closeLogger(); + // Write structured JSON output if requested + if (parsedArgs.outputJson) { + const breakdown = (results: DetailedTestResult[], key: keyof DetailedTestResult) => + results.reduce((acc, test) => { + const k = String(test[key]); + if (!acc[k]) acc[k] = { passed: 0, failed: 0 }; + if (test.passed) acc[k].passed++; + else acc[k].failed++; + return acc; + }, {} as Record); + + const jsonOutput = { + summary: { + total: passed + failed, + passed, + failed, + networkMode, + }, + results: testResults, + breakdowns: { + byFacilitator: breakdown(testResults, 'facilitator'), + byServer: breakdown(testResults, 'server'), + byClient: breakdown(testResults, 'client'), + byProtocolFamily: breakdown(testResults, 'protocolFamily'), + }, + }; -if (failed > 0) { - process.exit(1); -} + writeFileSync(parsedArgs.outputJson, JSON.stringify(jsonOutput, null, 2)); + log(`πŸ“„ JSON results written to ${parsedArgs.outputJson}`); + } + + // Close logger + closeLogger(); + + if (failed > 0) { + process.exit(1); + } } // Run the test From cc6d0fcc1efafc7f00b05ebe1887a0086d5a7cef Mon Sep 17 00:00:00 2001 From: phdargen Date: Fri, 6 Mar 2026 10:53:37 +0900 Subject: [PATCH 030/129] chore: version typescript packages (#1469) * updated changeset * chore: version typescript packages * updated changelogs --- ...dd-x402version-to-facilitator-request-types.md | 5 ----- typescript/.changeset/bold-mice-sink.md | 8 -------- typescript/.changeset/clear-tables-teach.md | 6 ------ .../.changeset/fix-settlement-failure-header.md | 8 -------- .../.changeset/fix-svm-duplicate-settlement.md | 5 ----- typescript/.changeset/red-geese-sit.md | 5 ----- .../.changeset/remove-duplicate-resource-info.md | 5 ----- typescript/.changeset/types-optionality-fix.md | 6 ------ typescript/packages/core/CHANGELOG.md | 10 ++++++++++ typescript/packages/core/package.json | 2 +- typescript/packages/extensions/CHANGELOG.md | 7 +++++++ typescript/packages/extensions/package.json | 2 +- typescript/packages/http/axios/CHANGELOG.md | 7 +++++++ typescript/packages/http/axios/package.json | 2 +- typescript/packages/http/express/CHANGELOG.md | 15 +++++++++++++++ typescript/packages/http/express/package.json | 2 +- typescript/packages/http/fetch/CHANGELOG.md | 7 +++++++ typescript/packages/http/fetch/package.json | 2 +- typescript/packages/http/hono/CHANGELOG.md | 14 ++++++++++++++ typescript/packages/http/hono/package.json | 2 +- typescript/packages/http/next/CHANGELOG.md | 15 +++++++++++++++ typescript/packages/http/next/package.json | 2 +- typescript/packages/http/paywall/CHANGELOG.md | 12 ++++++++++++ typescript/packages/http/paywall/package.json | 2 +- typescript/packages/mcp/CHANGELOG.md | 7 +++++++ typescript/packages/mcp/package.json | 2 +- typescript/packages/mechanisms/aptos/CHANGELOG.md | 11 +++++++++++ typescript/packages/mechanisms/aptos/package.json | 2 +- typescript/packages/mechanisms/evm/CHANGELOG.md | 12 ++++++++++++ typescript/packages/mechanisms/evm/package.json | 2 +- .../packages/mechanisms/stellar/CHANGELOG.md | 2 +- .../packages/mechanisms/stellar/package.json | 2 +- typescript/packages/mechanisms/svm/CHANGELOG.md | 12 ++++++++++++ typescript/packages/mechanisms/svm/package.json | 2 +- 34 files changed, 143 insertions(+), 62 deletions(-) delete mode 100644 typescript/.changeset/add-x402version-to-facilitator-request-types.md delete mode 100644 typescript/.changeset/bold-mice-sink.md delete mode 100644 typescript/.changeset/clear-tables-teach.md delete mode 100644 typescript/.changeset/fix-settlement-failure-header.md delete mode 100644 typescript/.changeset/fix-svm-duplicate-settlement.md delete mode 100644 typescript/.changeset/red-geese-sit.md delete mode 100644 typescript/.changeset/remove-duplicate-resource-info.md delete mode 100644 typescript/.changeset/types-optionality-fix.md diff --git a/typescript/.changeset/add-x402version-to-facilitator-request-types.md b/typescript/.changeset/add-x402version-to-facilitator-request-types.md deleted file mode 100644 index 63df2d3a3e..0000000000 --- a/typescript/.changeset/add-x402version-to-facilitator-request-types.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@x402/core": patch ---- - -Added `x402Version` field to `VerifyRequest`, `SettleRequest`, `VerifyRequestV1`, and `SettleRequestV1` types to match what all SDK implementations already send in facilitator request bodies. diff --git a/typescript/.changeset/bold-mice-sink.md b/typescript/.changeset/bold-mice-sink.md deleted file mode 100644 index e83c6e0695..0000000000 --- a/typescript/.changeset/bold-mice-sink.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@x402/express': patch -'@x402/hono': patch -'@x402/next': patch -'@x402/core': patch ---- - -Added dynamic function for servers to generate custom response for settlement failures defaulting to empty diff --git a/typescript/.changeset/clear-tables-teach.md b/typescript/.changeset/clear-tables-teach.md deleted file mode 100644 index ae20548dd7..0000000000 --- a/typescript/.changeset/clear-tables-teach.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@x402/express': patch -'@x402/next': patch ---- - -Cleaned up dependencies diff --git a/typescript/.changeset/fix-settlement-failure-header.md b/typescript/.changeset/fix-settlement-failure-header.md deleted file mode 100644 index e3e5767651..0000000000 --- a/typescript/.changeset/fix-settlement-failure-header.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@x402/core': patch -'@x402/express': patch -'@x402/hono': patch -'@x402/next': patch ---- - -Include PAYMENT-RESPONSE header on settlement failure responses diff --git a/typescript/.changeset/fix-svm-duplicate-settlement.md b/typescript/.changeset/fix-svm-duplicate-settlement.md deleted file mode 100644 index c51c768c3b..0000000000 --- a/typescript/.changeset/fix-svm-duplicate-settlement.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/svm': patch ---- - -Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window diff --git a/typescript/.changeset/red-geese-sit.md b/typescript/.changeset/red-geese-sit.md deleted file mode 100644 index 9e7f45f33d..0000000000 --- a/typescript/.changeset/red-geese-sit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/evm': patch ---- - -Added assetTransferMethod and supportsEip2612 flag to defaultAssets diff --git a/typescript/.changeset/remove-duplicate-resource-info.md b/typescript/.changeset/remove-duplicate-resource-info.md deleted file mode 100644 index f00a71cf65..0000000000 --- a/typescript/.changeset/remove-duplicate-resource-info.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@x402/core": patch ---- - -Remove duplicate server-local `ResourceInfo` interface; use the wire-format `ResourceInfo` from `types/payments.ts` directly throughout the server module. diff --git a/typescript/.changeset/types-optionality-fix.md b/typescript/.changeset/types-optionality-fix.md deleted file mode 100644 index acc61f8ed0..0000000000 --- a/typescript/.changeset/types-optionality-fix.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@x402/core": patch -"@x402/paywall": patch ---- - -Make ResourceInfo.description, ResourceInfo.mimeType, and PaymentPayload.resource optional to match v2 spec diff --git a/typescript/packages/core/CHANGELOG.md b/typescript/packages/core/CHANGELOG.md index 2ccb20544d..fe72eea1e5 100644 --- a/typescript/packages/core/CHANGELOG.md +++ b/typescript/packages/core/CHANGELOG.md @@ -1,5 +1,15 @@ # @x402/core Changelog +## 2.6.0 + +### Minor Changes + +- f41baed: Added `x402Version` field to `VerifyRequest`, `SettleRequest`, `VerifyRequestV1`, and `SettleRequestV1` types to match what all SDK implementations already send in facilitator request bodies. +- aeef1bf: Added dynamic function for servers to generate custom response for settlement failures defaulting to empty +- 2564781: Include PAYMENT-RESPONSE header on settlement failure responses +- b341973: Remove duplicate server-local `ResourceInfo` interface; use the wire-format `ResourceInfo` from `types/payments.ts` directly throughout the server module. +- 29fe09a: Make ResourceInfo.description, ResourceInfo.mimeType, and PaymentPayload.resource optional to match v2 spec + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/core/package.json b/typescript/packages/core/package.json index 226e53c023..2153ab4ff2 100644 --- a/typescript/packages/core/package.json +++ b/typescript/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@x402/core", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/extensions/CHANGELOG.md b/typescript/packages/extensions/CHANGELOG.md index cb75350723..899ed31e03 100644 --- a/typescript/packages/extensions/CHANGELOG.md +++ b/typescript/packages/extensions/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/extensions Changelog +## 2.6.0 + +### Minor Changes + +- Updated dependencies + - @x402/core@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/extensions/package.json b/typescript/packages/extensions/package.json index 993aee45e6..d602427dbb 100644 --- a/typescript/packages/extensions/package.json +++ b/typescript/packages/extensions/package.json @@ -1,6 +1,6 @@ { "name": "@x402/extensions", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/http/axios/CHANGELOG.md b/typescript/packages/http/axios/CHANGELOG.md index da6673c6cd..1de2ded144 100644 --- a/typescript/packages/http/axios/CHANGELOG.md +++ b/typescript/packages/http/axios/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/axios Changelog +## 2.6.0 + +### Minor Changes + +- Updated dependencies + - @x402/core@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/http/axios/package.json b/typescript/packages/http/axios/package.json index 7576667a29..ebd6d0fd90 100644 --- a/typescript/packages/http/axios/package.json +++ b/typescript/packages/http/axios/package.json @@ -1,6 +1,6 @@ { "name": "@x402/axios", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/express/CHANGELOG.md b/typescript/packages/http/express/CHANGELOG.md index e80dd62610..155288ac55 100644 --- a/typescript/packages/http/express/CHANGELOG.md +++ b/typescript/packages/http/express/CHANGELOG.md @@ -1,5 +1,20 @@ # @x402/express Changelog +## 2.6.0 + +### Minor Changes + +- aeef1bf: Added dynamic function for servers to generate custom response for settlement failures defaulting to empty +- 205257b: Cleaned up dependencies +- 2564781: Include PAYMENT-RESPONSE header on settlement failure responses +- Updated dependencies [f41baed] +- Updated dependencies [aeef1bf] +- Updated dependencies [2564781] +- Updated dependencies [b341973] +- Updated dependencies [29fe09a] + - @x402/core@2.6.0 + - @x402/paywall@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/http/express/package.json b/typescript/packages/http/express/package.json index 60fb267ca6..2ba9f8668f 100644 --- a/typescript/packages/http/express/package.json +++ b/typescript/packages/http/express/package.json @@ -1,6 +1,6 @@ { "name": "@x402/express", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/fetch/CHANGELOG.md b/typescript/packages/http/fetch/CHANGELOG.md index 3de3a9e62a..4e530af0dd 100644 --- a/typescript/packages/http/fetch/CHANGELOG.md +++ b/typescript/packages/http/fetch/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/fetch Changelog +## 2.6.0 + +### Minor Changes + +- Updated dependencies + - @x402/core@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/http/fetch/package.json b/typescript/packages/http/fetch/package.json index a2ba606676..5d47a02b27 100644 --- a/typescript/packages/http/fetch/package.json +++ b/typescript/packages/http/fetch/package.json @@ -1,6 +1,6 @@ { "name": "@x402/fetch", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/hono/CHANGELOG.md b/typescript/packages/http/hono/CHANGELOG.md index d53f8aa1c2..cb43832902 100644 --- a/typescript/packages/http/hono/CHANGELOG.md +++ b/typescript/packages/http/hono/CHANGELOG.md @@ -1,5 +1,19 @@ # @x402/hono Changelog +## 2.6.0 + +### Minor Changes + +- aeef1bf: Added dynamic function for servers to generate custom response for settlement failures defaulting to empty +- 2564781: Include PAYMENT-RESPONSE header on settlement failure responses +- Updated dependencies [f41baed] +- Updated dependencies [aeef1bf] +- Updated dependencies [2564781] +- Updated dependencies [b341973] +- Updated dependencies [29fe09a] + - @x402/core@2.6.0 + - @x402/paywall@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/http/hono/package.json b/typescript/packages/http/hono/package.json index 3ad9dd4595..a7f95fe114 100644 --- a/typescript/packages/http/hono/package.json +++ b/typescript/packages/http/hono/package.json @@ -1,6 +1,6 @@ { "name": "@x402/hono", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/next/CHANGELOG.md b/typescript/packages/http/next/CHANGELOG.md index 01c5856c68..6738d2183a 100644 --- a/typescript/packages/http/next/CHANGELOG.md +++ b/typescript/packages/http/next/CHANGELOG.md @@ -1,5 +1,20 @@ # @x402/next Changelog +## 2.6.0 + +### Minor Changes + +- aeef1bf: Added dynamic function for servers to generate custom response for settlement failures defaulting to empty +- 205257b: Cleaned up dependencies +- 2564781: Include PAYMENT-RESPONSE header on settlement failure responses +- Updated dependencies [f41baed] +- Updated dependencies [aeef1bf] +- Updated dependencies [2564781] +- Updated dependencies [b341973] +- Updated dependencies [29fe09a] + - @x402/core@2.6.0 + - @x402/paywall@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/http/next/package.json b/typescript/packages/http/next/package.json index 0b4254327e..5adb87dc35 100644 --- a/typescript/packages/http/next/package.json +++ b/typescript/packages/http/next/package.json @@ -1,6 +1,6 @@ { "name": "@x402/next", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/paywall/CHANGELOG.md b/typescript/packages/http/paywall/CHANGELOG.md index b50f371dfb..6d73bf3ec3 100644 --- a/typescript/packages/http/paywall/CHANGELOG.md +++ b/typescript/packages/http/paywall/CHANGELOG.md @@ -1,5 +1,17 @@ # @x402/paywall Changelog +## 2.6.0 + +### Minor Changes + +- 29fe09a: Make ResourceInfo.description, ResourceInfo.mimeType, and PaymentPayload.resource optional to match v2 spec +- Updated dependencies [f41baed] +- Updated dependencies [aeef1bf] +- Updated dependencies [2564781] +- Updated dependencies [b341973] +- Updated dependencies [29fe09a] + - @x402/core@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/http/paywall/package.json b/typescript/packages/http/paywall/package.json index 179272c450..f44301b143 100644 --- a/typescript/packages/http/paywall/package.json +++ b/typescript/packages/http/paywall/package.json @@ -1,6 +1,6 @@ { "name": "@x402/paywall", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/mcp/CHANGELOG.md b/typescript/packages/mcp/CHANGELOG.md index 34c111e5ee..a430aa321b 100644 --- a/typescript/packages/mcp/CHANGELOG.md +++ b/typescript/packages/mcp/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/mcp Changelog +## 2.6.0 + +### Minor Changes + +- Updated dependencies + - @x402/core@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/mcp/package.json b/typescript/packages/mcp/package.json index 2d655759f0..c06e6ebb68 100644 --- a/typescript/packages/mcp/package.json +++ b/typescript/packages/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@x402/mcp", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/aptos/CHANGELOG.md b/typescript/packages/mechanisms/aptos/CHANGELOG.md index 16dd440bf8..19521f2fa5 100644 --- a/typescript/packages/mechanisms/aptos/CHANGELOG.md +++ b/typescript/packages/mechanisms/aptos/CHANGELOG.md @@ -1,5 +1,16 @@ # @x402/aptos +## 2.6.0 + +### Minor Changes + +- Updated dependencies [f41baed] +- Updated dependencies [aeef1bf] +- Updated dependencies [2564781] +- Updated dependencies [b341973] +- Updated dependencies [29fe09a] + - @x402/core@2.6.0 + ## 2.5.0 ### Patch Changes diff --git a/typescript/packages/mechanisms/aptos/package.json b/typescript/packages/mechanisms/aptos/package.json index 6efa05e8bb..5385734f2f 100644 --- a/typescript/packages/mechanisms/aptos/package.json +++ b/typescript/packages/mechanisms/aptos/package.json @@ -1,6 +1,6 @@ { "name": "@x402/aptos", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/evm/CHANGELOG.md b/typescript/packages/mechanisms/evm/CHANGELOG.md index e44972f2c6..310ccccdaa 100644 --- a/typescript/packages/mechanisms/evm/CHANGELOG.md +++ b/typescript/packages/mechanisms/evm/CHANGELOG.md @@ -1,5 +1,17 @@ # @x402/evm Changelog +## 2.6.0 + +### Minor Changes + +- f431337: Added assetTransferMethod and supportsEip2612 flag to defaultAssets +- Updated dependencies [f41baed] +- Updated dependencies [aeef1bf] +- Updated dependencies [2564781] +- Updated dependencies [b341973] +- Updated dependencies [29fe09a] + - @x402/core@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/mechanisms/evm/package.json b/typescript/packages/mechanisms/evm/package.json index 8d57cfe37c..86fa94c5b5 100644 --- a/typescript/packages/mechanisms/evm/package.json +++ b/typescript/packages/mechanisms/evm/package.json @@ -1,6 +1,6 @@ { "name": "@x402/evm", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/stellar/CHANGELOG.md b/typescript/packages/mechanisms/stellar/CHANGELOG.md index 92f159f6dd..e6ac674090 100644 --- a/typescript/packages/mechanisms/stellar/CHANGELOG.md +++ b/typescript/packages/mechanisms/stellar/CHANGELOG.md @@ -1,5 +1,5 @@ # @x402/stellar Changelog -## 2.5.0 +## 2.6.0 - Implement x402 v2 protocol support for the Stellar mechanism (exact scheme). diff --git a/typescript/packages/mechanisms/stellar/package.json b/typescript/packages/mechanisms/stellar/package.json index 24adee8547..58a0ba7411 100644 --- a/typescript/packages/mechanisms/stellar/package.json +++ b/typescript/packages/mechanisms/stellar/package.json @@ -1,6 +1,6 @@ { "name": "@x402/stellar", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/svm/CHANGELOG.md b/typescript/packages/mechanisms/svm/CHANGELOG.md index f15d547fa2..525d6ebd55 100644 --- a/typescript/packages/mechanisms/svm/CHANGELOG.md +++ b/typescript/packages/mechanisms/svm/CHANGELOG.md @@ -1,5 +1,17 @@ # @x402/svm Changelog +## 2.6.0 + +### Minor Changes + +- 7cd93d8: Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window +- Updated dependencies [f41baed] +- Updated dependencies [aeef1bf] +- Updated dependencies [2564781] +- Updated dependencies [b341973] +- Updated dependencies [29fe09a] + - @x402/core@2.6.0 + ## 2.5.0 ### Minor Changes diff --git a/typescript/packages/mechanisms/svm/package.json b/typescript/packages/mechanisms/svm/package.json index 93067cc08e..cd7d777b59 100644 --- a/typescript/packages/mechanisms/svm/package.json +++ b/typescript/packages/mechanisms/svm/package.json @@ -1,6 +1,6 @@ { "name": "@x402/svm", - "version": "2.5.0", + "version": "2.6.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", From 65f12004b1359b0ca4be10df91c25e553db36f49 Mon Sep 17 00:00:00 2001 From: phdargen Date: Fri, 6 Mar 2026 11:38:07 +0900 Subject: [PATCH 031/129] chore: version python package (#1470) --- python/x402/CHANGELOG.md | 15 +++++++++++++++ python/x402/changelog.d/1120.bugfix.md | 1 - python/x402/changelog.d/1121.bugfix.md | 1 - python/x402/changelog.d/1359.bugfix.md | 1 - python/x402/changelog.d/1430.bugfix.md | 1 - .../changelog.d/split-v1-v2-networks.feature.md | 1 - .../svm-duplicate-settlement.bugfix.md | 1 - python/x402/pyproject.toml | 2 +- python/x402/uv.lock | 4 ++-- 9 files changed, 18 insertions(+), 9 deletions(-) delete mode 100644 python/x402/changelog.d/1120.bugfix.md delete mode 100644 python/x402/changelog.d/1121.bugfix.md delete mode 100644 python/x402/changelog.d/1359.bugfix.md delete mode 100644 python/x402/changelog.d/1430.bugfix.md delete mode 100644 python/x402/changelog.d/split-v1-v2-networks.feature.md delete mode 100644 python/x402/changelog.d/svm-duplicate-settlement.bugfix.md diff --git a/python/x402/CHANGELOG.md b/python/x402/CHANGELOG.md index 558598b814..030f8b0f4b 100644 --- a/python/x402/CHANGELOG.md +++ b/python/x402/CHANGELOG.md @@ -2,6 +2,21 @@ +## [2.3.0] - 2026-03-06 + +### Fixed + +- Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window ([#svm-duplicate-settlement](https://github.com/coinbase/x402/pull/svm-duplicate-settlement)) +- Added serialize_by_alias=True to BaseX402Model so model_dump_json() produces spec-compliant camelCase by default ([#1120](https://github.com/coinbase/x402/pull/1120)) +- Auto-wrap eth_account LocalAccount in EthAccountSigner when passed to ExactEvmScheme or ExactEvmSchemeV1 ([#1121](https://github.com/coinbase/x402/pull/1121)) +- Added assetTransferMethod and supportsEip2612 flag to defaultAssets ([#1359](https://github.com/coinbase/x402/pull/1359)) +- Added dynamic function for servers to generate custom response for settlement failures defaulting to empty ([#1430](https://github.com/coinbase/x402/pull/1430)) + +### Added + +- Separated v1 legacy network name resolution from v2 CAIP-2 resolution; get_evm_chain_id now only accepts eip155:CHAIN_ID format, v1 code uses evm.v1.utils ([#split-v1-v2-networks](https://github.com/coinbase/x402/pull/split-v1-v2-networks)) + + ## [2.2.0] - 2026-02-20 ### Fixed diff --git a/python/x402/changelog.d/1120.bugfix.md b/python/x402/changelog.d/1120.bugfix.md deleted file mode 100644 index bbe9671188..0000000000 --- a/python/x402/changelog.d/1120.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Added serialize_by_alias=True to BaseX402Model so model_dump_json() produces spec-compliant camelCase by default diff --git a/python/x402/changelog.d/1121.bugfix.md b/python/x402/changelog.d/1121.bugfix.md deleted file mode 100644 index 9d7fe5daa6..0000000000 --- a/python/x402/changelog.d/1121.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Auto-wrap eth_account LocalAccount in EthAccountSigner when passed to ExactEvmScheme or ExactEvmSchemeV1 diff --git a/python/x402/changelog.d/1359.bugfix.md b/python/x402/changelog.d/1359.bugfix.md deleted file mode 100644 index ae54c75816..0000000000 --- a/python/x402/changelog.d/1359.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Added assetTransferMethod and supportsEip2612 flag to defaultAssets diff --git a/python/x402/changelog.d/1430.bugfix.md b/python/x402/changelog.d/1430.bugfix.md deleted file mode 100644 index 3fcb3bf302..0000000000 --- a/python/x402/changelog.d/1430.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Added dynamic function for servers to generate custom response for settlement failures defaulting to empty diff --git a/python/x402/changelog.d/split-v1-v2-networks.feature.md b/python/x402/changelog.d/split-v1-v2-networks.feature.md deleted file mode 100644 index feaffda9d9..0000000000 --- a/python/x402/changelog.d/split-v1-v2-networks.feature.md +++ /dev/null @@ -1 +0,0 @@ -Separated v1 legacy network name resolution from v2 CAIP-2 resolution; get_evm_chain_id now only accepts eip155:CHAIN_ID format, v1 code uses evm.v1.utils diff --git a/python/x402/changelog.d/svm-duplicate-settlement.bugfix.md b/python/x402/changelog.d/svm-duplicate-settlement.bugfix.md deleted file mode 100644 index 4d3892721c..0000000000 --- a/python/x402/changelog.d/svm-duplicate-settlement.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window diff --git a/python/x402/pyproject.toml b/python/x402/pyproject.toml index 4f19f9d13f..c23db453a3 100644 --- a/python/x402/pyproject.toml +++ b/python/x402/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "x402" -version = "2.2.0" +version = "2.3.0" description = "x402 Payment Protocol SDK for Python" readme = "README.md" license = { text = "MIT" } diff --git a/python/x402/uv.lock b/python/x402/uv.lock index cb061ba93e..37af8be178 100644 --- a/python/x402/uv.lock +++ b/python/x402/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -3407,7 +3407,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "." } dependencies = [ { name = "nest-asyncio" }, From e3f02dad33232fef1846075c4cac88fe26c0deb4 Mon Sep 17 00:00:00 2001 From: phdargen Date: Fri, 6 Mar 2026 11:57:12 +0900 Subject: [PATCH 032/129] chore(go): release v2.5.0 (#1471) --- go/.changes/unreleased/added-20260227-085721.yaml | 3 --- go/.changes/unreleased/added-20260227-175046.yaml | 3 --- go/.changes/unreleased/added-20260302-103254.yaml | 3 --- .../unreleased/added-svm-settlement-cache.yaml | 3 --- go/.changes/unreleased/changed-20260225-174750.yaml | 3 --- go/.changes/unreleased/changed-20260226-175344.yaml | 3 --- go/.changes/unreleased/changed-20260227-153504.yaml | 3 --- go/CHANGELOG.md | 13 +++++++++++++ 8 files changed, 13 insertions(+), 21 deletions(-) delete mode 100644 go/.changes/unreleased/added-20260227-085721.yaml delete mode 100644 go/.changes/unreleased/added-20260227-175046.yaml delete mode 100644 go/.changes/unreleased/added-20260302-103254.yaml delete mode 100644 go/.changes/unreleased/added-svm-settlement-cache.yaml delete mode 100644 go/.changes/unreleased/changed-20260225-174750.yaml delete mode 100644 go/.changes/unreleased/changed-20260226-175344.yaml delete mode 100644 go/.changes/unreleased/changed-20260227-153504.yaml diff --git a/go/.changes/unreleased/added-20260227-085721.yaml b/go/.changes/unreleased/added-20260227-085721.yaml deleted file mode 100644 index 838dd8748f..0000000000 --- a/go/.changes/unreleased/added-20260227-085721.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: added -body: Add route configuration validation during Initialize() to catch scheme/facilitator mismatches at startup -time: 2026-02-27T08:57:21.873969+09:00 diff --git a/go/.changes/unreleased/added-20260227-175046.yaml b/go/.changes/unreleased/added-20260227-175046.yaml deleted file mode 100644 index 5d57a9031e..0000000000 --- a/go/.changes/unreleased/added-20260227-175046.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: added -body: Added `onProtectedRequest` hook to HTTP resource server -time: 2026-02-27T17:50:46.051464+09:00 diff --git a/go/.changes/unreleased/added-20260302-103254.yaml b/go/.changes/unreleased/added-20260302-103254.yaml deleted file mode 100644 index 166c2e3bbe..0000000000 --- a/go/.changes/unreleased/added-20260302-103254.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: added -body: Add WithBazaar facilitator client decorator for querying /discovery/resources endpoint from bazaar in go -time: 2026-03-02T10:32:54.304235+09:00 diff --git a/go/.changes/unreleased/added-svm-settlement-cache.yaml b/go/.changes/unreleased/added-svm-settlement-cache.yaml deleted file mode 100644 index b2e32aa4f4..0000000000 --- a/go/.changes/unreleased/added-svm-settlement-cache.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: added -body: Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window -time: 2026-03-05T13:35:00.000000+09:00 diff --git a/go/.changes/unreleased/changed-20260225-174750.yaml b/go/.changes/unreleased/changed-20260225-174750.yaml deleted file mode 100644 index 37b6385c4b..0000000000 --- a/go/.changes/unreleased/changed-20260225-174750.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: changed -body: Separated v1 legacy network name resolution from v2 CAIP-2 resolution; v1 code now uses evm/v1 package, shared utils only accept eip155:CHAIN_ID format -time: 2026-02-25T17:47:50.706805-08:00 diff --git a/go/.changes/unreleased/changed-20260226-175344.yaml b/go/.changes/unreleased/changed-20260226-175344.yaml deleted file mode 100644 index 921f0987cb..0000000000 --- a/go/.changes/unreleased/changed-20260226-175344.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: changed -body: GetSupported retries up to 3 times with exponential backoff on 429 rate limit responses -time: 2026-02-26T17:53:44.305222+09:00 diff --git a/go/.changes/unreleased/changed-20260227-153504.yaml b/go/.changes/unreleased/changed-20260227-153504.yaml deleted file mode 100644 index 1802f6202b..0000000000 --- a/go/.changes/unreleased/changed-20260227-153504.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: changed -body: Add pluggable PaywallProvider interface for custom paywall HTML generation with PaywallBuilder pattern -time: 2026-02-27T15:35:04.609332+09:00 diff --git a/go/CHANGELOG.md b/go/CHANGELOG.md index 402d4af069..47ab393174 100644 --- a/go/CHANGELOG.md +++ b/go/CHANGELOG.md @@ -1,3 +1,16 @@ +## v2.5.0 - 2026-03-06 +### Added +- Add route configuration validation during Initialize() to catch scheme/facilitator mismatches at startup +- Added assetTransferMethod and supportsEip2612 flag to defaultAssets +- Added `onProtectedRequest` hook to HTTP resource server +- Add WithBazaar facilitator client decorator for querying /discovery/resources endpoint from bazaar in go +- Added dynamic function for servers to generate custom response for settlement failures defaulting to empty +- Add in-memory SettlementCache to prevent duplicate SVM transaction settlement during on-chain confirmation window +### Changed +- Separated v1 legacy network name resolution from v2 CAIP-2 resolution; v1 code now uses evm/v1 package, shared utils only accept eip155:CHAIN_ID format +- GetSupported retries up to 3 times with exponential backoff on 429 rate limit responses +- Add pluggable PaywallProvider interface for custom paywall HTML generation with PaywallBuilder pattern + ## 2.4.1 - 2026-02-25 ### Fixed - Fixed changelog generation to include version extension and eliminate trailing dots which prevent go from importing From 0cde67e789d35828a2d7a4e55e9ebc66fc2fd624 Mon Sep 17 00:00:00 2001 From: phdargen Date: Sat, 7 Mar 2026 19:47:17 +0900 Subject: [PATCH 033/129] Fix #1468 for legacy (#1479) * move check to verify * fix svm duplicates legacy --- .../schemes/exact/svm/facilitator/index.ts | 1 + .../exact/svm/facilitator/settle.test.ts | 199 +++++++++++++++++- .../schemes/exact/svm/facilitator/settle.ts | 24 +++ .../exact/svm/facilitator/settlement-cache.ts | 48 +++++ .../legacy/x402/src/types/verify/x402Specs.ts | 1 + 5 files changed, 264 insertions(+), 9 deletions(-) create mode 100644 typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settlement-cache.ts diff --git a/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/index.ts b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/index.ts index 9fe06b13a7..41d7607ba7 100644 --- a/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/index.ts +++ b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/index.ts @@ -1,2 +1,3 @@ export * from "./settle"; +export * from "./settlement-cache"; export * from "./verify"; diff --git a/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.test.ts b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.test.ts index 27dd989d2f..ddc1b4bff1 100644 --- a/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.test.ts +++ b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.test.ts @@ -12,6 +12,7 @@ import { import { getRpcClient, getRpcSubscriptions } from "../../../../shared/svm/rpc"; import { verify } from "./verify"; import * as settleModule from "./settle"; +import { SettlementCache } from "./settlement-cache"; // Mocking dependencies vi.mock("../../../../shared/svm"); @@ -105,6 +106,19 @@ describe("SVM Settle", () => { }; }); + let txCounter = 0; + /** + * Returns a unique payment payload for each call (increments tx counter). + * + * @returns A PaymentPayload with a unique transaction identifier + */ + function uniquePayload(): PaymentPayload { + return { + ...paymentPayload, + payload: { transaction: `tx_${txCounter++}` } as ExactSvmPayload, + }; + } + afterEach(() => { vi.clearAllMocks(); }); @@ -112,6 +126,7 @@ describe("SVM Settle", () => { describe("settle", () => { it("should successfully settle a payment when verification passes", async () => { // Arrange + const payload = uniquePayload(); const mockVerifyResponse = { isValid: true, invalidReason: undefined, @@ -142,11 +157,11 @@ describe("SVM Settle", () => { ); // Act - const result = await settleModule.settle(signer, paymentPayload, paymentRequirements); + const result = await settleModule.settle(signer, payload, paymentRequirements); // Assert - expect(verify).toHaveBeenCalledWith(signer, paymentPayload, paymentRequirements, undefined); - expect(decodeTransactionFromPayload).toHaveBeenCalledWith(paymentPayload.payload); + expect(verify).toHaveBeenCalledWith(signer, payload, paymentRequirements, undefined); + expect(decodeTransactionFromPayload).toHaveBeenCalledWith(payload.payload); expect(signTransactionWithSigner).toHaveBeenCalledWith(signer, mockSignedTransaction); expect(transactionConfirmation.waitForRecentTransactionConfirmation).toHaveBeenCalledOnce(); expect(mockRpcClient.sendTransaction).toHaveBeenCalled(); @@ -182,6 +197,7 @@ describe("SVM Settle", () => { it("should return unexpected errors during settlement", async () => { // Arrange + const payload = uniquePayload(); const mockVerifyResponse = { isValid: true, invalidReason: undefined, @@ -198,7 +214,7 @@ describe("SVM Settle", () => { }); // Act - const result = await settleModule.settle(signer, paymentPayload, paymentRequirements); + const result = await settleModule.settle(signer, payload, paymentRequirements); // Assert expect(result).toEqual({ @@ -425,6 +441,7 @@ describe("SVM Settle", () => { describe("Custom RPC Configuration", () => { it("should use custom RPC URL from config for both client and subscriptions", async () => { // Arrange + const payload = uniquePayload(); const customRpcUrl = "http://localhost:8899"; const config = { svmConfig: { rpcUrl: customRpcUrl } }; const mockVerifyResponse = { @@ -450,12 +467,14 @@ describe("SVM Settle", () => { instructions: [], version: 0, } as any); + vi.mocked(getTokenPayerFromTransaction).mockReturnValue(payerAddress); + vi.mocked(signTransactionWithSigner).mockResolvedValue(mockSignedTransaction); vi.mocked(transactionConfirmation.waitForRecentTransactionConfirmation).mockResolvedValue( undefined, ); // Act - await settleModule.settle(signer, paymentPayload, paymentRequirements, config); + await settleModule.settle(signer, payload, paymentRequirements, config); // Assert expect(getRpcClient).toHaveBeenCalledWith("solana-devnet", customRpcUrl); @@ -464,6 +483,7 @@ describe("SVM Settle", () => { it("should propagate config to verify() call", async () => { // Arrange + const payload = uniquePayload(); const customRpcUrl = "https://api.mainnet-beta.solana.com"; const config = { svmConfig: { rpcUrl: customRpcUrl } }; const mockVerifyResponse = { @@ -489,19 +509,22 @@ describe("SVM Settle", () => { instructions: [], version: 0, } as any); + vi.mocked(getTokenPayerFromTransaction).mockReturnValue(payerAddress); + vi.mocked(signTransactionWithSigner).mockResolvedValue(mockSignedTransaction); vi.mocked(transactionConfirmation.waitForRecentTransactionConfirmation).mockResolvedValue( undefined, ); // Act - await settleModule.settle(signer, paymentPayload, paymentRequirements, config); + await settleModule.settle(signer, payload, paymentRequirements, config); // Assert - expect(verify).toHaveBeenCalledWith(signer, paymentPayload, paymentRequirements, config); + expect(verify).toHaveBeenCalledWith(signer, payload, paymentRequirements, config); }); it("should work without config (backward compatibility)", async () => { // Arrange + const payload = uniquePayload(); const mockVerifyResponse = { isValid: true, invalidReason: undefined, @@ -525,15 +548,17 @@ describe("SVM Settle", () => { instructions: [], version: 0, } as any); + vi.mocked(getTokenPayerFromTransaction).mockReturnValue(payerAddress); + vi.mocked(signTransactionWithSigner).mockResolvedValue(mockSignedTransaction); vi.mocked(transactionConfirmation.waitForRecentTransactionConfirmation).mockResolvedValue( undefined, ); // Act - await settleModule.settle(signer, paymentPayload, paymentRequirements); + await settleModule.settle(signer, payload, paymentRequirements); // Assert - expect(verify).toHaveBeenCalledWith(signer, paymentPayload, paymentRequirements, undefined); + expect(verify).toHaveBeenCalledWith(signer, payload, paymentRequirements, undefined); expect(getRpcClient).toHaveBeenCalledWith("solana-devnet", undefined); expect(getRpcSubscriptions).toHaveBeenCalledWith("solana-devnet", undefined); }); @@ -666,4 +691,160 @@ describe("SVM Settle", () => { }); }); }); + + describe("duplicate settlement cache", () => { + /** + * Builds a payment payload for the given transaction signature. + * + * @param transaction - The transaction signature to embed in the payload + * @returns A PaymentPayload for Solana devnet with the given transaction + */ + function makePayload(transaction: string): PaymentPayload { + return { + scheme: "exact", + network: "solana-devnet", + x402Version: 1, + payload: { transaction } as ExactSvmPayload, + }; + } + + /** + * Configures mocks so that settle() succeeds (verify passes, RPC and decode mocks in place). + * + * @returns void + */ + function setupMocksForSettle() { + const mockVerifyResponse = { isValid: true, invalidReason: undefined }; + vi.mocked(verify).mockResolvedValue(mockVerifyResponse); + vi.mocked(decodeTransactionFromPayload).mockReturnValue(mockSignedTransaction); + vi.mocked(getRpcClient).mockReturnValue(mockRpcClient); + vi.mocked(getRpcSubscriptions).mockReturnValue(mockRpcSubscriptions); + vi.mocked(mockRpcClient.sendTransaction).mockReturnValue({ + send: vi.fn().mockResolvedValue("mock_signature_123"), + }); + vi.mocked(solanaKit.getCompiledTransactionMessageDecoder).mockReturnValue({ + decode: vi.fn().mockReturnValue({}), + read: vi.fn(), + } as any); + vi.mocked(solanaKit.decompileTransactionMessageFetchingLookupTables).mockResolvedValue({ + lifetimeConstraint: { + blockhash: "mock_blockhash" as any, + lastValidBlockHeight: BigInt(1234), + }, + instructions: [], + version: 0, + } as any); + vi.mocked(getTokenPayerFromTransaction).mockReturnValue(payerAddress); + vi.mocked(signTransactionWithSigner).mockResolvedValue(mockSignedTransaction); + vi.mocked(transactionConfirmation.waitForRecentTransactionConfirmation).mockResolvedValue( + undefined, + ); + } + + it("should reject duplicate settlement of the same transaction", async () => { + setupMocksForSettle(); + + const payload = makePayload("sameTransactionBase64=="); + + const result1 = await settleModule.settle(signer, payload, paymentRequirements); + expect(result1.success).toBe(true); + + const result2 = await settleModule.settle(signer, payload, paymentRequirements); + expect(result2.success).toBe(false); + expect(result2.errorReason).toBe("duplicate_settlement"); + }); + + it("should allow settlement of distinct transactions", async () => { + setupMocksForSettle(); + + const result1 = await settleModule.settle( + signer, + makePayload("transactionA=="), + paymentRequirements, + ); + expect(result1.success).toBe(true); + + const result2 = await settleModule.settle( + signer, + makePayload("transactionB=="), + paymentRequirements, + ); + expect(result2.success).toBe(true); + }); + + it("should evict cache entries after TTL", async () => { + vi.useFakeTimers(); + try { + setupMocksForSettle(); + + const payload = makePayload("expiringTransaction=="); + + const result1 = await settleModule.settle(signer, payload, paymentRequirements); + expect(result1.success).toBe(true); + + // Advance past the 120s TTL + vi.advanceTimersByTime(121_000); + + const result2 = await settleModule.settle(signer, payload, paymentRequirements); + expect(result2.success).toBe(true); + } finally { + vi.useRealTimers(); + } + }); + }); +}); + +describe("SettlementCache prune optimization", () => { + it("should prune only expired entries and preserve non-expired ones", () => { + vi.useFakeTimers(); + try { + const cache = new SettlementCache(); + + cache.isDuplicate("tx-a"); + vi.advanceTimersByTime(10_000); + cache.isDuplicate("tx-b"); + vi.advanceTimersByTime(10_000); + cache.isDuplicate("tx-c"); + + // Advance so tx-a is expired (> 120s old) but tx-b and tx-c are not + vi.advanceTimersByTime(101_000); // total: tx-a=121s, tx-b=111s, tx-c=101s + + expect(cache.isDuplicate("tx-a")).toBe(false); // expired, re-inserted as new + expect(cache.isDuplicate("tx-b")).toBe(true); // still cached + expect(cache.isDuplicate("tx-c")).toBe(true); // still cached + } finally { + vi.useRealTimers(); + } + }); + + it("should prune all entries when all are expired", () => { + vi.useFakeTimers(); + try { + const cache = new SettlementCache(); + + cache.isDuplicate("tx-1"); + cache.isDuplicate("tx-2"); + cache.isDuplicate("tx-3"); + + vi.advanceTimersByTime(121_000); + + expect(cache.isDuplicate("tx-1")).toBe(false); + expect(cache.isDuplicate("tx-2")).toBe(false); + expect(cache.isDuplicate("tx-3")).toBe(false); + } finally { + vi.useRealTimers(); + } + }); + + it("should not prune any entries when none are expired", () => { + const cache = new SettlementCache(); + + cache.isDuplicate("tx-x"); + cache.isDuplicate("tx-y"); + cache.isDuplicate("tx-z"); + + expect(cache.isDuplicate("tx-x")).toBe(true); + expect(cache.isDuplicate("tx-y")).toBe(true); + expect(cache.isDuplicate("tx-z")).toBe(true); + }); }); diff --git a/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.ts b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.ts index a733effb76..8391816b61 100644 --- a/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.ts +++ b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settle.ts @@ -35,6 +35,7 @@ import { createRecentSignatureConfirmationPromiseFactory, } from "@solana/transaction-confirmation"; import { verify } from "./verify"; +import { SettlementCache } from "./settlement-cache"; /** * Settle the payment payload against the payment requirements. @@ -46,6 +47,17 @@ import { verify } from "./verify"; * @param config - Optional configuration for X402 operations (e.g., custom RPC URLs) * @returns A SettleResponse indicating if the payment is settled and any error reason */ +const settlementCache = new SettlementCache(); + +/** + * Settles an exact SVM payment by verifying the payment and recording the settlement. + * + * @param signer - Transaction signer used to verify the payment + * @param payload - The payment payload to settle + * @param paymentRequirements - The payment requirements to settle against + * @param config - Optional configuration for X402 operations (e.g., custom RPC URLs) + * @returns A promise that resolves to a SettleResponse indicating success or failure + */ export async function settle( signer: TransactionSigner, payload: PaymentPayload, @@ -63,6 +75,18 @@ export async function settle( } const svmPayload = payload.payload as ExactSvmPayload; + + // Duplicate settlement check: reject if this transaction is already being settled. + // Must occur before any async work so concurrent calls for the same tx are caught. + const txKey = svmPayload.transaction; + if (settlementCache.isDuplicate(txKey)) { + return { + success: false, + errorReason: "duplicate_settlement", + network: payload.network, + transaction: "", + }; + } const decodedTransaction = decodeTransactionFromPayload(svmPayload); const signedTransaction = await signTransactionWithSigner(signer, decodedTransaction); assertTransactionFullySigned(signedTransaction); diff --git a/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settlement-cache.ts b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settlement-cache.ts new file mode 100644 index 0000000000..696fdce4d1 --- /dev/null +++ b/typescript/packages/legacy/x402/src/schemes/exact/svm/facilitator/settlement-cache.ts @@ -0,0 +1,48 @@ +/** + * How long a transaction is held in the duplicate settlement cache (ms). + * Covers the Solana blockhash lifetime (~60-90s) with margin. + */ +export const SETTLEMENT_TTL_MS = 120_000; + +/** + * In-memory cache for deduplicating concurrent settlement requests. + * + * Because Node.js is single-threaded, no lock is required β€” the cache + * check + insert must simply occur before the first `await` in the settle path. + */ +export class SettlementCache { + private readonly entries = new Map(); + + /** + * Returns `true` if `key` is already pending settlement (duplicate), + * or `false` after recording it as newly pending. + * + * Callers should reject the settlement when this returns `true`. + * + * @param key - The unique identifier for the settlement (typically the base64 transaction). + * @returns `true` if the key was already present (duplicate); `false` otherwise. + */ + isDuplicate(key: string): boolean { + this.prune(); + if (this.entries.has(key)) { + return true; + } + this.entries.set(key, Date.now()); + return false; + } + + /** + * Remove entries older than the settlement TTL. + * Leverages Map insertion-order guarantee to break early. + */ + private prune(): void { + const cutoff = Date.now() - SETTLEMENT_TTL_MS; + for (const [key, timestamp] of this.entries) { + if (timestamp < cutoff) { + this.entries.delete(key); + } else { + break; + } + } + } +} diff --git a/typescript/packages/legacy/x402/src/types/verify/x402Specs.ts b/typescript/packages/legacy/x402/src/types/verify/x402Specs.ts index 3295f7beed..53ab4d7a96 100644 --- a/typescript/packages/legacy/x402/src/types/verify/x402Specs.ts +++ b/typescript/packages/legacy/x402/src/types/verify/x402Specs.ts @@ -54,6 +54,7 @@ export const ErrorReasons = [ "unsupported_scheme", "unexpected_settle_error", "unexpected_verify_error", + "duplicate_settlement", ] as const; // Refiners From 34d2442cbf0633be50e19d2f98a63e1841971924 Mon Sep 17 00:00:00 2001 From: phdargen Date: Mon, 9 Mar 2026 23:48:30 +0900 Subject: [PATCH 034/129] fix encoding in paywall (#1531) --- go/http/evm_paywall_template.go | 2 +- go/http/svm_paywall_template.go | 2 +- python/x402/http/paywall/evm_paywall_template.py | 2 +- python/x402/http/paywall/svm_paywall_template.py | 2 +- typescript/.changeset/fifty-feet-cut.md | 5 +++++ typescript/.changeset/wise-rivers-film.md | 5 +++++ typescript/packages/extensions/src/sign-in-with-x/server.ts | 5 +++-- typescript/packages/http/paywall/src/evm/EvmPaywall.tsx | 3 ++- typescript/packages/http/paywall/src/evm/gen/template.ts | 2 +- typescript/packages/http/paywall/src/svm/SolanaPaywall.tsx | 3 ++- typescript/packages/http/paywall/src/svm/gen/template.ts | 2 +- 11 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 typescript/.changeset/fifty-feet-cut.md create mode 100644 typescript/.changeset/wise-rivers-film.md diff --git a/go/http/evm_paywall_template.go b/go/http/evm_paywall_template.go index 24e183877f..1f03ef1070 100644 --- a/go/http/evm_paywall_template.go +++ b/go/http/evm_paywall_template.go @@ -2,4 +2,4 @@ package http // EVMPaywallTemplate is the pre-built EVM paywall template with inlined CSS and JS -const EVMPaywallTemplate = "\n \n \n Payment Required\n \n
\n \n \n " +const EVMPaywallTemplate = "\n \n \n Payment Required\n \n
\n \n \n " diff --git a/go/http/svm_paywall_template.go b/go/http/svm_paywall_template.go index e58e9ec8eb..1ca1b8e095 100644 --- a/go/http/svm_paywall_template.go +++ b/go/http/svm_paywall_template.go @@ -2,4 +2,4 @@ package http // SVMPaywallTemplate is the pre-built SVM paywall template with inlined CSS and JS -const SVMPaywallTemplate = "\n \n \n Payment Required\n \n
\n \n \n " +const SVMPaywallTemplate = "\n \n \n Payment Required\n \n
\n \n \n " diff --git a/python/x402/http/paywall/evm_paywall_template.py b/python/x402/http/paywall/evm_paywall_template.py index c9bb46d72f..cb301fe539 100644 --- a/python/x402/http/paywall/evm_paywall_template.py +++ b/python/x402/http/paywall/evm_paywall_template.py @@ -1,2 +1,2 @@ # THIS FILE IS AUTO-GENERATED - DO NOT EDIT -EVM_PAYWALL_TEMPLATE = '\n \n \n Payment Required\n \n
\n \n \n ' +EVM_PAYWALL_TEMPLATE = '\n \n \n Payment Required\n \n
\n \n \n ' diff --git a/python/x402/http/paywall/svm_paywall_template.py b/python/x402/http/paywall/svm_paywall_template.py index 29eff3263c..de853d5bf5 100644 --- a/python/x402/http/paywall/svm_paywall_template.py +++ b/python/x402/http/paywall/svm_paywall_template.py @@ -1,2 +1,2 @@ # THIS FILE IS AUTO-GENERATED - DO NOT EDIT -SVM_PAYWALL_TEMPLATE = '\n \n \n Payment Required\n \n
\n \n \n ' +SVM_PAYWALL_TEMPLATE = '\n \n \n Payment Required\n \n
\n \n \n ' diff --git a/typescript/.changeset/fifty-feet-cut.md b/typescript/.changeset/fifty-feet-cut.md new file mode 100644 index 0000000000..7d84f3f38f --- /dev/null +++ b/typescript/.changeset/fifty-feet-cut.md @@ -0,0 +1,5 @@ +--- +'@x402/extensions': patch +--- + +Removed dependencie on node’s crypto module diff --git a/typescript/.changeset/wise-rivers-film.md b/typescript/.changeset/wise-rivers-film.md new file mode 100644 index 0000000000..e0d9af184a --- /dev/null +++ b/typescript/.changeset/wise-rivers-film.md @@ -0,0 +1,5 @@ +--- +'@x402/paywall': patch +--- + +Fixed encoding of characters outside of the Latin1 range diff --git a/typescript/packages/extensions/src/sign-in-with-x/server.ts b/typescript/packages/extensions/src/sign-in-with-x/server.ts index 429f12d1c3..5135000cb9 100644 --- a/typescript/packages/extensions/src/sign-in-with-x/server.ts +++ b/typescript/packages/extensions/src/sign-in-with-x/server.ts @@ -6,7 +6,6 @@ * - Refresh time-based fields per request (nonce, issuedAt, expirationTime) */ -import { randomBytes } from "crypto"; import type { ResourceServerExtension, PaymentRequiredContext } from "@x402/core/types"; import type { SIWxExtension, SIWxExtensionInfo, SupportedChain, DeclareSIWxOptions } from "./types"; import { SIGN_IN_WITH_X } from "./types"; @@ -62,7 +61,9 @@ export const siwxResourceServerExtension: ResourceServerExtension = { } // Generate fresh time-based fields - const nonce = randomBytes(16).toString("hex"); + const nonce = Array.from(globalThis.crypto.getRandomValues(new Uint8Array(16))) + .map(b => b.toString(16).padStart(2, "0")) + .join(""); const issuedAt = new Date().toISOString(); // Calculate expirationTime based on configured duration diff --git a/typescript/packages/http/paywall/src/evm/EvmPaywall.tsx b/typescript/packages/http/paywall/src/evm/EvmPaywall.tsx index f8663c5a15..b28c130093 100644 --- a/typescript/packages/http/paywall/src/evm/EvmPaywall.tsx +++ b/typescript/packages/http/paywall/src/evm/EvmPaywall.tsx @@ -5,6 +5,7 @@ import { useAccount, useSwitchChain, useWalletClient, useConnect, useDisconnect import { ExactEvmScheme } from "@x402/evm/exact/client"; import { x402Client } from "@x402/core/client"; +import { encodePaymentSignatureHeader } from "@x402/core/http"; import type { PaymentRequired } from "@x402/core/types"; import { getUSDCBalance } from "./utils"; @@ -154,7 +155,7 @@ export function EvmPaywall({ paymentRequired, onSuccessfulResponse }: EvmPaywall const paymentPayload = await client.createPaymentPayload(paymentRequired); // Encode as base64 JSON for v2 header - const paymentHeader = btoa(JSON.stringify(paymentPayload)); + const paymentHeader = encodePaymentSignatureHeader(paymentPayload); setStatus("Requesting content with payment..."); const response = await fetch(x402.currentUrl, { diff --git a/typescript/packages/http/paywall/src/evm/gen/template.ts b/typescript/packages/http/paywall/src/evm/gen/template.ts index 8d9a00e2ec..d31f495b40 100644 --- a/typescript/packages/http/paywall/src/evm/gen/template.ts +++ b/typescript/packages/http/paywall/src/evm/gen/template.ts @@ -3,4 +3,4 @@ * The pre-built EVM paywall template with inlined CSS and JS */ export const EVM_PAYWALL_TEMPLATE = - '\n \n \n Payment Required\n \n
\n \n \n '; + '\n \n \n Payment Required\n \n
\n \n \n '; diff --git a/typescript/packages/http/paywall/src/svm/SolanaPaywall.tsx b/typescript/packages/http/paywall/src/svm/SolanaPaywall.tsx index 4826ca06aa..74fa2f4409 100644 --- a/typescript/packages/http/paywall/src/svm/SolanaPaywall.tsx +++ b/typescript/packages/http/paywall/src/svm/SolanaPaywall.tsx @@ -4,6 +4,7 @@ import type { WalletWithSolanaFeatures } from "@solana/wallet-standard-features" import { ExactSvmScheme } from "@x402/svm/exact/client"; import { x402Client } from "@x402/core/client"; +import { encodePaymentSignatureHeader } from "@x402/core/http"; import type { PaymentRequired } from "@x402/core/types"; import { Spinner } from "./Spinner"; @@ -185,7 +186,7 @@ export function SolanaPaywall({ paymentRequired, onSuccessfulResponse }: SolanaP const paymentPayload = await client.createPaymentPayload(paymentRequired); - const paymentHeader = btoa(JSON.stringify(paymentPayload)); + const paymentHeader = encodePaymentSignatureHeader(paymentPayload); setStatus("Requesting content with payment..."); const response = await fetch(x402.currentUrl, { diff --git a/typescript/packages/http/paywall/src/svm/gen/template.ts b/typescript/packages/http/paywall/src/svm/gen/template.ts index 0ba985a098..954431627c 100644 --- a/typescript/packages/http/paywall/src/svm/gen/template.ts +++ b/typescript/packages/http/paywall/src/svm/gen/template.ts @@ -3,4 +3,4 @@ * The pre-built SVM paywall template with inlined CSS and JS */ export const SVM_PAYWALL_TEMPLATE = - '\n \n \n Payment Required\n \n
\n \n \n '; + '\n \n \n Payment Required\n \n
\n \n \n '; From 0334eab61ae0c110c846613de585b7c6a378edfc Mon Sep 17 00:00:00 2001 From: 0xFantomMenace <93462858+0xFantomMenace@users.noreply.github.com> Date: Mon, 9 Mar 2026 15:35:36 -0400 Subject: [PATCH 035/129] =?UTF-8?q?feat(ecosystem):=20Add=200xArchive=20?= =?UTF-8?q?=E2=80=94=20first=20HyperEVM-native=20x402=20facilitator=20(#15?= =?UTF-8?q?29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 0xArchive as an x402 facilitator supporting HyperEVM (eip155:999) and Base (eip155:8453). Fee-free USDC settlement via EIP-3009. - Website: https://0xarchive.io - Facilitator: https://facilitator.0xarchive.io - Networks: HyperEVM, Base - Scheme: exact - Assets: EIP-3009 (USDC) --- .../0xarchive-facilitator/metadata.json | 19 ++++++++++++++++++ typescript/site/public/logos/0xarchive.png | Bin 0 -> 25170 bytes 2 files changed, 19 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/0xarchive-facilitator/metadata.json create mode 100644 typescript/site/public/logos/0xarchive.png diff --git a/typescript/site/app/ecosystem/partners-data/0xarchive-facilitator/metadata.json b/typescript/site/app/ecosystem/partners-data/0xarchive-facilitator/metadata.json new file mode 100644 index 0000000000..d8f7351d8b --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/0xarchive-facilitator/metadata.json @@ -0,0 +1,19 @@ +{ + "name": "0xArchive Facilitator", + "description": "First HyperEVM-native x402 facilitator. Fee-free USDC settlement on HyperEVM and Base Mainnet.", + "logoUrl": "/logos/0xarchive.png", + "websiteUrl": "https://0xarchive.io", + "category": "Facilitators", + "facilitator": { + "baseUrl": "https://facilitator.0xarchive.io", + "networks": ["hyperevm", "base"], + "schemes": ["exact"], + "assets": ["EIP-3009"], + "supports": { + "verify": true, + "settle": true, + "supported": true, + "list": false + } + } +} diff --git a/typescript/site/public/logos/0xarchive.png b/typescript/site/public/logos/0xarchive.png new file mode 100644 index 0000000000000000000000000000000000000000..3a49c2b98a4d297e0d12f3a61a2db7c93c19abe1 GIT binary patch literal 25170 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
71%xACqjOag=!)!j| zXfSL={mKZ>0>ACu2!HtubkCPRoBC#bwQ^U4r||=nRMjP95pdc8;MOxY*xiTgB=Jy> zA95JGJ@DSY92$4@wjBOy)fs%1T_L8|JhRSQOp6qk%RUedyB7AO-HW+VXs;;Rt9=&P z+EC0pp+i?eO#n@oG$fu-NcXh4=#X$KSsN&GDFoYKsl4Z2pFJGa#QxQt;hNUT~9AoX!~g~5;%lBofQ{`}?WBlq)XOLxk}VG|$p&1-dVZZ%IY zHtaoFTtvAfn~p6HiNpsZ7ois;Pw8R@o{UoMZYH~vfZ-4`pw#MpgVD3>QKj0fWs>2f zMx`sGjgkO@Up@c=)GCb`)@}V{B(jOVC`U-K0C+&LH3WzyH3D-U!cz=zQ183Rhs@Ic z%MLFw1ysk&>px`pe>nC3Q1kyy24G*iy#Bu?!_ftZv51BR?)dN_@O%X^KkY|;j!*oY zAP&AxzzaxLS{8guTIQCF+ Date: Mon, 9 Mar 2026 12:38:33 -0700 Subject: [PATCH 036/129] chore: update Spraay ecosystem listing (62 endpoints, GPU/Compute, Search/RAG) (#1483) * Add files via upload * Update metadata.json --- .../spraay-x402-gateway/metadata.json | 2 +- typescript/site/public/logos/spraay.png | Bin 26128 -> 23060 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json b/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json index 097428d459..ceb0646ca2 100644 --- a/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json +++ b/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json @@ -1,6 +1,6 @@ { "name": "Spraay x402 Gateway", - "description": "Pay-per-request AI gateway, batch payment engine, and DeFi data API on Base mainnet. AI agents pay USDC per call to access 200+ AI models (OpenAI-compatible), execute batch USDC payments via Spraay protocol, and get live swap quotes from Uniswap V3. 6 paid endpoints with Bazaar discovery. No API keys, no accounts.", + "description": "Full-stack x402 infrastructure platform with 62 paid endpoints across 8 categories. AI chat (200+ models), batch payments (200 recipients/tx), token swaps (Uniswap V3), price oracle, cross-chain bridge (11 chains), payroll, invoicing, escrow, wallet analytics, AI inference, GPU/Compute (image/video/LLM/audio via Replicate), web search & RAG (Tavily), email/SMS, webhooks, XMTP messaging, multi-chain RPC, IPFS storage, cron scheduling, logging, KYC/KYB, auth/SSO, audit trails, and crypto tax. 63-tool MCP server on Smithery. USDC on Base. No API keys, no accounts.", "logoUrl": "/logos/spraay.png", "websiteUrl": "https://gateway.spraay.app", "category": "Services/Endpoints" diff --git a/typescript/site/public/logos/spraay.png b/typescript/site/public/logos/spraay.png index a60f29317239a8fa67f0948a3287ba6c50b731e5..57ca47f18a9258df8e937181e11d8b1bce2d02bb 100644 GIT binary patch literal 23060 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 QTmS$707*qoM6N<$g89XR=l}o! From 94787f497e99b60bba700f53a4e28f29d65def0a Mon Sep 17 00:00:00 2001 From: Eddie Date: Mon, 9 Mar 2026 12:40:49 -0700 Subject: [PATCH 037/129] Add ActionGate to x402 Ecosystem (#1486) * Add ActionGate to x402 Ecosystem # Add ActionGate to x402 Ecosystem ## Summary Adds ActionGate to the x402 ecosystem under `Services/Endpoints`. ## Files Added - `typescript/site/app/ecosystem/partners-data/actiongate/metadata.json` ## Why this belongs - ActionGate serves paid production endpoints using x402 V2 headers: - `PAYMENT-REQUIRED` - `PAYMENT-SIGNATURE` - `PAYMENT-RESPONSE` - Includes public API contract and SDKs for integration. ## Validation - Confirmed `metadata.json` schema aligns with existing partner entries. - Confirmed category is one of accepted categories: `Services/Endpoints`. ## Notes for reviewers - Endpoint docs and implementation references: - OpenAPI: `https://api.actiongate.xyz/docs/openapi-v1.yaml` - API quickstart: `https://api.actiongate.xyz/docs` * added actiongate logo --- .../app/ecosystem/partners-data/actiongate/metadata.json | 7 +++++++ typescript/site/public/logos/actiongate.svg | 6 ++++++ 2 files changed, 13 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/actiongate/metadata.json create mode 100644 typescript/site/public/logos/actiongate.svg diff --git a/typescript/site/app/ecosystem/partners-data/actiongate/metadata.json b/typescript/site/app/ecosystem/partners-data/actiongate/metadata.json new file mode 100644 index 0000000000..50943da533 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/actiongate/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "ActionGate", + "description": "Pre-execution decision API for autonomous agents with paid risk scoring, simulation, and policy-gate endpoints using x402 V2.", + "logoUrl": "/logos/actiongate.svg", + "websiteUrl": "https://api.actiongate.xyz/docs", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/actiongate.svg b/typescript/site/public/logos/actiongate.svg new file mode 100644 index 0000000000..dcc1697bb9 --- /dev/null +++ b/typescript/site/public/logos/actiongate.svg @@ -0,0 +1,6 @@ + + + + + + From 8def75862ab5b72671fe42b03bd3d9c52db4f07c Mon Sep 17 00:00:00 2001 From: robtex Date: Mon, 9 Mar 2026 21:41:45 +0200 Subject: [PATCH 038/129] Add Robtex to x402 ecosystem (#1517) Adds Robtex network intelligence service to the ecosystem directory under Services/Endpoints. 50+ x402-enabled API endpoints on Base mainnet (USDC) for DNS, IP, BGP, threat intel, and Lightning data. --- .../ecosystem/partners-data/robtex/metadata.json | 7 +++++++ typescript/site/public/logos/robtex.png | Bin 0 -> 673 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/robtex/metadata.json create mode 100644 typescript/site/public/logos/robtex.png diff --git a/typescript/site/app/ecosystem/partners-data/robtex/metadata.json b/typescript/site/app/ecosystem/partners-data/robtex/metadata.json new file mode 100644 index 0000000000..b8c3260f66 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/robtex/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Robtex", + "description": "Network intelligence APIs for DNS, IP/domain reputation (100+ blocklists), BGP/AS analysis, passive DNS, and Bitcoin Lightning Network data. Available as 50+ API endpoints for seamless agent integration.", + "logoUrl": "/logos/robtex.png", + "websiteUrl": "https://x402.robtex.com", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/robtex.png b/typescript/site/public/logos/robtex.png new file mode 100644 index 0000000000000000000000000000000000000000..146092900029299c773cb1f5777c67f4966552bb GIT binary patch literal 673 zcmeAS@N?(olHy`uVBq!ia0y~yV4MKLEX+WWqKVr7fs{hBN02WALzNl>LqiJ#!!Mvv z!wUw6QUeBtR|yOZRx=nF#0%!^3bX-A=mz+Nxc>kD|J%3!H*fwwfByf)i~oaz|EsC} z*VP4@^`C>|zpCngef|HdSO33p17!Mw>o-z>6l0RNy9;0bUITw1hrPtp*OmPhlc=B& z_mp#NQ-RWtJzX3_DsH{KyU~+5QKI3YhTjCiTD4Oe1z5!k*vtjq+&y@! zF(-J&qaDqA#OH0dx074ADa%BnaVy{bXXM Date: Mon, 9 Mar 2026 15:42:35 -0400 Subject: [PATCH 039/129] =?UTF-8?q?Add=20Soundside=20to=20ecosystem=20?= =?UTF-8?q?=E2=80=94=20MCP-native=20AI=20media=20generation=20with=20x402?= =?UTF-8?q?=20(#1480)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add files via upload * Add metadata for Soundside partner --- .../partners-data/soundside/metadata.json | 7 +++++++ typescript/site/public/logos/soundside.png | Bin 0 -> 373216 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/soundside/metadata.json create mode 100644 typescript/site/public/logos/soundside.png diff --git a/typescript/site/app/ecosystem/partners-data/soundside/metadata.json b/typescript/site/app/ecosystem/partners-data/soundside/metadata.json new file mode 100644 index 0000000000..5ac0fc9de2 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/soundside/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Soundside", + "description": "MCP-native AI media generation with x402 pay-per-call. Create images, videos, audio, and music from 5 providers β€” composable via resource IDs. 22 tool/provider combinations on Base mainnet.", + "logoUrl": "/logos/soundside.png", + "websiteUrl": "https://soundside.ai/docs/x402", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/soundside.png b/typescript/site/public/logos/soundside.png new file mode 100644 index 0000000000000000000000000000000000000000..347ff9d26134a6e959ad897af39535292cfa1fe0 GIT binary patch literal 373216 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 _v%;BdR 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 z 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
  • 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

    ^k9yg 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

    N1{6|6v(Wslkbql9p^-EwMwAMczf4W?<( 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 Date: Mon, 9 Mar 2026 15:44:44 -0400 Subject: [PATCH 040/129] feat(ecosystem): add AI Security Guard (#1522) Security scanning API for AI agents detecting prompt injection, intent drift, and credential exfiltration. Pay-per-scan on Base. Co-authored-by: Fard Johnmar --- .../ai-security-guard/metadata.json | 7 +++++++ .../site/public/logos/ai-security-guard.png | Bin 0 -> 804978 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/ai-security-guard/metadata.json create mode 100644 typescript/site/public/logos/ai-security-guard.png diff --git a/typescript/site/app/ecosystem/partners-data/ai-security-guard/metadata.json b/typescript/site/app/ecosystem/partners-data/ai-security-guard/metadata.json new file mode 100644 index 0000000000..90dccf3b8e --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/ai-security-guard/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "AI Security Guard", + "category": "Services/Endpoints", + "logoUrl": "/logos/ai-security-guard.png", + "description": "When your AI agent calls an MCP tool, fetches a URL, or processes a document, it trusts whatever comes back. That's the problem. A malicious API response can hijack your agent's behavior or tell it to run malicious code. AI Security Guard is a firewall that sits between your agent and untrusted content. Before your agent processes anything external, we scan it. Five specialized analyzers β€” not LLMs, but deterministic detection systems β€” examine inputs and provide verdicts with context. When something looks wrong, agents get an explanation of what it might be and why it matters. Operators get visibility into what's flowing through their systems. x402 micropayments. Pay per scan, no subscriptions.", + "websiteUrl": "https://aisecurityguard.io" +} diff --git a/typescript/site/public/logos/ai-security-guard.png b/typescript/site/public/logos/ai-security-guard.png new file mode 100644 index 0000000000000000000000000000000000000000..d85be600a7d1aee0c21b3de2b4cf470b90c19a21 GIT binary patch literal 804978 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


    3Lt@_@zB5ySF`VK_iiPq$c- z(gE5fQs;~TcOnLxyqHn)mOPD!dK;eQ%{Q@nNX->Z>brS0=mz)45eFy*LIP(2PBM=L zt}Rv9m$;cx(tap5$9{&A(h}`DngOMQGPtB785e~^1mJb@|N8jDc&$Y(UvN>V`XiF4U%Bh*|&uAOJ~3K~y4hfpAW!VW#MNHC&lB zt&N?Bg>hfYODffLPJF>4;g<*m_x+-4B-2(JxWJxK&|cT7>_BUY)WC^G(f_uwUj&a9 z9szi;=0DR}JKwIgSgR8x*Zv8(ag;xy5*Idu2F~#euppkHd9Yh+OUg8YQKwkec2**^ zc7Dh>M(y!Qd`e(yu>KfKTFqa$t~9&kAHEK=f~+xNJ* zShJfZN;NJ|Uy*7?Ovt+(XJ0=>b-=3f@a`S%9KIM16{uM92`pPNu zdFSJ!cw04T349K=M=d_CQwnN#)1!OvrhOubQlrm&^HP|}sWDHxF1ZO{*E1wVaZ@&{ zQL%%0&Mt?ZAOGNcTwK25^yxD+b@ZuYyW7x4amiCu_KaeUB5m$qZ`JAK)v4n(m#8u~ z+J6JXwfQY4dAQu+SR_J(XmCs zU!g730Ven|80?jAfe$errG_1VT+8Hqb+jV0LAa_1`x4$7S~69t)6t`PTyu3GYl6~E zbHYvPDAUB|{E}QC4PT(O^5mZ77 zT*)Pz?bX4ptx?8_QMYcW39%-J!Dv<_xv`~nO3szBxb&+Nms)A(ZRfURp1gX+m!Eyc z)r(hbuhx`mq@-x-Se=}3>pS1!!@u|m-+%jUrabZD{G2a8f5h{z9+PjKbNTE!mFJ9A zkUCN+VJs&w2$m;AI;h!|0aB3S;97N~m(YMqtWV72vj*+n+o>gAiQ0N5Z2-dDokH<7 zDH3k3gIw0eQHbP%Ar-l`1AelXxgg?I@Iui23HrRunAY9{AeN5IOyO@zlN$3VslP5c zUB(k=k+~BT8mfpV?Uh1gz8|KNO&{| z?pr{O&Md)}5N9Vy4I@I4XhT?Ma6>S%hKxs{>wP|SNf8NXnz|;-&%LRSk2T-tJSRT*~9m8Vf{xMw#MJdIZjK1bM3t(6*IC!0Y2b@{m9H zd(@%kg-`+P7%2tq`F3t?9hwYD&0j~78l|_QDm@CMDwfPW0(*fDFBtYNk+$S*n?m&E}0r+GgJ9lOA*nj%IAP zuXyzPpKqqHJ+lKC}_nc~Js&P?#Hbr7rR z`@KS|^PgyfXn9ss)A2SVzlfqVp_0&H$#8gtu8tUP-{*UO{u4fY|9y@RmJF$*3%zS8 zg&Td(kACn&p1nB5rX6KBk*}`EC1b$)>=nam#p=cpzy9d={OzCrnB(Pw?O6Ec@{CU& zKjPQ_{3}ks`ik-Vg0kB%Zb$M|ymB0O*_w%6+;>e%^Utt)jRB!?ze+4EH3D8$tV9*C zdiRQ)GiA5q@mJsQ{0HCT-m*tUXAcNX$)BJ3JbU-v9WH+GL!Nx`n9a*m&^4F?Zgncy zlyQ*A=cu%#xS492C;K&L2e>MMh#Azq$=nPinpf|<(iJFBi+yKy0COeL0xfF{3SVIZ zxP->R^?RiO#90f98*t`;fin>#);x>8=eZubif}FD_thg3>b@K+d?%(6iTkrC>fB941zjp^w;oZCU`0P7x@#|myn$&e1 z3`?FpdBRjTz6O-)vYDE_ONj*75?xs|*bZ&l60b{^DA~sXjmA#$1g&m;T8gnbJL98I zK4P_8@aC;s94!Vnv=L=DPMltC_~_HmdH%_lT)sGUS&aZz=~oMmAKvGUci-g)@4w62 zM>i2Q-nw&#hbMP<^xzGizkJH$#iwL*mdxh-%%4bc^FBeKbE;95E_Cz-6K@4;Is5Zy zKwV>)1z<;UUjkH^O$x0g-#!geZ4!V64unF! zhAEMnQ}Y8f(CPrYP@{7|lLZ7rF5->Wg3x0PB?XA5N)#M?ez`0FmmS1fpc1|a8sJ|@ z;8kMHltN0y0T$V>fqn1N9ICIS2}RA>OIC&5Zo{-OQb^R$MCubMbq;i>kYX&&fMe5Q zV62u4ie*;!-eEXcF>k!uR{WS-fT@KcWb+H~0U@!6`}_+qE@U6fYn*&5=oEw^g7!Vb zunb=j1#+xW&6CNIty-&yNKzqT(jnR-wKwM`^(JY7NSBHzHp#l8+neaUC3^PgPd4%Y zQ$6q3$G`J<4FJ48{#eHh0KY&$ztHk+5CA(vIGRCx89eDvW=QSO&f7XC%zAMVKxfq6 zR7Ks>U&YIu388n8UV3paqg0c(1EBSCibR|!jcGT;TQw3Z;a}ktku6@=okx^RGw+#0 zZi#C0+-KXo5*x`b;)s7K#HT%tn5#Fn zCA3|%AdKf@fiQ`9k1GkI!73HP*hsEd{UcfOq`61Bgrpu*b@M;Mph}foJP|<^83y{J zo4otu5BZB9{D9-dFejU3ehyw?dT?^Wt=o55U!JnNIOlw~CRKF+XB^p_z2enZ9lslQ z93HLs&V&0rdGU&me)oIMUY>ILsFrtI-y));*P8%qw`wSp#{uWp{DTi$`Db`_CV7>%;G{NUl*WwPI1ZE5$392dcdN z@IFVkZ}DgO4m zY{Y!TYP&BnE}OZQh%|q!nNbkLh`mW)jHiYZv>>Z{pD5JT^Xn4 z2?y&9S1(RE{qhlLN8PQNwj-PMhSd2M(RGPowc_yjnB#j7`Rl*>OWwb8i=)(0Ot`x` z;^Bw4xwSgtXWH}C7oTur+;Jf=t~XdIj!f4cNe=AP>dCZ*pj@gty&h+tNvY8~&&P^c z{9Nlicgr}jU2oB|Qy%~3HVpb zus?^UvKI@=c>^1Q@duS84O9q*T5gg7|Dr@B=uzn>=={zMh;9MV0YtnfGNl0_*(vKO z`E^nE9s(tj{8=WUMpAWVL-sX26JUVGf&nPbV3|^|CnV$%(LKi0f$IcV5o#)=kBMzz})MgG4p%~`FN0O-lkRp@@Y(=ZGc!JXTnWuzLg`TLXIY9%Vd7o|twoZG)~cn{-aM{csIWq1iPV8w2Nmf=thXZF z*pZTuRwKG;?R(lu{plsue~Rb)`uKMqe=HL~;9C>n_3{7TV+H{pc+o*_-h{58(-M^u z#wk4{uV1R+afN72sw$fBZOP+PMWwSuFG>e=<~{)Glr1z#Fna}4i7o)`WK>Aq;1siO zE&SJXu{6T92ejIfF=&zW9Q5vC0Ey(E(282a8|I)yEtB(>JZ}90tx|JlER!b*#S!f? z?h|&aPPZ@DO!IOn@miUUjGVge!A2>qU7LdfwJ164^@Zlj@8{%I^!N-}rI{u+!D6?+0yAY#Qx(rI9T%w7adbK3k1 zX!j#t@2&gVXJ{nr5ePPLrX}gJhj!ZewqU|PJ(FJ3FIvi;jMgSoR&-CGwQL;*`8RTZ7IjrSj&(`@DSd4cnueT)aA?R5!3R6L#w> z^3%$8H}ZGmj$a)faCLUY`Ky=I^_q**bH=Mn@;G8;3a5FSDeWo=NipuG;#ISdG-w~! zsfj+QrXot7MzF%T*^={!6mz*i3T6p~JdUK@hTW?(e*5d+a{KrOAKbppje}LRp)>kU z(Uizj;UZ_Ayf|fjaYf&E>_j5@FIXz_&?EtocvP>hYOEWcFnMy~RntcQZ-`f0`v9WLL^D%s zySVu}qHO^BL=AQnZbn9{%(m~^gAzniAdQ*SBrg_opn^$(nlOo$hp8gg%?u=|1)Kc5 z)r^eM4Lt>8ZI!NHusy#(dw+&w&Zs0xhQ0?KIu33eaeVh4-+ljkeDD4}j?~XnlF(a1 z$IQETPB{KQ|9AfHzf;amU$R)P=C!QkOzJ_3pSx?o6DD;|G`;<1qA^*@IFVB4pbt*f z&Qn29QlAhLHkX%_THOm`S2%zAoKJ6`aQEJQmIo`&FE04>H^1lX%SUW3FMI6l^G!N+}IUj)Y!t z3VV>fG_J$6GQ}fFDXy&;+U-HP8eomq_`U!K+BtiYY_qpfDoW|XcSZ1u!steXv#&x4 zNdii-&gC0Lu)K2spk}I;c^$acW+~Q0_G?e<)vXob{G6`+zdx*4+hXiod#k^{ix$uc zWNOUM_S~51sDg^rqKb4Tb*Lr_uq9#xLQ>JLlbR--Qp)IPNU3fFxVpA_a_toUM2@`^5erBkRNbP4PTry#BW`0$wq6t%zBpTql zkp$~RM6}XTO{JU5^v)6Z)(HgCos?l%`e|06^@na}4>a1gMx~gjQninss}HfXd(~~f z*0KQSZvPbpYT5@gPF0aIAdkeklK}hzV;z*j4 zJ>b%kr4n)j#}oF?vw;TpCpCd*))XU|8MY@Z=_GSi0OL3Da(kUT)Z2UC!0XTnZ&xpuKqZf@hbP zym@>aEy&!QN;)Oy!X!q~%6Hzl&*P`}I6r;PFf5s_)>tW&9M$b{L`!B`U-Bep>gcW8 z%64Sh?yzV}DP}W8ULr}fS}+tbZ`Fx-wI5Zq>*yCthJyq8!<%%A75$LdU0pF=UZUN= zcy&R}B^Uuli`1>EJ)IWrb8C(ko@7zB8Al#Qz6a-LXY8at*GpChe(V0Z!4A_!B^kW(;*Dhb8J6KkvPzQ0}X=$AXXVeqv# zIY8zKONSzKdPrI>Y271E}l;8E-pDdKj!S| zipL*+jHZrhJCfH|j8|9eb{nrYOGm#5|BlPm-{=Hv=o~<&ZS4v&NoKqY^6) zI!5KcNnNVS4C;t5vjG}_v>!_i$`)D`ps`$})S!l=JcwdT>1*QxLVnC~%SWY0t)d*dO zluF-qrY@XDreQF%NjKM2h45`Q;xf@%pJFGF2m(G7m}$oRO;6}+OQ=tROz{0ZrA)tA zSUIQ!ec)rV$p+NJM@ecO8#|HGf%ZvQCQXZC9swPRj!c&_dAMvo0Gl!JcL`AcTj%>- zyM|ZC|KNB<0K7W>GY|QruV71R7mo#u-d55CES5+=lCstKQA{%8bX>60uDUrLL$P&kP0nElm5qOB5zOCl5OR4>> zeETB5UE|;zOERXSMmDZiN*O_?4X|1*!|&j zmMwIYfv7U6AZo-wPCa?Kq~G1;%B|PfzH!scnRa*CzIK&vkvV#Cz`<9KDZu*l)a0u< zQ>KyO{DO<)V?KTKnCpMF$KE0{)j}ziR1)h_%ndsyu5T@Q_pN(8{QV~e&M|_Zlxj3d z70#wYcX@6ql(ACBkrF1BW%7D=*~rY$?w8$ap{7hqn1laf!S?)rGL0j}iHqWn>52h8rb-nf0@Meuky&1TQc9Zu zP3z*I-@F21!imowTXQx|`z(2-M8^(|x>*nM+vB#_`OC#>&s%nnl37iF7g zn^9|0rD`FXPQ;j35-CUlXy z$C2D+`sIRQwLvx+Y^} zQ5h%3VQuXSbEfOFb-Nfw>;6*BL@sYF5b0pibMx-&ym{j~eae)oERuhI3Jd@Hi*e-f ziv!M%ju?xTAf&!WYoZfjYj>O6_vF5#mO>pzQ}YZ1sT6b^2pUQ&XlI0n`NovC=NTsz zWlu^QC=IrGYekF)iYjiC+PnG=bs*|8@dWCGcP5B51J`)=-0J*& z@4!d_b+Sg(jYoqF^K5#UT?ViWU@E{y_f=}F{nS=|BS8-M^DID#>&D9jW+E7@ePDDj z5b<$RL&j+HEBhXWn(87k6AmH{wv+n(XLH!Xv6`aVB`R7p7CCQ||H=l>7n;<$p1fe28Mx^*APA7?+O3t;?3AL+~zEsIb zmnBU(kEER)qz*7WK>p?-^7Hxaze@l*Znge9Utb;H;p0!$2JqGKmwB``n|U0xEi;sN z0GC4TA?pg!ZC|4kxhlC@?3vVvXZkMrUZ|jCZvdD@=oIY)Ns`1>syahE-{>G}#Vp&A z7ghq0nxR!>6y_{~1ppgnG6DVx!ayR7Y{5wsH_wRmS|&l;H2UtJmC!GC1mo%D!Ix`B3w zB3115@C>?I=>d|wCJ)Xex^8q)YYT zWI)G=l876^iC@L;C9d8uhyS!O2Al{9c`0_yt)-!08BZH6?LOJ_lLHhZ11c6kPQ}Je zCBVO(SB-3jlTRuR=w;(IlM@5ko%*wwj5vu)rhCY4c&L>wcQzD@T7AD{(z0jk>NS=( zZ*k+D_qcukKKs|Ma_9Bi+_-*)E(zZ}JK*pB_y2?Sdd>QBK(!z!<1le~bj<1Fr+jte zA-Aqx<9m1S&}9SsRu}JqZ#75j*REcrUv5z+lkrmulmM5)G_DyhjrkFTQmk&;=7{|Z zV@wclpC_gSXd)hk+|%_7ws!aE_O7u1<~=_6=tDky|9x)nZnL{su$oK`{hOcv6PlEw z6ZO>F@@erP6#IEqxjZ`H<)hCzySU)Bo7ec@dk=VR+UI`3REz+y z@~FykXF^f-uU+BB{yxhjOkoV#nMq#*Zz`Ou*ZlT(zh_vj=e4{TDJKXuCF`4Riz8(m zNL`|q!nB$U{8VKcN3X^98uD65U7~nvz1FQ=%tNAX~#?B6Xmnc(lRlcp$ig~%byj=11v!`4hpD?XQQs3EJqi4CZ&CZo8?A^M> z?%p03r)R9sFIb_C#KB7y`ti!Y-(yEP1PLU z)fFyL5ib?hOp<8xr>@-boz)CN++pAME+@^bRG|70u`y{y7T!?Pfvo}2AZG0vl86!2 z4x*>3q-6V`FY)BqCyHh2B}(z2B^AVF{E^WYt90-drD51>pJcQMl%hxuZJIWsAUX~R zaeW>?RHf#S*4yvRbg+_>?V%F#e;{`@b}|+>Oztlr0;NWInkgHSs>egxN_|qhFKXnB zZTaSf(FhK45=I+2lByzI#6Z=~Jwul=OqJC4-U@RK)%;&{a^^tI)5Tn#bS}ea3Z_^? zrL8NqY6I^rtnh^?)+k?Ie5V&}R^c!J03ZNKL_t(i?%J{=t5_RSveSSecSG0&WwS}Ce#K{_OLNop3`Y0V)lna6svcd-~b;m!h9 zQ=Gfrfj?}ZLJPX1z}16c!t@PVSYe>9p-20dwGjq(C;S&4Y={7LqKu>03L7}k0OgYf z7L-a+p^VjA>ZO*kjx2g9)*n5L0gKBN70cw8inRbtSO&>6`Nc^D4H>>W)0e3>;2ry| zdhluA&mI8k_3o;bFkmlE7zEMKUL$Hg1IYX97yodZQleV;AMa}o9x_rjSqhG5g)zx4tK6zvAS85oi6j?2jA!E*H5`PJtg(0 zNH>rs(5X_XP3kR4Sg+QcA01I^bMzFD>&(bvb@}j2-EJjL77la_L48b}mBwJx38*cUNwl?N$S$vYfNGoYU z3zcG-T9eFdHRAE2hUlboN)Zjb1q&!d`b_~VP4v2c`72>Vj+!WVj3b-Ah2Lqnjc49eH zf+^;Mk8R4VR|c2c}a_1M+S;LC*{z+IpGkp zhWIQ{Z@p)aWyC(ifmVJ+5;E3K(bP(XX&k77dAE>~tDu5Vbh(l55fP_FLc+*&nb$Eq zCW-cts%>02hZ5F1Ha^4@WwAHM-$geD<6FGs)5z4EQ_8h!k4T@;zCtI^Cvum%(pM$t zo>U5~u8^hyxtwF+SUA5c$9L&mUmgD+kN*e);D0orW4(NJ{AC`_(YGhP_MfB|dEJ^<93n5qH4ianuJ^8~1> zEqibKQ#Bs|N4AsJ)@H9NFhQBL@f1z!UL)`~XaC6Lt4sNUaIj!h8}T0CxoyT(D7cCM z@pf*yao?N}h)fP?E-k1Vce%QP!BI+8BQ?am3udms>iL5Vh#;(G12#UVC@*NwaS45> z3e?E~B>A<@#0H+pHd&)Z>?I_Hvf)hcS$aeap!=Ar#yHJVPbU+qqz$Ek8TXMpDw*6R zGw{pVK0h+jc?L;^-1k=VUyHdyr{oUy9o=G^{>nAp`|%I?>Bk?k*Y!3Y#zGaL&zZfg zjtBSO;>n{gD5oc!jsufgkLI#ob9r>i!Q-zNxW0(HW2b@CDi>%Grw5$sz00Gse}LGOi5tRfRH=s+BV6RE-35b2#<(erggMDs`SL z&S*vUzj{U=b$=26zL5fgv3ma1)-s!$5_39g%AH`0a+kWXSfvK2rDaD^n%So?E1u$) zGglBG~^QRC63G|y_vFJ%zSe>5oyWf7o-K*ER zfAt1Ciw<$`4l1lm;q!w7e*f9$oV`3^eRg3Au_P#o+%MR>ex3V&^*$ee?|trH-Dg#m z_wL@~#pxN3zW$0w%P%sq6uQ4vgN;*7N zh%9_9Y9zE8n6Fbbg#}4Yc6pXth|(Y0>sJhuicKrOHgN+<8rV$Y-C&Z(1v_bxDOyQYT+slP`mK%vTBLA;c|Z&LMo(~OBvGE%c3i;DJ1QWn*uHFr`=E|oME6J^|~$nh&2 z^y>Iu@c54)0A4Xfua1B3*hJH@R}znHmH_O~$bMCjK9+ZNKO9Y2vgKAak&xMZx8+qm z`6VgY-(-o_x1ch!-Eles$z5P2d2e)u4Hp_BsE(jneFIeWI7H_QiFBJ81xho|G8#l? zk|1T!$w~mG(l%05D5cuJ8X1RbpuJiEQbn1(K6p}lOk2Qc8*l*n*@VxW+YOjU;BU40 zrOb7@YAx8ITK0(m`Tln^Xs~+|oz`fe!?W%ie;---;xg}_pQ2&u6;!61>HNi+BtnrDKFJnUp(3gnqeAw|9kizyCfTfAB6hw-$7Lrc~&&g@6TR zHwo{*b)Qdv_bJ2W1zHA9UJTybx-!)=ml>d(pI^|e20F>C&Q8e7jyjC2&n_9)D^uar z(Io$Bnf^LWt&Bl+?p~n9S^y?O;bKJEtO)RVc`RCvLftO!C;ozI6469YU)~-wJT-jr} zv&WUYZ}7vP{*<@w++sbAJbd^SPrmw+lW(4}=oTD5d&+ouhE^q)Oo?klz3j`))l~2v zk5-H9pKZd_2&j=7AzhbjY6ziHb!50)vls>r9zWq{|M-vmj%Bn(xUyWbx3$If?QL%CUE`Ba zw>UpOr9WFyigo=+z1Y|<6V}_uRdThUy-~fj#C5B!VXnp@RWB)0Q_fW(IzAXdTHEzY z@)DU)e1&u$^R}^V-N>pG*1?D&$wWyS$>x6uG+S)o3y!$=NKgRt6Xy;oc7vkCs7+%(p-k5=$T>4M zia_RgO+%eRGC3EbiH?b^s*9AQ?`mEQT6)deORZUjZjtF&lJ+e755V6*`nlC^{jYv( z>;V7j`1c-vb$kbpKUEvRSM1kc-XZ_S*Kd8FECeLhX~zsn6{#JmS8p?$k%d+l?bnng zr6iIip3oV0C9D6E)MMKiO?GFSvV8jr)Pf1!7}2qb znVFEw6tN9P#KEi>^KNzEu`ye~G)-0lP{!(6(r}fBGEE!V`Y;02mLbs+6933(+MZQV zsKQjC*4pIswW`U;0V-ZT;NUpG3ikf3hX0Rb_6BwwYJ8XPLi&zEM*5!IFG!0e zyW86=ws+_kOL8YB+rPYIb$&q^28;Z%1v6c@BzK8nm>9-6OO@387HTO}tt`6C&i)lx z^rX}^IjI3pVO*^^eEfvVVdTFr6Hg!9XIc+De|gB+@i8aQUU2l~*Ib+)vtC_VTRbA8 zV?fwI8X)HGuO6tUnn;~ALI#qXWI9OjY-`FkStWPSFSv6179W4~SKPmK15u^a0-DSV zp%m+DT`RY)Ug6%oH#t2zq1)P~Tb?nDqp2j+`~cKjQr0ptm5EYeI(3QiRHx_%x2_rmw32EEokBJ6uWA|IloH~dIqEdQdf@Ek zVFN9f=NDYA&w2Nqces7+D*dwOUmkwSA3pgN7bgc?oSji7SK4GDbv--#``ozyfRBIt zW8S~_23NP1XieO|^%`Hj^A7*?i(fKnB6U57PrkIy6glG}6mpl*&NIfkvEVsL66GdOzx>t)oR+WES7xy;7zXVEjc?m;o{(sbg`u5 z3QUavHPCG3aXDq1ADB|gB<$*>jH20mIc&b$d>}H^ZJZ{mn$o6$b&M<{nYt*+EVEZ% zwM!CG5k$(I@z)t6Rv())DKM*YRBeAX?m*`@e6g6SljW}5K$6v{yB9%K8+SN3PF|bt ze#AsAT5cd!5U+O^k3lNpL*Cr>Q_QVuUn|y0!8*#=j7rHm@g${5{RNZ#r(~(?B0+Im zoj+nGe^I+%{XJ8t2$=l@el`Ntek-jQfshvQd$vs-LWO5ymp^&FSx*Uzh;Jb5d#_9S;kG(qnjE+B57l2nJ zz+c|6$s)E;)PI)%M)v@yYHa{_eBG^X_y>@ZsoAQKJL}DrL(PVkj7k>QVSDX=CrL$A zq^L?KiJ;&`L?UPmke6}?l5Nwg9()Ex@AciYE+O`9ZJUs`rQJ7D*<9(hUA-VPDS$nu zT9}4aliNzgdO+8Z(pf!U^o1_PNQPR(9iy$bFC_k9>{lIh*J1`&0g6p3Z60lQb}rek zb8fM?LtkXYD|36k;x&hLgA|B%gwbDF(MBkk0>L9LolOPRH)WIm`(tWAsW$1ieGa-& z`cO4KiU8#fTKt|yxk7;b$S!&{#as%pQ4%r({K#r5>qwrS-ZO&ly`VXSXutMCuc0 zM%_g^XWxq42P1c>eP&XXuJ4c}bbZgxVnIhTFj@+I^2}XM=Af;x)AfAty$3u$ddd0G z3;MoiRo#40)%u&)VzuW~#%iQUmdrGSOx;bu#tEx!wt8~I)M_0JRADNF(qGsp0f_6? zpu}Q4MY({j549;HFd&Px`DklMW2>Ba!;(>HQ>yQySz=B(P?wF(*X8!9u?t4{#aI*v zIvUHFf78yqg@fuTJ(G{e^BVsUMjZ*SsrFj#8l?tKE2NmWp$~RxvAf%=XTUWa$i-{n zorpB)I(|*Ygp^Utmo5oXv*R%XN|RP{DMlRh9jnt*o(==6i%X_)%@+?Ja{bnI7F$cc z`uq{cUp=9$SCrA@|4D^zvBm!WK6^KA^1bi9&-d@$!%b)z1?Y$+x z{byLOFGy4_PtWOkBNl75@&?Ib!=bht-UtxSp|^WR^$s$swr6R9$v*Tct++fbtj9Ie zG%${94xT^bvxir?aqBkw`};in^fL~hJm&J~h+(xtMM;v$IkB~~WVyY=)hjo+vRK;k zrI?}NWP3->nPp1c*uBE`&bF!N77J>vOoQ*A2qHaY7zt`muosi85Sc1v=;w4ne)7pB~_}GPe{1-dz-&lU}P?VDN;$6M+l2S4<2G)l)1LPk=HiXBFk?; zy!xIUE&J@VsUmI8fzoMWGAM4DcHcfKxK9ag`e;fAHnyTri6s=7><^odK*SzCmnC^= zkBEWs$>vzCP6DWUD?X#alZeaob$&mst&Tqz^^ybk2oOtZq=bWYE0?Tl>uY4!s}l{1 z0sQ2v8`)bEY9c3TE%nUf!O6sG>tm_72S9BLPrIj)vDbNSC^R*h|1hs{ZSjgl&5|v& z^-pI8sI^rH6HIWX(BE`}r1a@&f{ThI$x<{Y(Z1H&E7Di@0Vq;3iLP6a)@$>31o%1M z$>Wc4oBo^6dUbp!k3SUw@Cy9DIyT3^Oa@#7osh*A9R)h|#2{$OzVFP$J^)Fi6Knm~ zVf$)lg=3OMRE!CT&5YPRq}78Fi@DM-duy}QHUnBcxjlD-^^Y&&v07yN6Vz&w#Hh8? zv>7l5NH(UuYNcvH)Ut|GQ8RpsOg=^gC|FCs!d%bpAWxN+!3_C-34Z`jg%{7vl^XA9 z8MW{aH?p8ooQV(O0QL7%p|$hV8TiJ=ThRupEn%lE5DIV)Y4!O5UKY5I!%p)LO>iSCE)Dzh=)&~^7`%`%SFa|yL-In()%uVXkByf z#!cRP_j^2f^ac4~$=233XP1|hsi2dA5UrJ3Cv++vs25jyLMg@0NlhkWbJ653wJ6kz zP&`8qAs4M05we;Oh6kSNnW)XIZ_H^4`HIiAS!EPUWyt5FV1_?R`b&Ecnk?GXKN5j& zcy9!2P(h`FhE^)pzBq!4h=7;|e6$7GbA57cCld^!%;0`w`H%UMB3R!zRL$Ja`A_?; zp*!4!%f@IU9^4=?B6O_d37U<(p^#FKL0G$vlrqElIkim4YRyp@nN}C%uIJgqjEGP! z*Q_rtnZ~gJOzAQyCl=dF?!569-@pHWt6NL5Sgm_Psgl^v%AG5_?EdIu7K@Jmc65MT zoWS|YGQ&BWfm_B^O^`hMZ9~bju8Ml`w5{plL`uq?jf0{{=cO;BmD$wsjMHIcxHxCA zwN1CZ!;}1b@?yz&envSxWp#dus`(K}56HsSq~#XZZ(e7s>uqlUvJ+WGa4Dz5$irvP zdGX|%HfK^YrGsFl7b1zgC?u3|9HADH!ZeNME*~HEG}^U_>DEMIY`T;`d)tTbK#*!( z2ORv9ZER|eW&|=5S>S#b$!qbw#h?>lwzQ}D-m1?#ANAs-L5&eB*%fV0C`n|WrJZ-Q zYi%W3j$*~^~6a=FAKpx`{451@+v~^I>6L- zbNXLfvPSUo4|^36_W?*sHz|uQrM_0_q}HsNUPf}Nq^^*b+oW!VJbi%h&|j{trr((( zZdaW1=J&6T@9^ekezWPiE3kz(;Vz3Np!g<<-8%i^I)f&rA(W&L#y3L ze&oe(XvH4ymKIPW$>fX48dB8G2CNYe$rOfIa3iU+zU5n6EcUOlync-v4<7K=+Yfl- zjl0~wew~~9du(+bSt|EmyUDYcFZe@M>R33R3Y}OP$yC;?FV0zCob&SJlOM-spFC$crt;air@ku3w#AFs@b(E_|$(!Z?nUVdT-5k9qIz zJ>FXE1Cx!h1j{Z_NlaQORoLI^dFzeWxO($8FFt!j^_pvnwdvDoqD+%BQTDG)6G8VF zIZ#`>OVMhs|J5Yt0@N{TO{>?h(tx;Z5GG(U_DW%1fg->y?Pmin5HPvbLfdL$Dhem+ zth6=in*BXBA~U-uv;4(Nn?eSSPvQo`1JFmjEHlHf5$_qnU`R!hHct>u;Ugd$=hLtO zvt~#d5z&xNoU_hyYDXGIsEUBMhRYgYFvB=p0z+pV;ZQ zxp((2JJ+sp`SdA^ogKzu4Wi`5(mvOzm}FW_`C^_hYSfMRy^dI0lkE>R_9eUbrH;Ps z2|7XYc7((EIjLXRzLtQ=Ob|^ioPh)lUj!SvJ@UZf66a^ z`&-s0r_^aOGP=v=*sIFc{*J99)yH+27}iFnNHSBu>Km2qX$2Ox;kR*Eu{kF0lQB-V zx2D(`3gN&X`;AttWopbM2kYXyjyjuU%@CXd4#2;$2chn;?_)jr9x*H2eA-r=q=B5h zw5C=jF`_?jJE+l={aLD?c=V#(1G z&=mVdK)YJaW8W;$3v>t_)?>)xa+NHqUN%-qDM|9IXUP2UjW_oT>$B_|Fai2wckv+J z{#fTYIRa;qR#(n*+pjdK z{p|K{Z2>JeG8_Lzt$zhtt3hbe`uH6iuM?SdOK1kbkFTEX1XK+;YCI*1e9!9xl)}NNgY+qv`$h-O=9;yVeb7RP^?xxwo!czIXQ?J2{g#I|688uS@*!y$^Z*@|bBoFb*SSbqTdnigIy!!utG# z=)9Elp*NiB0JY0fxn zr2%Q3CLi`Pw^Jf}AeqRE1&jS%`t4noJG(6QcgeX!wJ@BWlTycJmnh?CAY7GUH6VG# zbau|s!664nC%n18k4VD0z9s79?E@PihZ61iQUs6&F6wBV3Z$0iSwLhvwOY160C5$Q4| zC34?0*?=`^z9e!s1yk28jmT2v*1gxcfA@8ki)^IrROusIt=M|4=80QtuHC773T*>Ov44k`30-<3-1P*QJvaeU}mN^)-#wg#~4KG zUtj#b_}CP){YRs1o6ew-w#G;4kr8nI21b^N-P29_O&lQ_8J_1kve7+*YE!Ft@G?~+ zDh$LYQ#80nK6a5LLcx7N+|MF;R=eP;A#sw=;{XjXiu(JBB_&+(B3S8@7I#XnvDTVG zAy*^kqa&Uuq-3RhNv(__DXv^G;4P~5nTmDQ5EE@7QpwenT;W-%L`+j#Ih%y^FI!+n zHD!c?6I&jWbP;2CEK*D<5@deX+4ms8|F_C7+x^{$#r%BQswsg}#ebCfC&A1#y$jUF zO6zN>HhwgT%v`Cs&!I>sSvskjQd}ogD z+WEdZ{$Ct_Dh0r+yUHClqC8A+8~Gqq~XmMRrNG?K76 z2^~U8)ReO1V61I3G(Z=%g(1fl?{$;9o+NpGtet4A(Z1so8;EX*T7}KMr}dcKjAj8+ z5DGNL!%+3axLz}rVwpzuEPjzz3Q!%a2iVvI_15+;{>E$Rs#vB|g~=s*R>!YRDPa6Z zrPdUQ2|SMV&2$FEmhq2lp0w}%!o1wT?vG=DCf$#F5DJ3`<^!b9*?nEU={jV&jdnef6MgDEScb044C|3Pto^+$xQIFEF`8H&s`s)Y{575zD?pCG|bh znZHI&O4lvuwtBX&TxIXpO}4LHXY0y7ckbTh#`UXArSR$R|G?4LPvIbQet2l|=xS14 zYT@GKjFW?7zIl1T5ANQvAT@VnU_z}9IVtO^yf{1M7r*>9PrrIhxwz!=^c*RcSuSHi z)QB~yl{!@e6`r9~HA%O+CqZ$Luhb2*uj2O_Un2rY+k~pMdM45Tmy!cv=5o|nZ{jt- zWff&>)~ube86<83Dh{gK3&p&QbEr0x>PGggx$*~j5kYk5?KM0GJPW5jpLAXkO{wGS zKwOM12aS}F66Foj=6wX--#SPCHk1tkwu0CQw|`IIwevN^;`7$KPK0{L5Sqj0N!pH6 z6jB~RGP+U&zg;0snYo9cuk1O|^&MmJ4jx^HXk~r5MpIAmbyI9BVk*^p$6JfQp$?o} zp7Z(VpR+zWG4)Cnd##k%zj1|bXB){2v{a_mB~m7a)g`OT3oBD8g`^!yY2`7XzIIiU z?Yjw`mg=?jW~NzV-zpCH-TT6n6GlAN3S(W7b7HZ*#o;$k`SkNg?7jVfMHZ?ihSA8g zqRJP~U-0DdV=j-6S+CY@JQtL$-EFq__Sw7pIv@S*-*DsF6^8Z1`N(5_>lGS z5oa%-S+|pEWL&Mt+Sw?tg}hu)w355dymZFF%9=`rI-%o8Mk&K!Bu*(vF36OuPCd<_ zUMki?(n&ZYeUi(|A;f_;v~8CNWkpOS!N-gQc=nkn;d3*q48+GjRz%bS9jcKn*0nBy zI0>VTW@z&^+Wnuq8@QtBs{7Y?S zki>r7)=iHaVuz1RjJir96iFKUm%WG)ER6;wcb$36_*^pM!4Qv@Mhs=!0ZlAweVMaB zCl-@-npBd~p*3rw%M)o!kqiFS@m&Pdn>);_Q*t6Zi|3^XWjOn%_<+>oZAFsm|ZdgRdfVGWW2RWOd?_P1YHi z%#D1Pk6N!603ku%zSLm7V@vkHv<1gH%f=!&^o>i~%SGnOjnbxpaTvVqpG$;GCE6*Y z5%ke&@eSyE*1jf+T86Y`@vCJHi~n2{mp)rRu2Avg%}R>%u8&*s;Nnun;gH%jRiBqqun=+d(7+>AD#gs+3sif3}De()fxQT zjh~eWh-`Eg@Zh*T&#OnW%Z1fQqMBR*5F~)&=1{x&Fo* zy#4+My!-A0?%%k@-d2YKw{G6#@Bi-a8K;SHSTn8GjKhFd7}g^fXXos#E;%|oVL;i> z3&t{0B++#p7psYv=a>BM>nA*X^oU2l{)E-@7hD`2GYz9<|EIyml?plygiF6={sY8U z17X#INR7Jv0KO#_1Pf3#oc4V#36R1&LW|>6TNs)+Rb!=zk^!4zZdh*%q6YZa*&{15 zVr?aw*@T9xTc{S-vjO~N;|Vce+c%A-GhiKowHkOKMO}ZZ^Yz3hkH6;W zqc5rFmyE*-Nr|pove;g-+`Y>7tsA^{|1Ct6^P>|^pTA&rd_sS5&ieA)Kz1qUWcS?G zx$5`J4Nf<1nW@d^a0*(W5UoefEsAmxq+mjX#~x&M6^_C3o(>&3kXX!|khk)X`equBO75Z@ELT@`-~`*5>kDevneH{RGNXX4Q?|&EjHIu3;+qTL7Oj6l6kgPwd}q) z*Ogo`P!YO~fn?P+9u2j~&DR1?N+gs{?8UX%+?!COvl0lc4*aXNfGh%(N==DUtyH3@ z+GAxj1&eAUu%sp@SYq9pV~!}zup8@y53Zzang2BZU0YzpVZ63@AmyHva+^P3_iWJO z9G5L1Vx)@Kibj>EWEDE79hw$UyDYgYI!WnCQzDfCxiONa*?#G}2&Nln^#AvXygL5l zj#niBua5uhV`DXLW8qt4Vh6+y;jbPb~q%L)< zlxf8{3`8oedeG8(-McihL_M9?O~zwWbPNdK@9o=KDS#@qrbYzV)y%cIQ*lr)xb)83 z#D$dK%OzAJpt3Am@u*X4YNR{vRS+c!_R0To*#K@3=OjWHU4_K1M$d8=JxXAT*sOEF z9m|ebb8!2FQbZ}9>uBdMM79V2G_6Ow2gH7!Eu*gn!E%3}et(bs*Y2>`-J@G>A&Vu8ttAQN<>Rj@FJ3T=lRHc&%Y5aGs&I6C#`<-y zDaU;dR9jDPH?QZtH(uwf=Px*Yc|f;VlDdqp2Bv9Xb#V^Mj!%F2D_%T*MoO8>lXFoC|S~J8n`?^;qdSU z&reV2_x6~oGFD|u!lUOe_~%c4$2X52bMgEshmW6d`tl{~^K)t)?WQRx)_zmH_S(7+ zRLc-n&lsxu^;@9Xr1o_Vt^))`-HZCV5vG?juy%4W=0Tln;=SP)(I~vKaj%_VwE5Ja zdQ%Xf*2+zqMzztGc6es}Tfkp7e*V@u#tS>3Z(ntTpo_&UR_pdAL>*Jp3Pc9e?^U=J zM4;ZfBUC3&XU4$D0&%s$hN40Io>)fL$VD@V6jX}=9CJ>ydy*1bC(Oi6+{wd@$eg4y zN41U`>rB_X?s-JJ1yT#86tX0ids`eo`jVgj-GAfk^v8Vs!3Vs)zfDdZT@p$u45jeJ z^XL5P*Pn3k^%I86OS@+o7TZg%-n_}yjT=1p=tI8$z4zGN>N#Jn`Skan^W`5NvOYiM z_~}z}K4ZANU??G@b|qRUpK3*-rHjkQL!s3Qo+?CZy;|o?rcU-)(nK9cR_ABrMaOW| z^M~L3ii5)gZr{4i?c2B5+1cR_pFiZQPe0}2*>f&VPMD@>k!fpYRbl7KJ~v*w#oltu z-X|q?`<^ScaP6(PsipGr>!+-b&*>H;T9bEJsH8s8Z||_Rzh@*(8R<|iPfl!4NChxe z1W_NDt?Z$xS}-L6T5UgQ^U%E{eCUNWIls6vwL)5*O@M9CUmF4X^4kfanWt}&H?y??X>#ECOW zMigZKy{Vl1xlT6PxhRvf7HKkX0J}{=tUxDDbS6tCWFOPHdWnLs2N55T#1tFhVNjsv zO$8xd%3$6Xww4wnN>Z$co9mhpR<@3ADubfXqRw~MW0#f&YC&7veOpje1j#-9V$tS| z>in7_8*9Jfm0F<`K%|h+k|1>=HHqX-QclwuM_~U zjz8t`t+CJmzaq%Xp#msGd%lqHTNqNR5e%--w%F`B}*R z9kA;xr8mstY`r*fVCjbj((UHYK$(gg@OgVdlB*(Sz#Sz5Hd-W<%ub4c?Y!c2x-?Qi zL@cwDAbQS)SyrXC&%_7=4-zasw7|l94qK(R0as08=PMiM)mda!RLQxs7GOz`t~VgC zv&;US*XXWa<<^6DxO?wSu3o>v^=nty-`-|Djr^ZK`%g#!w_`~4zZLhi7QvGK(hQzEyVy>Ro0g)luCcG;{2PZHln=_WOcD( zSgq0GZvRCoqqURLQmK|oC4j4V0BkP*rGbY?E=RUFVd@A(y#IQKq@Kn04tZ;r{WtFN z;ZHv1qYvKa#`Y4am9bW)1ic9RTig8L-M9Jj;X_V$_gJ5wbGcf1KXheUuUQ`*^X2dV zz|U{oKtKEeDJPyEpYrs@0bhUpn8&|=$csl`F`OJRoL?{vYhW_4P$%j%nC!n4n7kGo zOd2gFEsh@6@wmyb=Q)bfvZ%&cNdxr_NHoGE2(NiLa9S*eIN|Oel5!1z9VUMB;uIW4 za9vIY#H;(~7M=%n<8RyQ8`4>F`2U_K}f&)eD-zl?_h%-ea?xh^<@b(Kbv&U`}< z80wjQC+wUEz)e`&`>3|@)s$AA;V*)>b9Kd!`us;wGd%G5ZKG1N`HPflT^=L}=3QdF z>a|w17ztM=Gq_AS!!%f3ci%G(ms}jeuo}oI@mVg6>vMka{U7kg&8sYn0lnwvXZ+@~ z-*f!r39I81#?`v5F}drxa{Crmv|+Fo ziC;WoxwFk;XP481LoQytWOa7RaOpkUU3#6m%wlVcZfA?Voh#(NvvbM9x)geWK4%t- zEz)8^S}e?PabcYZsLIZ@ebV+Gi!0a3{Q}j34r}samtlFz`t%g7BehJFL5!3w=KHHt zA^DzNu%>@#L8P?1Vr3#RE}Ya)zJF-UVJ8iI1Zo5C)F*oF>AK*uU>TpxV@g0W2q7M*(bYrhF*L=1pJNq`!F69%ohMxGq?>> zBPz1cR1IcK=-m`z&x{Oy^3OWOy`AT0syIP|n;+sn8+Ptf6}oJR18sAL&my~Uv!eY4`uNjM`sHK@S zS=}2`s%R3CE+JhK>3#d^K)Y1v$3&`1U$iZ04D$;6=K!2vVY)wq<5d@cSI2+WvH6+* ztIs}xat&%>hTa~pEqvwG>=@n__?l7@Nwr5cYnC9;MU5WE#cerZ%r(hv-PGR^U)aTE zdr7<{nPr-4JM9gkAWjS%q&gGqrd<&V)3VvHnL)Dv6mNs3v}jwEGOU>`_JG5o})wGNTOKKPk`p+&~RHU^Q zv>M>3=W{oEjSq3&T;s9YT&n~0Z-SU;pCs`BDt0ZQxWKbsq^Rk)JygS0KTtwvpx=Oj z2MJ>30v7b+*`4G>#>Q(%LX)-V(=3p)Jx_$x_ka-|sq^PgCTFZtOy=J8^xJ!EU%L)h zu5#=B5BTe!{Dik&yUkLBP7*2GwZ8rKJDfg0WW2a!8Yfb&ATX`h3}r^QUzv^tRS_L{kK<3RuHJWvL)Nt?`VyzA}W_Ita$`-2bouRs1FOB6{J$sJws zY*S81ExfkB#~W|l<>=`%R?8zUt*DhcRi@$6vb`zu>tFm6hewB`lsS5N#L2-StHWbX zU%uq>=!j_?sOuHeux47XkusVg+*qt8+JV2gXM&B*;;sHbYY+i505xu<=}`PXoe6;; z2PC>6h-bg8jG_T^RX47z%=IxbKOzeitB+;vwCTNN{u=YBeN!88AYNJ%=Qn5ZH^_q8 zqIu#H+o2nei*B4>T;qHy;WHrZFYIsTP&{r-T%lic$p6*Gp_SGs0c$o-#g@+~P1)FB z6r#nVUBi4Wwxm>do==8?azcEKY^~e8rn#2E=6w>hs}v~)5P+$e+G89Gk_D|3r-#Qp zd-8<4ufM??_wKT_)$_YYU-0l(pK$*41!c9Sss~``o|xCU0H4hSb71 zRTf=h+4XF9cer=^I=AoK;=liI{};!fe_=|m)I8zs>tt;=n{Pr5Qb%VZrj~guiOta( zn}AqSy?BkiU?zKI9I4~L;%JL*xkVKtW>Zmyi*u&+;F*74g}X%VGP&=`i*0sxwtT$y z1_sB85oMSvPo6(ROTm^PGj!<|OAw*oyTbCdyWD^OeQw^k#<;rV^zfL|gF}Y%Q%;^e zV>~}+b#}t);=;7=(*#pSQZX`*V*7Gcq-3hh*CtNvg$Pi?$kRt?4Yf+tj%&3w2BP%QKxWf-KRoM?Bs^*d1~7Z{qQZGDO~4I9N8!_6!d{liYH z5dyBx4)C_N9=KaERK4>+Z53Edu&gKrQ>C`w#U=qovY=Whn&SMmt=Bj?ymLwH!COFp z`!JbeADv|6KM`OUNYS1`WoAjZG>@wNou?f6}e zH<8Xd7p#DA3UX`9BztEWDGBXE$Tn<#N=k1=M^TZUPOT{DOps2DWQdxGH=GTRQb|r< z)#BDYWOyS?=QQfRSc@g-*$VUsmLM% zO$?DPW|VK-&K{OsJU;GE&y>&pZ-Z`KQ9{BZL;?eyF{QCHq)yWxov!V zj{4Uu)Yfwfp+6B$w0N)r@qQKWJ1u_QJcdm;0To0$T94#la%d82|30bR3&bcAZL$L3 z8M0^NI!T`CDqwk}?-HMW?<2nY@(V6sy`b-BjO&Xi&oow7mx#cN^@`_TJf`bAa$JM5 z-mqD%7?w-MVS|kWd9$HxHW2yTI&GAxy!%1rS(l z638oV1Kfd}0`2;rSxx2J1fn!W3Y#>okf?p9y}ugF=H41@O|>Xqd>vv_zP`35^MIyQ zqs7)ygQXKehSXr)D&EkJT}v7!?oxmU2>Z?Y|yT!jBej9UyZCT zuDEr1MY+1<`Ilevi{nFP^EnqUUbB4piq+Y9wA(Y1dXO*l%3sO_V)JaXFco9z&r`F zS35M`tyu&}(A8zss$69`XJk{vrSV_kYN{N4LmkoSa>9dUeUS zFJAD?S6^}d{5i|lCtSRI!SdqVTZJN+j%eyU!nJ~p1xp2`K<8`R+X{McYPn#NK|*XN zbZKgNi3YWwqAi18Tfl;6XW$cAyM}Qw1K+M*0)xlBU7oCk#TLF${E#vInWx|#O zEuIkJ001BWNklB5Rpm&7v2n zpnieQDGyrW_l|;fUXoDPn1S!7I2cehI~=Hz0G-??iB6GQ0Dy%sZul<4=tuEQ&O02` z`5U&ziD`w}{sRXLc&IZ){rW?97L=f#reczHpwfs+_&24QF?Oj|TiOJ~gfE2YP zDjnHU!Fn+70ql5x8aLhw@Ys-NlU3uNKB@mD$J;pWU*UM$1>o)YU5@JUy*ZksjQJiV zRr9KSunWM|XQ-&s)p9riF;P=2A*DxLs|ZUfh>9TQ((R1`=}l>3Qw+MAs*<`HtunO* z@ZnejP{nuRY@1+J94n~k)ttL)>l@(o^TRn-YpA+W$iq62@1XM+V~oJw^}_sfxpa#_TPIkf8MA$ME--M)h+Lq3Qut7JxsOr34@#O-DcoM}c4i zAT1ELS{e|yuhMXD2Kzn*s>XnWE8%$5nbDm1_?Z$xePam(5K)8EO8HNbov#-WF`wgNV}sQ-}0Dq#6Bu2kAPx`3|$bZ(v6$Bg?BxY`ylWp(#KMVQ+t* z`+K)o^fT5Wyw!L9yE}pV2S+S!9g!A0NSaYLp8c?_PIEs$<@Dq=Up#-o!@WHivpaZZ zj0V@k$mMdySKmJ2XFv14+?(rb@;F2?KQ~5835Tg<&mK;hWEi89go--hc+$Ikv<1h6iSDHiSd43-z?tgf#xQ@Y+cM0xOFC~r38$W+1z;~1I$p#@2nBUq?4 z!xrTYOaVQuyG79c1!_BsT4qr_xN18}hyqq8IM}{nU+TJzRphCHEzz z-gvUv7o)BhyYYO}CXj89(`q~)$idcY^2Sl?G3(cFS@a1Ip++y$d$#>tsi!?1#4~mi zuyEr-Mt~KUKePfIw5z2Kl70P_slH(Ax<+<70;r&TIUpIxjAv@Al0GgrXBu-@KvHDB z1v76Ih$v;9(Y_~@LKe6@Ibn5u#cXH6$v26v>#-qIHXDZZ22-J%&(OX@=R54)J?6s? z-sNyHr<9D$Am!viR8FMi^X>BLlJ)hH)X(VVBP7MxpXbm;G8*$Hi2efSx8A47)Y8NFN}HHgyDQZ?dz%Nl6L@m_^u?CM>+^6Vp9DAh& zu)d{OB=P>Zx79UJgUV)5byk40M1;`_32nYcbml|_l2~BG?wNV{fG0po@dImdr^~8f zaaY$@V5#C_#i|NLqJ}<_18x6w@HHo697nQ+MqcOwSQt-h7jVng)Ft2i2{+K&d`a8- zfXOuP{mxAVGn%{wsJ|ZB|8NMU-Qy^jmmO~bfVbm!HGW&*U-zvV_`8Ys#FWkm2C|W)(5WI)=#pZh>h0bk zQKSQA2Avg@jzm%gqlgnv1BG`|Ud?!^ZwngPOif<%c_Tozx}DT)mQ2oa4NjSmimHe` zA^73zZlM`wh9n84+PYB}#$oO4*23|xU7jRZ0a%m*Y;kRi`4?2cpybK#wPIVreElx* zL}!j5tI+E4n}A>h$i?EbWda|pXbX%>&1y8>p9j@dVLzl0f>v37X$1npC8|hEI7A+- zR|-A>7}UT({5=)5sQ^R0L#=&ZYRmzr@k`4t}R} zUAlgU+5R3oM@MKkXSUd3_h_G;yQ1b9uq~`jYkKwFk9vbF06S%h)LX7Bja7f?8deG3H_>=6FD6p}wts=b6$p zqo4I{4q635NeOF*yd56cz8bHSC}ii@Y~T-|TWQ?TTjeyey^%_li9H8Ue|xh)=S%CE7sS#hTr%;tu}7rMNj9}&Ts3$w)Nind;k;e0L?+K z>plV~(GW!i0*q`wtK_JWrxr3(i@`99HezuNgP9?!9^9$6;8?<5xXraDJgUu32+;YQ z&|r`y&+KRO7JkF^3QZkJUBO&3eV&(Tc0nQaKHoR%_|@Xyoh6pA ztH~QBKqrZ!@9cXH6~4wr*%Dp?5z|j4>}j>Ns&tYlvw?9~v0h!0%g8uvNC9-NHfvs9 zT=VSN6UNIWoAr`1jt<0`K)*wOc!%SA4|(tKklQ;ul$=QjDY@X={^1^X_I9~*bjW|} zmCuKP&1S=}T9HlMCP;Q$UNYMG`m%8(DU{8C*$AB?=3s#fuV&W;30tV0J0Lk{P<5mF=Q)6e2!j2ccyWeGUuS9N}T%4a36d5bHFUJsK`5h1Gv3b}2; zE9)r34SQ4f>zajkfm3bxp_D2J;OEs=s{u(#0St@MX#2$+81QvwA-EZ(5YaM_;^&#o zb2rWav`H@}$_7h;l-yuw*v~Sqy=>r7ZX6J(;Edd4UD*~p$^2SL z?0uj}>fI)U5NoxWVsV|qBSK7yFB6sG+KNE0XqS`Cq-4d(cRkv5T{r5c`b!_d@{4Vw z_nij;{x$rDf79ciO9T*pdqDVh{OcXR%~ieO0&@suD$BzR>Aa=4kJLWZZT(FmB!$i_ zb!dc-BHqEtaa%DliiTWL008bZLhaw4qV~&aU^NJ}*e{&g=vkurbLvmn-iRmqp2f=z zBB(okjA9loaSSb~O@&%i54b~b?3dQS`F-7^<8iy92s5c7#3 zID!O=^JxHp*$r&~Go`h;v*;)go3NJ&5UufQun{E(Tict7);K8w+z95aW|ZskqAZ{~ z>owr7X;*0nq=5jfrXyyP3TPL>e;4=MSswmfk%_=CaawOm$wj}iQ@s0bhVIPhc6Ql4 zI%Mz8J<{$0`*)7my>-mpyLWha|A;#W2aMVHzyH&JWOZ>xx7xVSoCxE%X54HTuC96f zoV9uu52EeVdc*SUgePBp&R_rRh!5U*hnFX( zJbUq+Z=XD4eSXEbUU6~yn$_h6!=?W_4}J{GnVhSdbIj?=p{!|}P|Wc9Xm@;ET+5yF zlsq$OBBZWow!1^W*k!)hrC%&ONazy7as_?of_tkaHNTPsYI077%(z-%%PY=KFIa5` zc4i%8=qM~YuihzExZY%5p1@EX4x?b9RIk{2ExNY}gc?(zW|t$Xu1%I>=p+}0!$6M#4$*?O%a1Kaifo&}3cdRTP-+|6@s zn8lWz+{QVkD3Uh!rq5gZp6a-_%_B0eZU$sxP1I{uL4hnFC2V&5j-WrQPV6R)-{jXQ z&N16WD-Jt>lt~@|@p^M9Sm)U3`k{vIOW1ipqfCSMBM1}!b@wsBTEUb2*m9hHfaGB2->)!$pPoaajP`` zs8W=gDUcSzZmnfSLqEgo=3|XTn!d^pD>tc>HJJ8pG=*dVdf#AfR0^dZ+e^HRT+0r^ zNid<6!qmN2!w<1o*G0BO0ENcjs{o1rt!0JQ`~wA#?c>D#GG|J(X$5a17@KBv;mHA7 z$YdLuZS?C|1AGTMr*~9a=a@p+hPcv%ZbRz&I5G8$6TkpblBLvgD98}DM=)Gd%#SWM$-BS88_bTs-5)P@pk+RkGBkfx8rv;{z<^cK;#UweZ&^tE=A;~ zQM8Ptna84qV#(Ay;s_!tortN5sY}bac&k-+QffjtoIVp=GFO@(-OYOXe(u3x-Hd7$ z$)=-O^^~`O=xvI>Y;C?qZ2VJ7uBq2*>@77*n8(3`bNsn!XK+U=*T5}%ouCIHPT?mI z`dkD2Y%RbqqOHE)y8-yFoQ*9Jzo7J470YvHa2p`V4T;xAkMs>bTE7)(B?E0!-D(Sm zRbfR5A3|aSukVio*2hVv_pz9+uLXF@R+i@;NZP?dH>T-xpVIUw~vpwy}!>QCHjQ-qZZ-OhaYnC&9~&` z(#09afnqSOmu${2`1*^_IlQ&U#}DqYGoSm-$peTn?-KV8571c`S!Tg30|kb{>gs}= zN7kDSe|_~|`2Q9=lv3!;*eusvon5fGUNWv%tgf$}-kx&=PbIP&?pV2#Qvn-8#@Z_! z%!&t-ROgkcETZ$ahiNurvA0jRSg?C|%+BEfI|qC0-nzxX(J`-{KI7N_^KT+RFNpZx zkt#gpGiq2ZxjZ@Hn=ilM@(;hyV&0*BB9F%PI8v*xQ^vZctSNO{C~8))ux8)A z-+9n)OP*r&nkm|{TP3_?34oxvku}J-nx&eo;l#{{V^-fgu3rnhL%45>q3hhK&aiCR zExCay)b~%cS#Cbq#u;kqPV=0nKNH9>9bDdg5GaIHUw4Z}@S9+PzuzJ&H$fv#A@_5s zv?pO==(_FF_-u1Ai-HY;< zf@hjZ3E99XE{dn6W5_~chtzkJJhHmH=H;`eTz>!i%ymX5u1v22I!h#s^=8A1^K&jQ zE`5*bTnKG(YoFT>AMm3e{eU06`wj=YbCyHqY8ZKWe!(w(dCb?JeNKP6hoqNWo}R)= zplsYW1qklJsFJ!03|gBbRdKzwc^$W&4_bExmKc2vXc8Fww@G@U!Sr%yI@$aC?zyh`b4+C%fa2dd~o+R^Uj49mC)nKRcFJ4&E>dZ zwOW!l1F7rjcNPq*rT1`GL+3jj?%zT?rB@}dH(b3wAum^qs}s1c$@LUUDQ*kRz+4a&%hawnIs5_rEU8_ zExm9B{{|G532dxo6eb1hY9hgHlUZ@lzt|*ToQs!dv}+muLfFlEZK{oF0AAQ96Kmh= zhGz?qmAKB;F%;L_Aoe>^bw7}afh2K{wE~kC1ww&>s5m*ooC(m0Q)+radKK@CsD_qA z8rSG%5|Mbr@O`Jpzn0(eZ+5%|0N##&uJIdyfF1fSWi7n+$KlhdDJdI$pHY%_qC|Z^ zQp8k}CKDCZ)QX9yP}$7xRM$Fv8ba>&U%`}=yk^@ocG^x+YNok8-lFLSg4|9xzRS1b zcqTI4b;GWnyg@kXuDCpG))AluwckRi-K+_-8$z+{B2h&mfDx~Ov=UkYu9#nPrSwY+ z-X#M65)MJ#EKAiCzy$%_d2vyp3Ide6xwfo)ZAs+UuxN!W;tFgz@c!?BL{$A+1j1gy z0W)tQW%U|IX3jx^5cvs8zxUm(=j8f3h#)C7nyhK^pug|Y-o^XOCb6-u>-;*4XT1~d zut-YGyPj@uAKTyO(I5OFfApt+$b0wivNzwM(?qWx1h^u8fl)ZzKV-JMN9sD%a52Gb zY&I*dU!QRH{3Ty}`3(<_kLbG2TOHvF`SYaA=QFhH7{&n`Mks@qd?4h(VD!xVaD5%w zB}J{Uy1FLkky)1*R~yQ(Zo$8oh*)H^CM?B!*pE@d?lq%LOCa!naV#$sDyO}_X_9vH_p zo2w-+o_@>cUw_Tv4?krzSPvts&A_XZbAI|i|CX%ZFAC?yI|YPv3N!&<3B)HjzJWMBj+9Co^R z08o1sN{QgYzsI#ZfHJym&>C2H34o1Et!T_J)plIJKTa8Uz!4-1CG}{u6dc#e=IWaH zVuvTc_%(kyzz@Fv2YmGC5w{O^nW?iLM&QNS1)qQQ4a@Tj#$iBH$9!jpTgSKg@WXfc z{-gWc-(Mh-NJZI2xc~402i=UF*_>Z}_A7?Xz-B$Lwn7;O7ddmq0H60Uty}p-1e9cR zKqEHfdW)=;srX!|J?XtKL$Z;tugU8*>*X@;iFnC{ zCS*3_-G}#hxWDUrT&y__y__y7s={W-ytusL`Kwo~ua*=W+uo8oW$);aZvTk844-yC6#?|ERKn?!NL-Ww1d-hrZIU(2O{xx-iO++=YG`xnpE&H-COjkQw_;loU3d<(1%a8VJ`Y}VR5 zN&pVkTugL@03B3B+}ROxh$ER;htVmdB%~4@6LUewIl8|_W(7H$tk~9%c{|>Yf0^+X z0C+oo*W(Qj_qUH3i1m@I@0^t-7EHJVVkHS$+X5z)68l@1#M~uQsq#2g3Aed;Q9m~! zz`pr))SmP;=%fa~BK|!2H%riJwythWP5erxTHc_|gy3e2Mlxd8zbr=r%^3N>5i&YPqE)_U`{@@3PlY`<-_>2nDq&*uAgxTsIP9)u$? zW#}Q|hQ^$Tz`dgEM4;5N|8dQur5`CojzlB767+uLH){E7u&*ikZ&lB(Nar=RCW6l9 zl+@96Gfb78okfj{09bEa9bSMAWehvf|FeW{s&d*NR42F(={)PhuXUh#QFR!@1y7Zb@GUFx(3&4Yt zVZCB31A?2AUiTX}N03m0u1nG&c}IbgO9VARQRzCr zhuSe;?6P}!%cOLTY$KNAgEP0&=hVu~x7wd|Q zo)uxZUUOlu*p$Lw|JVOYO2(|8^XlZB7tddC_Tm*MUwzH1$KSBNx?;GxVzXI$wlR;4 zrC`Nr{8TZiQbN3}G?$s;*?&W@u@Z_s!_;E_TKj@$q+&5lLAk{$h}2O9$=c;>pun_# zB>+Mfk^>4+hg;)qYuX;uftZ5q>a5n$l-#UkU~gE`8kB91SmzEn*aTE;f9IRl_@8n^ z<&D?1e(%;f)WdECBok!8jpr-^B#S`4W%UEuwVK{=Lg^WK6eiGIM|u988bhB@(qu_dd$V^bB5IhlG4w1IKF$E z58r#lgZ+JaNo+QSS?B%Bq444HKKK9pPuV-z?hIAf`Wy`20k`e-*LYIJ!gBFdF3NJ16a)cK7hmkAsT_)0cM52OpNhOVDofU8JA)U?C`qXa* z9Ss>=^K<(ozDr~4!o3~;TE<%d;O+Qbk2eiQ#Z={%Ap@{uAp+-UdQnS|MbOZ6vC8DV>4-*@Br2hX8`*tTiq$@}hG@QFo~y{*ge}_^!cMDUuikL| zE{XclsQznNI}H!D2Cq3XnKjdYBSVHe4^tgKtv0t27nF`~I!^~*gFx47^QaQLk$kqxL}hR5sDXty3D#3l=bno#WH9{j5cmQnx% z9{eLZDfx>~YS~6D(@>}VXYovfx9{pHsxI7=deUNt+1@TYi+wcp%yt)E<5~)c(Oq6~ zeR1KGeOEk0QVM}P2M8!auRWs-sMV4{3H5D76728ID4jcCv(&N7u7uqwSkA02FF1eo zg2&Ik<-y0Fl2T$lX0Fz2o}ZobH$V9)*H2$ys}_gyL%zBK};Bjfm{qU@$6^6 zp0__=Au9+}gU$Zvmh_ZnIOuR!t1kGkGh_1jw0|A0PFx7}xmp(kua8?_2HJp7b&9DHI7?>|=nVih6 zKdp9Ns0oD(cW|WZ16? z4R}m71uy2;yhSeUTKMaA)39dHqqrz^TCDxZu)1{v$R3ms;2bG%ABg+2^&{)W3&B7) zd8wUB$=;jX=ZCK|azWMW$*p&07o%XanFk9R_F9!yz9f$$!#FUG1D|hJJpTOG+`0dN zciw-Oamal3*=L+Sd%@M|IjAt7CwBK2+`Dtk!-E56$?f56-uc&4$feL}&jIl8&K>p+ zZgKhiC8o*2=FmAopzG&!$^Y%yR^Nv#0@lX54k1m-b^ufZT)bVaDW!~P4`q}P6fCSS zygVRvuFadr+FfJxJwcuMrD80vF8S)kGd{X=o1=&lRg>?1#qokMXTCl?dODsAUfcz1|mihsQ`BAFzv)4?1UA?l8803mt*J&OWN|sPM3>aQd@ssr*!tSxo3By z4O~SHq|!}es5Al|ZHozhq)2r?;~PuyjS#0WQtMZPW?0c|DLAp>-;AbRFyhy#)V(ThLa72eRySZp zGzGKZrjmdAT%hsp5X9^1wEiM4h-K=5r*HZ-xc7j*=1(&ZPl00sF?nH3!07-Jy=pxbnPMV%XosT)^DMJ_HmNm0k-A?Vg0IMp1 zBLN7Q_srIUki2KP2uTytb?rX&2e)|V{dYN@&)AgAP>gOiBaI&5BvIaf^pIcNxx?l8 z8JDM3!Mvl`nsLl7w3Y--Bg19kY8+U-eAOtKc^p_T*W_XFfFx&1T$4Nwp2@coj$r5( zh1q&^J+7n)=b^A4thgwr_LEpDB1^e#1+m`bh&t+%@ z>TSd^x7xDT;B`AoMLlM`M_P%1wB!4EHPm72c)#)R#(QpfoBveMUtgC9(CcdvZ&%9w zo9?S@o%#&`!C+dnw7{XU2O^-C2w(ylpiy_Llh5{b3SriIkcsXPZOi<<)keErO)aB3 z5hfgs%vOT}x7}I^W8mOJ$}NkfBp*)VO*{lmm9`$z*Jf6?Qn2>z&j5gaIiBc7Z)l_$%AhU za&f>fXLxyb%4W6kY;@>kXqOP{5Hb3lSy1h~j3N&kl4bH{!?@YBy+wRsV`|<)uVkz^ z^U0tIai-KYkWOd4zgF96mNDwkh1ANo{MzTun!K5_eEE{U`yW4MxmxjqNAL0B-P_#K zLxB2mIa-eveNc+~H_3X9$}xpUwE> z;T=AFc+7k6KHxuh%2(G{%-1VcBG@=0eQ?rL7>h9j$exXs?6h=E9ZIHb#&*wJR}o4J zP(?xV7}L^Pa9tUBv0vHf&i z)HUY7K*1O`8!y|kjMkQbxK2i^*r}kwr1s?gMHrMx3!oaAHw@ku;9xNq4MlVY+D*2r zUSle&DZV!tP!fP_D(HxaNT~`&sT7ikYL=4J(5^TEaLDbXzKa0Bn`7JJf7gG@zuEB? z0C+oo*W*nCQGI0v*sUP+Jiq`!EFoR>g)?diwWMM~XX1%ZYMH%+SEw!yn5(5$sQulo zZ8YYauzB{g>u02{N0W=4Svag7ETwS3>rW6&^47m~+Jsc6O$jD2LFxgt{cxjrtE9YU z9LIQ%wtyVM$&Wz4BIh2Y6mn3G3m&9Y6umhSv9US*KLCO7Z_TK}x=#H=9T?bhHF631 ztopTcSvsYr6`iIZ7a#9=@7e*)lSeAh;2u0Jn=kG-lbl(g(mCjm5_HMcu|0xyHluct zc?dGD;N=1W8s!^?AoCq&vl)xSBX*CD*}ZdzyYIcv`yagT8L|0{y_qXUfA-C{{MBm1 zY?T>uX0^NmEetuM;|6l(>g=4Srzh;)zRygAQri`ogF4Hh@Or)C%csv+UtVFOG3HFR z$eID;dINGzugcTUzu-TgpEKLpVRf}4UtO^}zhJz)WOI4NIIMkUL?G)Bx~bVn1hrjKYi3qZn^>{OBY43Um*-aFu>LLPjklsvFmuCX#Y;7|hg33f&5d%7g7 zmsj38)7)K4$uoPEj(Yp>fR8@?nDf`KSnTdHUSF|UF1_Y{DAc~zy~m$us?pdo@MQgkxFbOs_$$B|mXEU#aoGN+WJ| zY8y*<HWQ%!$oj^1 zzFYSrGSF?lZv{FO3++&8_t2A&E`(V#ls?LhdTlr5F21HwGEg+;RSnA`{aVa?qp{de zR6RHjR5r;LC^QITHnbaof{sy&GWvhZol9S5U5}*RHAY5Avl+9++^>J%v%gp{*PfgU z!zPoG2j#Oa(c$a;YTR&gc0tLma<4eWSv8@(x;WlqkJ)0EerE^K!m!+suP#|#U3%~s z9Z^cv1R)2TEjdLz(Bj%6(Xy8VNb***rGkPfc}WruWY;wz$r*RH*|55}por0Z+w-fE zdGYNNK6~&Uw~vl^bbQ3!{asQLe)9Mme*W`cvV8f9>(g`cu!&Z_O1D^W`{8{)e(xO? zUFRSsUfy9Dk|yRP4tMt1J-UVL>>>RXDQDjwv$>6%&sgj&=(49jaa%Oy(2 z)`QQ}urC^=7e>Z1ZsWwf)gTr?C0<^jN)orNITw;hBqD0C?T(K#U~1qT=1tvKp;7j? z{0%i~+eQ-?4OS}{9Z5Md|5&)JB6 z!AgiFZDp{8R bvJ5(S00C;B!})mFa=EV^zZ5jm^J!o%k)=KK#9#6S|+FpH)S)V z)YeMU&N;_%Cq-%Y+J^-BathCl?ER%!jUHlHXNz*@%Cyj;$Ix4JX!$4HL2 zOG0NewCf?INEmvFKyA&~ZLtrMiU)`YqKP!?NIMJWxAy6dZgcR-$NcCIf1e+`_W}3! zchMrAMOQ%$e)PcyJU>6@m%uQt$(9+GE7V4;z<71d#q*c^{Fk4z^TQoJI5+_EKn=fS z(Ip1UUb0~D;^K_I{p>To`ut0-PEK6BXv|)#Ub4@x0-Jp0J?w{(v$Hd_@5!5iG7MZ_ zU6D5fYB{piPHVS3dR@K{StcmCpi*LPjtCmrqHtG=p~*A&p0!90;G{&iGe_qO=DWMh z_x9-04DFO$GUH~=aD9cyIjiLg0lMT_q>>Akql?4?64p)V#hnkHW|rt*G3XE_T_3 zxWYNEB@o4Ebbo1mjh`HyHSp43+I z;WfoJAur;!zaA(A{VeXY<$C|C){EO}BDjgvc?4LB^g%n;s0S}bNtskKqeP zKck!Vu1>GX0nnUDs@};0r>$?w5cl3i3zH^>Vr{OSt~Q)sTu_FA_4SHz7=2TXGOpRd zA-5jB!=q0=;^^p*GLD?Qdd=DM=UhC0PWSpX>#GY^*DK#rQ(R9C*0U9|c^3sqvA#9J z%aWjsq>zCx~Npkw~v|iGk*2U zUvd8JQh?;Xv;h)`a<*P_d3r&jkV|&K zQ0Mv@^mo3vI)vRq@3#)ci!af9OkUFH(iYYe$ zRJODdz^GD5>IPiIii(P=iy0)WsET%$=(H5o5zUD%?;-265S99Fk8NxGc6`UjTL9qg z_!k+!%_lXt`6(sTN|XTzuCD53VIq`XlnzTs$x2F9*AKC(ed`$*3GTT&Y(bZc4Nkih zS!9`l>@u|jA~v{MQzqd}>doKa=UtuW>Tv>>eGsBbGqud477%SD$~$^7U&rSC?!yOV8rhHg%W&l9858(U02arwjQBI5k+j z#pTZaE{lUhW_t(h9o=Sc{}y!KQf&WVmvI>Q^*{VQJW-0AGOk^P*@*8=Mi~c+WzJ5| zd3JKfC--l&(}e(Js?=4XOTwL7``ml?9iIH+GYp>_!+P*+m_Z%}cka}$L8*1t883Ul zgD+>j)HZ(Z>{`j;kb=`zN@xp&a(UGOz)Nm~dOO13s-7JsGEtuWn<8Fot}3CeLH2BB zi`%tCfQYAowmxp{_%&*dztx5W{k_?`7W_|SREzVJx{kIWJGKDC3J`2tp_XyB=~>%0 zQoQkeJCUvTYz6QCC}3b)|K0Gm>+Ak$yK$81&9-%|-=rn9Afb8SalEZ-S!oIF*H?Qd z)n0G?a5GwG5x_e^FlAq10xAQbtYC^|i(ou#Rs>!i^ePf86HBQDW7Q@WF{ezA=4Az` zgObtQp~=}oG7RKlhIR>TWGFqLP0(~^JJ?Rouv&3`ddjQIOYZIOp@T7#4oy8KUYDIz z*^qg8b;0@R37d;0c^EM?DE!9$(IGo`?{WXr@A0EQ_z{op93m8!>w&Moeag>%@>5=Y z{yDR=4&;Q*u<`OB15M7I!Gyl=d@bhyBx^91w@Pa2O|YozE^fC(qm&6qT~86%*edqQ z!nj^>{^BL`y<1%D?(nSdF@x3lIpg&;>nqn#KtNNyR&#Fc?INl38g+BFTF!-}KuWB0 z=E;kfoSmLB=E9gu>|KSugFVv0A$LFegg^bWKVh*m=j801v)3m){rW5DddlTF=P#eL zzFNB9kP_pV>5?-yAYgKZaTw@uw%EAYK(;1U>Hv6|Ktfe-VQD@$1;M1W5-!H#<#E`S zy$EJOaxlReQKgxlsuqxt09s0;R@QDn9>e={x>Z7xV%e1fwI!^1`o&uYLzKwav`j5n zRmC&q#UKUSrm`+Xq3UBc(1F5mj$U5k|MU65KIERHW)VOQDFEs3@t50Ok=%g)~}H zwX6fkkll40-$VZXalMJ(xgr0^6EeZLYVp{~&* zi4;uXPF1yTHKyXFn1SP}Y%$uJ!$|a|%^=?1%*;18Qttt5v~{W!cBj~d8(yCxA&20b_ZucQZ{G}?P`JTV7T`}*X_``ln92e$oQ5Bt z$@Mcc4~%zNF;ATR6d$=2xOr z!RWS}c*W9;()XAqMp0xoXSTObzq4R*YY!oumOPS{SJ*JJx>`EzG$p6YY9h^MFq=_2 z#d2YxJtU{Is`-+&ent zqdUi>VxCbVv%J1$bAH9;%a>fAo-uAh%rP7pieNT?b&!oAM@GiHM8j(|3*)dsqU5B~ z*h{7Pw^%6jBamr6VXgktyGppz;z>?tRLmAT>>b}_@Ah5x@89R)!$-XH{sZnD9&x<4 z$Np^2s$~8jRepB4WW8Ryqn5{3!#j=!%N19b7c9;%IXORL{@z1oL37WN5rK@7bEZ$i zy+;qQzVp^>y<$su{G?E&0VJ7EzzdNsGjO;5giD8rg zMoL^iKbC|OZ8inuLJh>NtARDkT{S%=9em7pVSN@Bi(;bNcD0eDLrcKD=`WIv6%1c_@rxti^bJdd}+fg5~)oo7DzFBOrA% z=KHs}_0Bu|@P|L-d-w0NKbw)qk)wIxcyE`3{XKrH%C|rN2l~y1atVX2kTI0tk)Z1N zo~V5yb?U%ftOa77md5*zwGy`_=i=bEx?NNA&3Rl8*m%L9ONzl}=M0_o9>ylYN+z#e zJP|XbOKvN3l;Bi-P*GI8U27f-nv~Hp7n^}^U%g^^cFy(L1@1~@iX{45w>W(7U4Hb( zf5i76y-(kFtZv_9^I_)i7yA@TTs--T&2mY}#cAqe1dV-iVZgSoyfmc#VDGvzx&{M< zJdA!_s%)Yg*I}$DN@L=8B-exHWIAaB}y4artHYZ_woIW2mUxhB#jNt*e2jw-nAQW|OR}SD|%Q(eDY5r7+ zgL}JF2gSX(URnng!~B}m&xQ@0T7C-d(WDzj%Hlas+f*US+8{K@7XpHk`WdP3+nlOE zyX!U-D9-Uo&7TY?Sw%`l3{BZe0+RS85`-k$B~4?R4d_upu7E!S`7v+D+wm_y-U0w` z$3Mro;ffXzJ3_*bs&1pq@O>fC{Av|N&B1<5&}=1jmXe^o8cHz-ae=DvTAeV9U{>&e zxr^rs^f~pNQ{ZKK?q=q$o_fu0*8pL1WC@ya`}Ym++0l#U@K$iSfR)kP2dN;55DAl- zDKK>p}9jz=N+T~d|=&mYlHNg`BnECfehowZ(M4B(SwSSA9<0JNN--hH_{eIrF z*xLt#r;op6_2Pt-3$`9zP>#-PJw@o^yDye&x_gPD?wF)X_XSK8HDP~deDdxip1piZ zzgVE%42JB59^*(!YsTv{mZvkmc=DLvd-oxWA`H23wpsD`+izK(ow7Q=U|6llC9{=e@f09&Yr(;Ho_RC1i?I5UoTl* zUGn0^OESNY=Ir88QBQd_44f{Pe0%bm&wln9Cxp(_XySum^F<5&e+rqB8*L{Q>UOEWa`M!+mJXf%V!=R6n>ntkT{i$X1I+8Ys}%EA9CjY*t><6mw6~0$cyz4%ly;VjM@_ zc>c}zZ;$OjpRLCY^w>U*P4BCK!;SBdDbR1nlXkqDc#1S^puTAC@5lS66K?oJ0cvmc zGT{Q1#pRz+Zr*PP4s0u+Q)0WQv1|aDQoJRgtDon{*cLB?Dj7qgZa6}X$fVX%644BF zp4%+Zf;5Ed(2f%I+f~$1)HP9-XIDIb^o++3AMxnkUGDDgvgmqdz3}4voL_(OYtEm) zB(EJ<%)?018S~v;y8Q#*|M(+5xPOPE-9^k@BWcf~>)3nuJyw6R=JoSuT%DYg`k4p3 zHqwX@62zOnk03tQQVRPvj!~)wm2O^x$=d$XY8y2n1nUZA++Zc4czMApkFZkult_JY zpreHFV-jR6EXT}jcfopf$=6RFbG*OH@%}!V5{h~!mSU{N!mpk`<>{ASGn`$ypr{$z zC3biBS=_$M!;ikl$B!P+cMj_8XwQB(=TE-(G4DLQ$B+N||K;-4OLok-x;RJ8^-=OT zB9hp>wZ{_cn!%5RNK`UV zLHKqcser4Hw5LlmFZp2-(XIQ5s5Hw_g3=&jDVQxPUge?%Qww!u#YAn?Y-llLJVMyO z+u;B0_+Mqb1pwZTf9}y(^x4qtZE|I1i1p2-6I>wPNtHqpp~oyGaqt=uwPcEjNG*ah zg6yxNQiZyFgV0uk=(WQ-Q@UA?NQfELdixrIHz&S&s>Fuk8K>6Me!D)++MZLxk2pls z)s+&*H?T2+pUU^A{oStlg~*`ChFzl0t~$B~t<6?J zEbias_}zCnd~lEbTgU9}EVzC9kh_P63?=g)|MEZae6^vdu;!Ay8AyEs_3X2hjO5I# zvokJpVOO21I+lV~AOLThg%}^d^MGGIeaPv{m+<_V)9y=zhQq++>sJ(vuMGaOjNH9* zoAZk$uU@_6<+tB@t?cC`WgN(x5z8ZB-Xl9ekSZ)@Iqph|@Gq%%r%;WowjpY4#rwd- z3_ug9OU>g^6LRNl167Ic5d}$oD0eH`&q%wwJo@+p{^X`S^|F{`TY430{N2tqWPF9=cURXjuMj0(IWC)mU9Su(;l=$=6G4b;XM( zPxE|7@`GO(=P}D9R<{5X?#qiuF7pMG(Hc3kA zVX4%>DmTWM#J>w8wUB%qm2r~-R50Iuva``78JqPL%aXGwgVz20Nm{#u)K4hPk#If2i*z-z}b4#XXW8q?(D^^Db#BM=K*~CpXvAMXSq%G`rq>bB|E~0o#Qt;$}X+wkx-le{2Wdzfa#)Fil z65>4wW|}GXePU|VM69sQu3yh^vb_WeASG^g{L?;`#e*gd=07*naRGn#P`WsNS zEylT8&ACD?UQ(?j{AvP6BWiO<7?UKml#x2u6!Q;)G5tzTK41L}^h8KyBaEd^el7`S z7>$Ww=k%UV#?}$M6k;+JV`krdl@KBl8e-EJ6}1ux>iOM&b5r0Z!j335gdkcP5%J~# zr9nc>LX!hA4urTMTn%PcTm92p^E&0;1R=&2BvR?q6VbFH zXI}*z5Y!A(&4^5RpgNTmIMhp?vjd#2NP&_`LvOUbnia1LP7pM?^XN5l^|p8t)oTjP zd#&~D85~5-X?7LjKo#;Ev5Lh)++p^be#C1I9sEl$kWWLwGVL@iNT5h0Gz}VBQ}AzE z4;%!~b{9gb3Rnj%E2SIr7aq}$)4Jvg9!>mEP)%b)YnCm(Tqc*vc-Lsm`0G6-D| zhN67%{zq)j*1Y=WTcmC1nuuy4B@?TQB_l<-ytv|gv!P)%I@&SXOJa}9?nf7d#bSX< zBz8-XjXAOLrV$)jtE^!@!XhDiJI3?C64FVFQ*Y8K-vL&ccP)?^(>+3XNbH(Q0SK1z#akie(!$I(sKo1$FG%WpxF0d(T5uG!(SYkQ0=J z=@2BN*o(qNzvKG!gl4(V(cN2|#sy#f+R6kr>kZpirwmuur0v=S=o+(=DMs!-e8{8Q z$E?}~ea@_+5JRAmLI$qVj&GhmVYj|QLLuc$kw9!)XDC_Az2&W2G;KHO9^}O4>WbZV zgB0uLA*hM3lHLAU#JUuv-cOP-@tp_A6Y_2zyzGruR!P(O% zq{}m!tCrn*ZHxh;iL91P*ES|ln_Yy|Q|1qBQRz|tN{gO z435=#n2Y;NzP71r0OXXcoFj&4K|&sg1e)X;01pbX;m!7D`~S!G zCIIke`$KMXdmZM#=OdzeU)0h7zEiqz2W zR3kl(z&C3xKT$s=L_1+{r(`AwHGa7+983Ui@=DzitaMar?HIns_{tb+or8`}YZ-cP zlVstDQZtuh##6@3XuWln@?1p$DXuuJ;zKoft5o3~qp8~BY}E1Ez1YSth`KI9UC}g{ z8g7Wh(2~V~zlPQnhGRt9)))azhcqp*>u44$iU!)n0uTeIxu*;}nm)1Xcas`_5P~+u zwj(T;9KZWE|L(8 zoVT^Gmu#N5AaoQ=;E) z*!byk_6#i!lKl82Vgs7ZWPup!%M8K&F1AuD=jwWf{nr zsT*1RK~bF@L?<4>2rPAObjA}*Mria_H3#EC?U9aO!~!cayRQIM1Z_NrQ<}%~nBAMc zF)7!p+shi5!{0+|gJ>B=sh8u|RDr=5XHX9q6{D(Y@&zP1N(#6*n$?_JP{MIuwAOIO z5-O-PHdYOw(W%%SjX>Edn|`3#v=9QZJ7+jQh0s_h8z7}bzh0C2!NhC{l%%ATS#}M} zgB6Rmqib4*!I%g#WN(V0Jij>S`L~bBmut$9Eu$Q)r+w_q#;r5 zOrJ8>SJym$`I5(9{+<_Ke8&3QugO4OZxJmt(R2L4UanZ_{wOZcW5JP}F|m;f$ITy* z;F=7$%`C;(g*kghJez>2LUA1k#8j2X62>}T#vqzQT@7R{BSWV6BMZ)Msgf77yoUd; z+H&_*Tn}Jm5>S7Ks*9v*v$J?fTF#l0d%r%WpgD5W29Cz0u6gP~W0~#Z_j7g))HT=t zKPGj+0_II)@0#8WR)|exUpGXw)S#mcP6C0X)pW(|aRLg`1mZ3usSs9~@I!9_@Mim$ zwf!*y0N>}nyxIQcZxy-Df45b2{-Gj^EusyfD4}C)x9%&B(F&CyqS0VO(I7!1Du{}R zs(1!pU?dESgmB~St3pPIfv^x84;0r-Pc`zBUs^}5H5;$v2cGSd8n$@Nv34NC%>}l` z3`WKH8i}rcsMvxdcx`lXdU7rDcPF$~@73PAc1jzUM*tkuE8c~jQtMu8FPqT`76_3d zrleaWBB4b?W9@NTYf%+qO9_n?Su_oqmTt9Txqn2nzelsT4`QNxLNS1Pc1pUwq^tw| zu(i`S5uqV;OWM6X!g4{$jH{`&VGCA!9RpH?QobW0pwJ0{w#o-ae zmgV6A-QJ2)5+{!zBNq+j@`9AM<9n!LLW0IhR<_$6n^ZXJlp$q`CYq)p1YsBwO%NX3 zzsKhXdq@m)izVCsiri;JtYwyFthXeEAq`wUe~u8)lbO|3g; zG!3BH0lu|4)baiFAVBf=-_cQFno9ys0d_`(PSAdO=NbPtX0@tnl`!dQ)Mp~qE1XP| zDoCmGwIWClGuAr%;^s@h^-D%@!u)&H9?UJBJDoE7{B>YoZO{DU@8IbDJEfj2wx}JhGodd27i`D{#&(m{wq`5$A*;8NRAs)Sj5KcL@Bf}vK%*cYpd5 ze*V)R({zE8lXG6aI_31$DKEZ$!uI?Xd40|0$t(J8PiP7$=@fX!%GvC8I~&R(CP;KP z(BMp%V1RIHoy+)sWVKQrP&7q!v*zqsX1m_dU0red;wg`Rw?I(R#icR1s=|C|=vIM} zGK;-E?%z2wW|ay_3bDRE5t`g^zFV_dUr|&oXc7epEvx+%2Y2rB&X50uj~_ka&@~g< zt|bkL&7(&={?WVq&8p>#vlH5!$qFfDf(T7xL87i(K+~9BLliV6hFwC)&|B+M^5FBx zGWD@>0aQ^md8tJzz+ms<012TL(C90YW=jBQCSqc=bDkoPRp^yJx{q}|d@Mil%ZLh~{>+fSwV5Nk?ZEf3{ZTIykN+61f z+7j$Nl_K5_P(rA#gPq7S{+dN3h>Rs`o*fTNVu01x3{6DZg=I@Cz{d&V)e|2FK4l+Y z_oT&X_v3}?4O}sL^mgvr3ND*)oCDXoLK?%lE;P}pkBo~_QT(3^$~nc=0tB`o7I$2W zN7=3WfTCEloeNGg~pDo;|jnxDA;O+7{`SXcGy|!jy8o&wQj~ar>C|_zp)8 z9&r5d0jtFx2Zsk79jrJxJ>@rl_X{q*_yTqV5iwO~!GaMYw2Kv}aJk!%Qh~;LC%4w~ z&U@R#{%XZ?Z;y6$!17>ANj;nEHM_jAjQw^;)3xZ(^ZextUOsrhdq>tupcHkGE?lL= z$>oL@=jVL(#aE=wnmlCBI;*vYQw6L(H2`V5BW-r0qhT5BjHc}R3xg#mfP=U0bNu!@+`4~{NAEr2_N^m!{g(gwpZ+gi zeEvDRVKAmbwp!j`(JfL+Y_G4`UR?3)?2`N4?NR+$Md&v>v=kOy%iUXt+d{N)KofZ)A`RzTZ@qJXY&q14rMxdA>%wUtG2F$9URSi8_{kD$Tr_mD|gMKoE8n;t*t4;A| zAX<-+Eh`zs0F+d7TiII5sE1O=;15AW#-NYstqEh9n5&xJb?9dYNo^^oR<4_1CTPxO_(IKF*N3jy05DaLgXlsE4*Ifz0h$}&87agR; zaDK{ffAI^t82FQqKH;5P$E;$cA=9VC%gr@Uo;{_%yrc}n$QZM#ut>A$Xb*33|DzB1 zU;gZ8{Mp01G%>I}zQg9D4|#dD=2xHoo^QYUinC`=7z&h&Q_{6B?j?^eb->16vdz)p zptK5M#thk){yy#g0Zq36iNpeV*pYTU{ccOzSU{Cz zEh1Gjv29&#t{AA_4JN**y@?uYMoU1-U}b#Hvdh=wjSDiDq6;tzxL1PSPA1CA3JZjXrrcqoHMb7n(P=EnQF1P zsiT3-=OQ?Lbkabo8Gmtx&X|m`52tyq({;tRp(+Sym=Zn~kg9g6pz6}QMiG#bRTM%| z2}qHk8j;dS2|-GUwUS_15t@wl-)98hY;U%IhV73L0GPWCZ?=D3+xI1O zKQ$^*A~8gx{)?a@rBDJPf>`pU5fup`h7gK)yC*~W(a^YrAnGl2f~&zR?&OQ08faqY zQF!}75Fzf~o23V^*^~kn(z@Q$r zmIhd#>ggDO2N!IC9peZE7YelKwFR)nvmCa(Wno;TafdRiweO)Zsy|JKv`c6g#MK^j z9YYeN>mUou{RMk>?z4Dsp9dd(#DjJ=J3M{)l&^pLDa|&~$KDm9Vc7PZ zKYL1CtvLDMM?5;(XFKdzr^3a$=gG+lrxz!@c=?j`#W~x{HD$e}U$5!c*OVbsZ)VB` zux!l~6fmbCS8+R-1%~XQ6h}KEn6u_iNv&1RIeRutAV3=exfl~9#>irC$?DcIi{o1y zy!AHs-~SPx{N%^Hd;cCs%LQ$Sgf_7K%N_sa>WZP?p{b`|?;K>9>b|B-&WT;W;mfDb z_~~1B>6(T<7lt9xwvEwkv6rvux)F@WV3holGO6#05=;?XK>7-T%pnq#G`M(E&X$!; ziJS&={Bwa^RlILf{f+J7PF9&j5Ua;1HTX5sV|8o|Wdq1l@J%x{;8uk;>-R@COewQE z^g4$|roYeg$#PlXKqp6(`X1Er%>n^ql#kaqP7Y+f=6SLcvw7?vj^KatcbOkrUptMx zYM!x{DR98-I5VI9W`cb_)@sJ)!GPDUVIJeSu}_VnydDI2Z9q4!S!cg<^XGYR=R4mX zzo(;MqmIu2rj~qmG^w$;`8)9XJy0xwP;Kituiao*uuw3R;zWgUgq2=WJX;xjcDQh4 z?fBtuGUBZWRdl@d2u9f!17*kn0g6VX$&?tdwr{4fQpD>1CDif)eC>*E=L0b|Bz9cq z%pQgIS;uex@4w;X*)tx#{Wfpixy!wyBf75T)5nkb>NlUVJ2^APfsa{Lh+V_#;E=uh z_xbqa5BTu-kQD(bfi^C<)xf=F%fscL^3}T!`Om-j1(#PBEVXAn48#DM#6YhI5{>C( zv~nw5iX~FYz_88!I(aKRe~E)r-PLcmwbB%_4E}%%5-h7P^cEP|##w2W*@CQ!c&CwW z(Qx|YDgW)i|2J+Q-{#iAZQi?cm;F^o$Gw9+ z7J>1)kb*VS4Gei;=y$}fA-PCj=pwO1!lI=+xzpIvL4Y(cthWs7D^l*s{f@Y_;JGFXY^a*gA>-VFET*hHjhQM( zLnT#>!u>vHM5dSDd?_WX(73UzfmVIp7RLJagL;rlN5Ed~sjXW%^}dc}q_uTt=1q-S zE+_=7;mx@!9J8N_84>XHvy$`zz?NBL{)nXSb+< zAS1}Rc0gs&Xl{Mkwc!gwCf2T&Z?*nXzuFA~WFGQaMVPi21>AHy(MtaE_nFh9bP{8hB9nvhApWdoaSxL*>r9iWG+RGrb6hn!a2vsd zfd-?PPhg|=7MBoBz{pt#qD}P_2uU1avZveN=s~{^AV8PWE8}|EM|J)ih1ueh!+a?+eqRDqyVFG1-af z_Q-5_^HJ3AdJOKy{&ie80P+n$|JqiMJr5w%s?+y>%dz<~EL%#g^56UE`$JK(OQYdvbBI~+j0MckNA)O@jtNFHf*;$PF|hy^5qMj zKYfa{kBR3k{bozIXlWNq_U_$ddALu>neFwKe6=BMHmtAD$-8TY^GnKh?HyRMN&kid zC5~$NTB<x|+6ja2R0M42SGi*&wQeccWbw*MZ{~H-x1&D4Z31pP0 z!2|4|T3i=NCp+tb;^0ip$^QC0)T-k#vpF?FLG~Yuzdu!jp!#V(>8;lkp;;L4cY|S! zp+Im=gc>QRf#o2^4fD91pb$l35`q*7r4%hr7#X(2s%6+r7VU?&&By)Sh3d`rgWKMe z0KD1$7~9N!BV=c6IeSk4DM}bXjD!`%h-Fm|pmc!{#r1OB48>x8TV4CDl-*W*laUh$ zT8sjQIa=ZZY$iq*T&=}%T+Q~10+CVBZ+;=QewWG79fJgz?yWhWGJ+EvCl;N6VkwC- zmXLXgfzy_Yc;9kgI7?kzvl7*7|52pKERyayO7StO%LYlX0KinDZr4}pwOP(ZB%l%r z?E-CDv|SJvE84w%bZ?*b;FxZ2kJKmH5NH=2-SI8%+<(g*CR1n@r)dv4(KQWskMD4B zbj)V?iVzymVdkeR*{R~^>uc6&U~d`Or9#YV#!2v~KIYJ*fm^ZR!Na$CviuCaxPWY` z!P{XV6{U#s>D8KVKm81e4PDn!(!kZ}IotC~`l~C77TQH?6vkmkN`r}bRluUyXX@>Z z3KYBscob!nF;igRKUgLx2!!TFEp}~#Rn?v~l@TyV3^Xx7Y>^l!A@bTJxwL;2GV9je|^Qt%V+%h$rJwi{YUN} zMJ~2mUY%|DgE8Ys`bS^73a^N}fPVQtuP4t`(4-e(y{Q zEl^Cv%S6pA08mtI;=<(QRbW+HWYynC#5^H)6aROSLd61ip+ZWdv`#=@{r5^Gt^0%- z_-C5uHJe`D!{YP1ig#21>$R+Nusv@6hYF76bznUMvi>@FrO+(v?FS4q6C|_qs7$Q< z8^`smy!-DrhE#VMr9kGOy}tL{xXhbho{hbZp$0GNt<^c$uko=No}Z6vJd{p#_39oIZgG7AKVPu`KoF$O0b%!t2dD$~uB$=M%4xEQeThce#uG05aM+Fpr(37B{r zHoqw*{%03&pF3Mc!W48dj7IPlpW-M83lJ)M0Rx~C{k$5i#0KkMuR$PWinq!O zT?5jR9aL-Ivpu_Db#%z)u z9j#b>`oaBs{Oqs)iVxm-K#{`f*#+lk8#e1pzWwGKHs>c?J%7&SH{YUp0M~p8?jV__ zP@Q7|bq>F3F?;4Va`b2vYRT1@!I#Nq6^un-pUdcDRG$Ygk0~?zXYP(pC0EMGlF_1+ zVP_qLirMiH;&^W-;6A!d7O2AK3?#=cC-Tqhs zfFJq`|7QFDzPYzO8H|)-|u3Azv!ky0c?36-nw(PhzsT871g z4T@*Xg*J-o(kRxG*eH@Aw2T10)SSBQCt`tve|q%Osi@y^;LjMr_Qhnj?%Lkjv#o_9 z%2?7iI~{N--P?bX7v{~^#u>(Y=sTe0g0Qc4UV()ZSTx@4!7t1&9r zZ3vfzwAnJ8oufdzXz2SLLq8y?ka`mu+73ONt1C+H;J>Je)G=#Gg*hfU7k6yUVG7{) z&47OljROeNQ;;TFYay|BFvegS00HtaFtD?l*Jv#hOM#{pV%HHD3%X@T7a@j7%7sOY zgkb%+1A=Pe{=K_&`zyM=r3n}%Q+zHZ!>-V;8_u4;U;uuxx1{N;&-KOmHP4`%LP}^Z=Je)lbEnk%Y;6}o9jq7Yu#jA>+q3YcSbHn#{w|
    ij7OYbqz}NZXC_>rf_QDT-Z-gDz|w!$T8J**E|Qr5nZG18Gbj=!W=gaP#bJ4pxd~9es$h|Ubw+y?U zhe^)>0$ z34OmI_h|~sC=>~FZO1|aO%qMQ-h-3@7_@MDbwR(qHeD3OY+{H68VDWxM@PK#@F86c zq->LK*|x0ONV9mGU%m4-Cy$?!5aMFV-FF}H(U0Ec-J?TdjO>o@*?9w;o&5=4J$=eQ z{*S+BSYNZ#-Uamrbijm^ORU<7uBPW9M=`%8XfT^z)H*j#R&ELaU_MDB(>xpla@CF? zqkv}pS8lMT+z?0sG3|=Fj^`mkNi+LzfjgO5E>*@(9yKnDh_@zWq$h}&_--|}Q!KBp z1@4Q8C4!o!8|}sTH#bNUiYI?Ws^qjSAp%GcDWb({V?sePNRbd!N|55oDn+;r+yZ{j z4{>{gl7hK)r2v>0FML+zHo5UYZV(&h|zkkkBgD*C&7T}4R5$E80r9|W)Q_eggb#+ok6dM z8y65?Btu=8$WW3y42&MG(a);mGSTY5kLCZb*ryaz_P^n*>U_DYYym7I6=W>zGc{kk zFBuDvXb2|m*LK9k9^KI)M~~j+&wu_`eEi<~D1{#3$-}pK^7tve4lEWOF$Pj8D0vjR zQZhnhf3+kufngX3!2&NO4;Cx{N*>6YHCN}SeEa+v?;IV{#7NFccEG(EEQ6G?Leuc_ z@``W2{F3475=xJ? zUURig+}&#lVgiB<7HrXC8Jl~D2i&@SoAbpU-D*j{UR!^0%+X9k&(+J9gb;Z88~ES8 z`NqImDr_&;4A)nz&(2t%U(s*3*1E5lKxG+rlzy;xws>1dapGjjexB;#l~HV}c(xAB zwx0s7(NM_Ffbp=FXL$@5*~?o2z8dAire0OJ^Yd3hM?4#Q!@+m2uxPEtHh^dNtIkiG zb2=VdZ`5*+bKRZfI`5@gA+5AoX25S|;p#RE7*?0_hQeRnCX9OX>r*AtMAPRcK)w-F zm>ee?5rez%oloo?Or_3zBCe;)W4laqD-*Uod} zZ}kgS6vimz=fbI@NWgfJ(?hCYa*9^e&!_Lzppq)~@;K9{iV)U&Z3^o18{sY8>S1%H zwiIMsKYYEIWwY!1Y%5)4ED#VA&MShw5JCJEwWU?XIw6E8P{OFPAEcl;Ah{qhqa`6> zFoD+)xV|uoe7opK{b1cug6(hJVg}-3K~}R*`v*&!7zjjiEza?7BZb0F6Tf->oLA4D z!;mO_PYl7j#%N-Bu+QQBw^-c1$45W@gyTE6xH!Gw)yrp`K6^oImaO)!*p49;=d91%29yk9tgoVl^IhV}lP3(9*9_b3*p| z@31>Nbw)_*6#B*jD#>1FL{M)L=phxdDvi|A86D?Q#rF1Y+UErsJ0=*&uf$9*@2ZS~ zalTg}&iXjiZ7G%k3SJnNdn?(fzT0TmZJq}gAg*i+o34(-ndU9yycDLc1ZD?nIRJQI zPlX_nrdt|&1Pd^Pn&BV)L;HS1AThGyY*jMND#0or8l|+NCALIKO_tabl1WfVO2|(^ ze#sAZ`<~V6&Gtjw{?Gw{?_2ucZ2$5%dF}u8=jta*6pF48O}6?p9iFvEh%_REphSeI zQlgqeTPPstKGnQyJ43G zPF|fN0{eSQjt-9a-It$p^3|8@F0RSjfqu8~%s8lKaxSEj2+^*mDCClf0z=O3t9xyz zcTkXEH1=@|VFIYZ?-7+j5?v(B-bO+&21UD|i4DzS$@1`!<^De1Y7bc~SnlnyTrTK0 z*PK0nK>}1FS_X38n?O}5r0ov!K!1JB%hOBl?(fq$9X5L&I{@uK62Amv5*#cS+K_D>6Wm+ZRz zz0Or_(zBVWmcbV-v%rZ1cytuuLW{LUtB#vZCCiEd(+lqRyrTc&J8D6l=`w;fDxOv^ z-I?Y{)#0d9#?!o1Krj!O*$Ywk7k4b{{Haq&#(OaP;%mljj;fha_ABtO$lT|s%zVpw zoEd1%%E4Vyjp9CY^4%r+|OZNX}tzk|e4$H5(Z|8mtZtK}wEy7Ss7#(SjGg{!Y0 zxu7G3UmaxB;Ddix3NDwyJm{?1*Pq$7iWY~`Ue}i0Zio6^@tSMDiCVnx+Vmjm@}&e5 zP74uoGEf&9D@k*kKqyE|rYs*CauZ1XmfArk)l6p-F@3omakHiGd$JY=XU25P4iyVV zQXn*elYZcR)f}e!?i}7ULIf)*lj#Zj2cbf z*+@Aj>qM{)xoKO)lsV>7kk&rKv$^)UZP+}^N4EkHQ5c|ygXq{z~FOM zJkU^$k4)tUqb>KKY-n0ztc?5C>#(z%*7RhM#7syC6v-+E2(>m`CnR5~Y*fLhx+u?(h&!gL)N;nLMNU1w0$FRFYM5$TrzOjr(hBs! z=<6``?k%nmEME6t7dpi=U0y%hwAPO9V4uUTF@;`%RU5gxzhW~C^xL(AEg>cAyBk7q z=OJ>w>v{6>6}#(=W$9I|hjYyuXQO(i%?4R?eDUjFaTCvzWV*k!D`?v3KaOV#DhezCdaF6#NJ>>5G9xpG>`QQJK z|3uAHtuHTZJgyjCG_%`m*j!z6esx6>Yi_aK4s;>Vb`e!!b3M=mIM_cxH8AW32k2Eq ztDwErcwV2Lu{pmQGnPdQskgq^IVDr;Pnk0G*4mI_t)+&9Xzh3~f&WV5uK|$?PKt}B zsj6j{M8@~rKxdg{vMVLqpBaLcRycT55YMuBqR(hURbpF~$*QC{z|ey_r=XV%pSM4l)BSo~aB%&2*02tcH0iE$}ZEweQsZ zX0Oi#$m`Pp$>M*PDWC*wJy(J|V_Cw_G=!koJ2Ryia z%)pdllHd3lnW@I&1otzqCaPz9OpCwRq^0`p2<@6FVpB|`Mlc#a+S9X9;I+-yO zWc1HKLmvH;(H5&eXc6}d7{@1}v1j1E;5^7tLBGcvC0NZt9Y+W;pgD<>MMcEhf~qDB zkRa2vg&+fQmS*^u0RGYdlCqS?6r%Gr+BI=>!y3kY)t~#f4m22^A`lJZX z4bx}8)+ja9jscT*QGd)vSI-q-RP_PNGSm`;0w(k);vECb8O}QOlAlBj#mfSGNM#BP zfa?GtzUVqgstz$?Ss?X#ScIIQPnOM!jg?D?CIUj|&Zv}N_3R}PLnPvkaVcaCd~@=W z-+lfmSFcVOHapYGQXyw|)C4kx0YR=J!__tGr>}@@BuHSfTC%xbQ(g1jc5C0u1(Id0 z({^i)uD8;YF~cj+dRE#6CUPo-8h@~xXXAC?Fwz3Sz`vIR#J07pl4lib_o2{6R06SW zS?nLs9UikhKH~ldAM&FQ-{*t(-{YWLaIjjizi3$~+}qpZMm!XZqdN)V52Zq`{tH8m4FKEy+T# z{>zqiS4vK3R&q&DvVni6_m?z4DVBXq2I4EAwjfn@N6g-(tm@ggvFOA)0H}_%f9u7p zUQ*%jb7jhS%1*H?XYpgyR!r7#!6%(FV8%N2iZCmf@(l1aacyo?ponL0C%|7P=4?Wb z@5pS9PiXU>ru|Re?RP()gJYR~ua`9jHynJ|;Z@Cqx=(d!M_4?Sj?e6nk3h{F2Ia-finYW>12k}&J~Wgi8z4V76x-5VV-?KD&yVO7tc?#-kxFvSF>>#1WN*({ZgucpUg z7h~`981@(g1Uj?1qZOY$kJnb63Mwk4zGmJPzK{*!!fGQJ30b#Q~D)46Hc# zsr?8YSdOY|M`fRk5>uLXD=yT1p)?VHzLmt^lu@N9m{VoWFz$o5BR zBjij-<-a0zqR_N&3z{$|_ z>DS+I{qz;X=9<*+EYRw=xLq!2_Kvv!;303{K4R51?6L);MTE8qynp8w508)NmK|4T zXQcI-m&$ z1{dbd6kPixg;9${LPP_k?S|YBCVsl!u{%HK+2>y%%LV(lj)c%-<1_SkYz$lcdywUv=D;M;49H1zraWYDU z!Bvx`1Zw91peE&QhS#84%}~^e9WqKo%7X=uJ$NAF?5eh*ejY}qj|G?mH_E&G#B4zD)=emJP$Hy3Wy+*2_cA;0TeNnszR$4t7|kM>}awg zo8g8;%MW#{*8dIo{{e4r0swEeKh!q2yQ2qoA3}c%(LDNk=1V3@Y!C@F)u-~7$}JGJ zl&Bg+G)M%bXh1_KS}Xr1XI8@-cfMcIV(sN>fkCD6J8iK-_sPH3v13|wmDRmsYgZ-IVc99|f|aSnxq9>J zT**4RA~iu;KeP625(M4H&KbFcS0VC{?$BpTJ+GW=>HPJ;<4s@Is;n!uW+ zcI8878el<-dLK%GDB~htOTa^8S^sv?fi%|oNeja;plP6Fzklvj$F`$gEs({6?%pjv z{Ij3&v!DDakM7>%&fdy;SXLTtBXl|P7oU90lcz7(t}nU1xMWxxUDosq3Vqs9wj0i0 zKIO&Lhpgfen(h7A=FHW0$J3KjUYxw**Z<>JY+s#F`W<;^iv8kXK9}U>9nopBHY0Mf zYtn2EkfvnsX10@P$yS3pV`_N5e|B%jm(8>E*;x!sl-#ilz(8yjma>~3P|X(65UZQ5 zZkOK-Dl^6YO@ANZo_V6v9IZf4aOY5G6MwQsBPhHv=V!pM#tx>*I2EW*SaSryu4$+@0P=VoPp!|A**Awa3nttcmIXq^AUu41DKwp zQpG@K1E~*7$8pxL7j&x4vV^*qb~*U)QU}v`@o`l~ft2z5HB&hPiMk#sz82K1tLp~% zO%58yma)Nsods7I>HB040*IBvR91t%BzB#p2m~c0Jcucjs8DL(b4At4nWPo+E^(c& z$hlBT=2^ev*f%MQsD~}Q}U6sWW+6WrmP7RcPhi(T{ ziix#~-}hK^!2unVGMJbk(e6p?T8d_$2bLkXXQ1OtmCIm3hS=Cxhl1uvY=rIQC7bJO z_OAE+Sb>Yq>htq@!?0bGw%$H4E1`|#KGW}ZH2scYw=pKN z*JO@V%s%&F)O+lS2NG&j!AkV(95wIm7I$Q6*#Lz=+jKNd>wEbcR)e5*9(i=JsEQLN zgJjU4p`-&b$ zxvV+@iuYa~Ymuu*%;cDmw z*k3KUwf7F1mBYn?KvnB^=Sl;M*wRX1(KK9PYX40m>;?;fjM?2}A@Mu}R0gD(Ai?M` zCk)hjR#{82tWVvqGADEbrKG8hqY85s&1fxsD8(EEr^iZAnsz~KmNbhcMIs>vVkm6Z z*QCvsoDy10+n`{eR$@yD!oBz2;eY)P|Bm+$4pCJaab%@|*t*iCD7R(7hwr`1vuDp( z9iEfcJBDo`;qAJTvOYcI`4?aD+k5vp{`sE~C2)Fq!Lz5QeD&p*oV<9!=IoTKr!N@J z&skqyQg%H;Hu`Ko)KC#=7|e;PwXii)?v(zT^~dk&807Ncih{T8@*d6R0iv46_p^$l zsWVe*d5icBG)dLZ8fbY*($Db>3(@}tG zLgaeWG*wP~siP|6{FuiW=CJ~whLfSwY5vz>KqwQ@rUKf^94R+68^(1YT+^w(?vK~zY)b4BL&mgsP9BQ;f>Ww9f;1Zt<>jkJBsQU z#PWEAzbn&)SxZ2*`hKQ5Y#~rGo{5~6$Xe@M14Kpb1i^dS+ijWvQO(Rs@f#)Tud$bT zY4(l-(WvMsqL~mI54;)Z%{dU7h{ndw-C7rue!C$*OKdMT#O^t}vpZb8c*bu^V6neP z+U?lAe8ukUob7gFEF%{`TpS+J9UgJ~@BxqR92*GE&^Cgq>9W*V;x-MuIyag36@fj7+nxCP(voMae+4xh`~t!(b*(E z4}Fqp$>bXBl{kV$aRZYF*YF9#bsj*4rfb>MavW9q&1Nit3Ie&$KyLx|lzH~;*Zl22 z{5>B$c*O0!1^ev+p;(}|-_dWkkctHgQYMtbt6^Y$am989PZQS%vZnr zip}YTF~SgQyBi}ogU!0PL<{=lVvI1gtiJ_IJt2WW5o1oM5GSKL%{43_9XybxwX$k9 zSE~J~$&0#!g*mWbdL!fav{-3c&gLK0V6*sq8+|mv*C;zz7}BvHyH+cY zvA{wdY;YTCT`%gI7u<-C`ae3cpG=Gv6;UA&G^=>)=>Qt7^I{PxF@%^y90+|ObSuK; z71F3UpNGJgrl{*lPdV)3-sJSoPa`I zpd5(SMMJ0hw))vve_W}bl``(mVFjlp7td@P#Vlh0sf;V7Eq3P5mKzR#tx2wQ)0*m= z?_*8#f~oOWx}#Qo1Xr^6x=It7^2-zmT1Z71Hd}VkixjEszo@bK6Db@!hi9YY`3geD~6jJR4Yl;;`hhFriSNPNKRXh_?wYo9XTV?L(ZEA4X0iOt3>K|3lass|1nP7j(Z*7rK)lSx zLgIZ*&l|ERdC0(&bk9!Ok!SJTVX$b%oLO+jJeniC=qg54b~!y&V0mMp8|9!*547Wg zjPoYr#MCoq3dLz6?S4(>3m$r;piv-@*mk_>sR$)OZ&L+IYq!m7wKYm|27u3foavk*+eAsaH z^d+Q@ZqcDy88;hCC|YbUtySs!4iL2KxPSj1d#R_BYbriOD|G>1>7&$#|RK zQ|E)uu22il|4^m~BH+MaM=?ODV}%MIkBL z7wD2`Uuy2Emehj`{!HVv5x%(v+#a{b@9elW0NftGjic$Tv!C-Xo50%uxi`jnO5~JD zYPn>RXw8sBlpY}^Nl6UJchyp@fQYEHoyis6x#pVP>mKockTP_gga4*IPl>5aiF2*f z+nt?k{Yc1|@icM3eSYM>Y(}jyJ=%P*Woa?EM;4Mjy zf0i8Z&Ei+J#js_6WKS6AS63f{TCFB@*{->K{*o_0{ghJR;LZ_0dH+N19qdtx)fw&+ zbgn2BkCjUz6dif{;eGDhzsKq4pTcOykZm2C_gBZD?prw~$)<2bDLJXIn@q@zH&%#w z0*{tm+q@Z7)hMi@UZTsDHut!-dEu4>NoH+A68-XkyuZiZqep!Bhd<@f#x4j@KS${S{saB)g!?c%Z}!>jPwzt08|V14-Nu^? zhw__E$2?8*dlewh0QsB8Tu8=8GmzdoGl{63tp73Z;+~F6nm4ZL?6dh9_&bts&BF-9 zuWjOGHna_#PkOf-NW=l^>=k&Q;$D&54U9rR_Y}^>xH7eEo$@)*Cc$jr{e#9chyu_C&po99F2M}DKV5nl0-@!!!Xb-d+wYZkTVo#Pth4j77|G++cNUi z#RZqAuc+%S>zj=gB2i0n*e@0w+<(9y{Q1A(fBd7La_{hvPv3r*fBN;OoL^kBc=?Lg zPrl^l^-KDpupY0;T}LS%&Xf|VvoXpkw*`_VS(4XCPAk=;`DR8_H=Jk^tdyyhWz||O z*FhCZF$#alMp>+0ZHD4|yaJ2eqF!415y5Ov7ki;t0GB_m1mBNq$&F@QZ->#`-)igbw{_-l-!xdDsCMXrx6C$ zZ&9K-zoFDky^a`L!jkN6xyXEu$eVD#T^!nbqmb-K!CVQOP-3;yOnT zW~F!F4zX)mOs<)_3R%V(H|Z0qkr>f{JVeqZ^^Z=JlNye zJCC_IyWr`?HT~Y&j5jru8S{RL7KYV^ub#i+_uqbt!%iqw$tqSLI0xn36sJX>c=X^t z(uLBItdhbwf(oUKT%En9ySXNJJ)>uW)?x5if2&MTs+IfGaYV~#b95}0c{alFc`p}wLPETVJs4%dE#wuMrcAcSyp3zamsTwHb9M}u4*Oh2sTfe7zHV{yBS+R zl8?6;?j$R%{Fw+^k^?mhbCO!AHIXu&9o~RZkqu~tZnVvL(Hlc;QyEig$wk%K1FC}L zOy28ZyJ2;D%F}1hc~00JiEN+<4-D4^ z?!W&oAAI-$C%I=I`0iT|dH?Z4ZiX$dudn#%*Prn7|LZ?-{`qGttB01Qj*<$Jm42~w z4{m3SfYHOBa<-pUp$`5t8`$qGH$e@`e0YaNsG}v_ODa=R!Es(s_-bl_S2RD!w zFs!$f;hfdw73-@ju1;T*Ql^SB4qLW2D_E~7+hWXu)PXZ5st(kxvbTT0a<3=np5?&- z%cCR8uq9{cZVp(To0+KR6`vmHd)LSxfSP8JLQtYY~xP%}2D zSO|#td1<;Ujq4L40zt^6ZZY!-+1@>dfKEECXM27TBqcE|O(3gCmx`t;Ig4mtQ_Z=j zs~d7xNn3#jz%y=-+vC6e@w+krd>sVd9{-w;Z+hPjecgyU>6}uPlqWDN*?co1LPqIS zq&mGmD=bhFRgo+P&8u4BKpZ%z$7ZTvaRQ-z8KqOJx)&guXC*Z90M|3+yImTahl81< zvv_*n;F@Eu>2@=X(PPjuK-(B~N;sr$QFrAmlwb7?EO-f~1mYedH*O?p+5amt#i=^n zH@qti4~0#m`Ub1M^G_bs3bnvEQf_Xzc=ZzY_qp@$zkJC!ZcwcZrNE%AOr7AMr8wblv;;mDO*f0vbFXh5%#W4(>`8$v?NG`Y zQX(ab8&xqX380oVcs;l#nDWS)2VGT$kcCBINw0gGdlw9yb1gZlh-|Rc%<32jh6pLm*!sc zXgAG}b_;XY0Pd##&Ov&(=9>fytSZx3Hg-VEAuzSyq9NvSygQxrA8BeYfW5{zdfPcb zgiIF(gG1aByW_QY3q+ecGO+*@o8I$$c8X=-p6Zs*y6ID`86sL4zgdIcEx}dxHWty{ zos(!UcmBNq;g$4DoAIfE2bZa7S|e7CgnYU?xUcqw=G!$fpsn~vsR~8U< zJo_ynK?=+;`-TF{QY13HD_lR{OAWia->N=~>zC7UGqsP4W@Bs(i0u^De>w&^vP8@d~hd=oV*XtEOfBlNO9ZX(Ig)Xx^ zJfPp-CoT3!Ig@<=%XY)KU9(-U*seBKDv;5hAs9_wCr^?UAPRYwb0%l=_FF}VNuMyr zla)0ss-)@(2vbE1jJihLh+Q^Y@?~dvRz&EMP=>;=9jq*%fHESQ83!fjj=iG=x$ii6 z>oJetf1kaRLynG)L5+cTbA82=fBF?){o=o}E`_vNS#Afam4Gb1{#~cg5FBJP=!%zz zB*Id(W%nlxyvg+}_rO>VWFh;)t!cJGT?Yydedr}YjjWEkt#Zs%^#RurtiO|3NzIBn zE%-1R$LfmY%JUp0liOxm(=i5;vgHB_|9?0d+MXiQy_#OAV!rLfVF z7w1=e^5jdNzkJEf^%WP-pBp8TLM@dcvdgcQpGL%Bn#V9r?*N_ zSS`bG?lWD#q~F^o^}Ttpl2D6*=HX^dxmlr9^OT9AlFj?jFE~6rVgJq@`ulh2`vuEI zkJOPYu(!A1yYIcrNB2%xogT8ezM%{whoWqor)cYeXe=_#K*d%>gqLyi|cRfNr` zMC3xLg`pN+tu}o2;uV{#HB!tVQfonnVhO0UBBOf(Jr+?*F*;jZ*=)kVzYN$r0^&!_VDu~l@X9mc~DG&sw$nGEGsde^FWs zJD!N686?{KpULPp!0e;}XrMY`4QkwQHkaDK%B`_&)<;(_;gSPO06V1 z(2-O#qa@fSQlBVec#tg|K&r75Bqa~y8j+iXzO-lEu2!7Ae91rFyU)W14|#O|9(PXm zIlEf%%U}GG%V*EIJUyd~1ERt>7P{1Nu)j}U?sNCWPMi+%)7}?w3XK{4G(RbeE(R=UHcL~Oko69TKmlxFShRav4xt24^X2rOUI`lo7 zyaZf7k7Mz02^Fifl7w!rrxcgHYRs_eGFP%0vrAE=LK1slDJvwafHMxM8Ny3S)Z*(X z3n?WJ*-GRrWOF&Q|KJ{f_&@zQ-~aB1^vM!7_PrTJwnO2A_uuD#UtRFk**W9|(haC? z(Ui<+UK2 z8=6zoZ{;lv_^atD7Q*HG!Z=vMT1hB9U8?l%8M2bboo1)-_nDR+NfRoPL;{TE76zcU z(Khd6BmuP8>@Ih*yJZ zXTud90`Me#(_jJS=k+S{Ki{-Fh%a^V#G?C7h6f?APbq^1pM z$MxA6+CO2ag?~8s2d>wb?Du;d?l0+6X1!T+y;*T}v*Knua{lTSubw|=dwI>(*=yEU z*K9TeWi%Rk^~}hvQy!9O`a?2BDg`6LU1lkfOQmXLZN?~*D&(%G-#=h+bj<$I35%mc zr#Dv0uw{FF4e1=snPIi^Qhuf+_lu5haX{KX;LeBd^5dWWl<&RsF3XgWBn;z79SSG= z2OQlw;brz%(gqZ5j*T0mZLVIw;+G$N#M=+<^WnV{QWd(cW2{Q4mCK>qBgE&@}@_*za6?Jkqck~ib3`|B<2hw3~NG@U{u0F)F_#n-u0)hAEmynHf zQM5CjlVxJ}`?z3khzNReyugsZZV;L889KMzw3p#)$_)sf;KmG$T8R+;X|RNOAetEt zyq)6rjr~mptzP{^+&G*p&&;Tv%OquxV)sv(#9&nelD3L1RZJ#|B(L=I=!$U|88%z?FR$6YKI81@n6HkHS?nLMcerFb3|u{Z#_H^hGOQRko3`Hy z%3^lSnZN@DbPvKdCUn-NiATkX5$a*uxhh=aG@;-`P{7ySPF zAF%IzK0iO_>8n?~di{c@pM6fh?ActLb9t(;wY)Axrko9ulN&^|$--gkzy9;5+#df@k6Q!4?eUvFdTs zp3z81>Q;a%BK=Gaikl&!v{sMV^G!j7oHEk&ru2j|mmE;fyerY|s2~uJCk>3aBGv%5 z%zw~Sd~Y*0!BUD*xm(sSJGC}YBn_cdR|=DcBHQ#o?_F$gQ-UfbO?>1k(|IxIGqqX$ znyLZHLJL(>8taB}vtWI8N?K$-*{pc_#b+EIAF){Oqt$5bNtM;j4P`rWb#ckn#W`sl z8MkYO&4yuR<&QL;vz4FnTjDjf5xOp$a+IM;@&t^^Sd^R+9sxp@Ouy*q5B52F_<+L) zkLiz&IeGAqlj9>Z03~?#g=3hyS7ZtW%M#gHg{{Fg6crR>HJdXrIKJAMk1`j zy#JH3RGk&jaDOCk5D4D1z4A(wQZuDfEFo5SV!Xz7b=2CZ%(XTnL4cb{ft={ts&PM= z1cfV~Ej+t{`9SLNPaXW}e0j9z|C%1MvnCzrO=O&%aPau9UFHU~Xnzh==S`cQs8c9I zpzS$|CyW7aeC#*(WaKpNkvEavyq``ulz4{tat`uk_74{^mQ&@;NT(*6T%(=9vt!I) z7s1Rh&=mgJ-_vlk4(|Z-cu$y^3ON_|im{WVQ`-)lleAPIJL9oqkkH-l-#qlqxiLRI zWH}hsK3D)T80`jcG_F(51sh9qpEs6@%r2!Zvliko?HQ9tzrC7PS|YXiU<)}W$E;m% zrWSt=Hxj6LinYj9f>5P+saZh>%rX-IRExcwB#0LCAH@Cdndg8z3=jq4?f^~Cnt0% zAvsa+9P!<^A8>Z{9>03~5r6mBf6G~|jKj!!wQ@RPN9q!N-&3n)t52fTVPqTzXZoqd z+IL;65EG1Db=daB%zm%z5RWb2TQig4!y{p2s!)vbx*w{QYy4bh=repJV}i<^>wrtSU=`! zRPNE(Q<~9Ayj><)AnxqIj2~4irC2GzDSw9$*HDb7PVl!Qxy>rAxW6)HCtIvl4$BgB_W!Vjuv!UEF^&2 zp0WHW@+4-sHWDs!B5{jgHiv~twg9)uJ z0Ex#~mMQ8?#p;<;i&Ok&8=~(^;@7HgmJw^F8k<>s-?q8d{^e zbbu$rF+scY*#6bA3(f7LKQlhFCEs!SRDfyz}@GhYG379{VnoTIn(@ zy3BHUUE72^QG z0G|jwXe0mtAOJ~3K~y#=9fpPG`l{Nz&TWANotp_CO-3Ym++cRi zj$t9>X8bL)TrqJ?orHK>6E3f(cc{Df0*~Fdy+#7$ON8aj9zNbxti_bvi#!>Of?Yuo z3g(uKP`8xDfM~3qB9n(z9As*827!I29+qRJ1C!@puzRJNEa!|^E&v!nJ5T6SNmQik zsGBw0Qq6Fh5~3q@y+(7QTPzse>uW}FO!iA=SZzpI7>5np)rQr2&1zfO!*ae@*;9+v z9~CZc*4$iOGj0dQ(To!P(ILwR_j&h&4|(_KgrlXEYpumxw0*zNy$1{4x_8W2D}Q}< z&SJA+D1|aw41d>Kf>`px=bVtVuwAd&Twhbhtr@DNlDd(y9j&rJ$N(3$DVY~L%CE{e zGSOWu|AT>Aqx_Gfy*r6G`HBaW`@~BtJiBT4f*!-G_+Qw{;ZnVlEiO9U(1O4PtZJ_cL+BOIzlO&tZ_1>H39*T=+95k|%P+ zLm8*M38yF*|M<0Jq0) z`uHZb3ud}zRix~b^4RqMltxU6&A#6lvp6Th#%jjv$nTevChUI#kW&&wyneOA36X%1 zmT_Lq@@_hrm5Q;Q&}d`UOPVe#5}Oas=+vFhceUq9lWnw8l|~^8pkfqw+o0#!%>y(v z=C*r#o1tN@U)OdC^Ptx1z%~?U^CBl2T~_T0)EjG?ca%_zjWZHR`MLoJC06{*$$&Ws}h-tQLDU164qCjsE&M923~yj z1nH8M%380vKD%Olam99ZLm9V}&BjXml|mi1rT~}f8L1tF7f%f6r4J3v+q|$`4LSku zTFroa(_A_;F*(DZEW6kst16l z0D-QQsWx=E3*Kh*=sD*eXCyel32OYVWYKSsI%dR~ltag9v37*U$`N@Zm7veV7Rx^a zoNqdb9S=?*ERyoML7>Ts9c#j@yD~G7L_2Yb&THMvvy$BE*X%xGtZ~&T8DhwrxOc=5RDXRnzm zl?%IJ4CBsb)7VY^$`nhM>L;|ktqc36z$^jj*_(PW(Fs8Ev4PKBQj5 z(Mq8eY9w)!NeMAjOiA=DuUxDC1^;Bn*9rj%H}q(LuRm!)EkSYtq*5@;0%G3(Uj1ww)GTF1BvtX*x+51w!!FN#3JMN(S+hf+S5UMW~uYkt{iDC6OdoDY;5X zqNJ>(C9uM)B2ULRNT1u|_W11|w+4XQ<2QZC8^7=9XiZJO0TvGaU5@7LdbE-qlB+67 zYfX}~m}*!=#i|8Ps*=WLs)+ezBj!JZyGSC^X6Kwpoh2NYRcUTZ1W{PuAu!nho?cWze~=WxC%)GO*1ptlCx8Krg~_Z=Z!$s@FPRE*FgBn$2o3y14&W z#|S5=lu|qiA7tsAlA5hlo+OGJFoYBgRmNdNOJ!6gr4C8ilKiQX_x4yG9`pF!cX|8p zn4Fa2RThS7UbIEd+`IRHuMQ7cy?$-q`{rKM+AqbEEFtu{gEAUea_?ppuS`%)NmZ>D z0-#nCn+n_Q7VSGWS2vW^mVU8d7zQK>o0~OtETohe%0Ss}soM?IVrBcr(Ubg*h?nCt zZ+@i~_xgl&M3v%*$r6Qml0MZ2;0yje-j2@$jT{fIZ~>GO0C|evuc*aG0`Bg2uq&=R zdHbU7MXGIqN7A^8DYrG|w=0~}l9)}#uc4|~V?LX|$>TZ`D!lo53{?PDcUw1*@8BqT zEbe?+@BHq=Boa#U4EQEjvgh7mr6tJ=oi&BW8)^UFfIKuH97Y70bzt6~IcSb{+xNi$ zP-m99?XHkb5=kAjLP&*TVHghn70x3t^@$_4_X++{D|>sAbB=MIy=9;{Fz0l$!lo|SX;A! zfcy_Lx+cF*qdM6bg<(Rb+v}`-Y1!B-k@qF=i-MP+tL`a=GRk#??V#1j#1o`YK8=@Y83dC(1V(Lj`v6G?^5YDFm~?_Ox-XV+Ie|Kf9g^5Y-#{=K^#?e}abe06!oS6_a~cy+~4 zikJBX>6YAi_>jkU?<1;=rP7hey^Ym&G(+mDjGSFv+Sq&Y#gsCOqdiU@-si3FeV@Ph zcYnddqkU>AjJe~}Pru|B|L_s7zWSVk*;dxqmyn9bjDynvjV+cyBc#H|d`cji8apnM z&!yB+P^*TJ%*s~B(bs^mU5^aI$VtD)W~|gw$dah4^pZ*H??!~wbiF730>~y!3n=5i2w|`Kng)===Px;X{d%m0}ZAs~XBs@wHSf^dJlYzIO&=K~)*H z8`F_&;hCnlv#_hnBU^h_;@sKl2}6s-o=0nM`WZ$}H&lwycT3kvAQ>HHTK?1OCixvK zt&_Tns6xs}Aqh!THIb?aWG_sVwp-HRm5%=a42g1`9{&aH`+RDtp;5^R4!{FV%mc~7gYepS{SVk8+h752oOKH z(ljND=hkVnQdc0uiarJQVhTnz4@}TB$Qh>=ig`&=CV4`}lrudU74uf) z&XiEutQl&t#7xytP~RuI<$}HC9(l23fB%Sa+|n%PjA>O{G@xZvsQQ{G-K>3d}yszvP#H_m8B_)+qnufEEMo!Q8NS zJEAFZbvDxX?wu)>VH`-R)RZa1NEx>Pr9fK0R`#$ArUVzKg?cvs>VJo~K0r90D?zI? zDk(l6?L9(c4A|s01x?L-)<9B(5g?OGTw^AydyyOrID%@4#sZ+JQ#a>eMJ>^#O}~n! z6o2^osFN}k&xJEkT;bFz)B1~8Pj^SPc+gm+f&Sh!2sAJi=S4#v~Yy@jZ88h}1PY70eh{McyQvEI@Qq`z?=RW}U8Gr5B{H2^wY;N?-;N9`Ke z1*kqIv#vYf)%JG~fdUA(gn;7X8DluRPXpxQ#sqb~ifV+TPcqp?b=N@Q*ES5^=oZ@M zU5tTXVFEGVb}+)+fWYJx-_cri_H*{G=0=k?w`Yc`NYK~J8v4fF-%yR)pIXuBfryfS z&D!CEr%WuGsG0z_S(?#}$>5Qq&&~{z)WDOvr6fu6>+F8^&TMVRXA&>hD0I`%MAyV* zwn#8Es<8v&-PLUGvKGjdS}oa}xRFvzH4A^T@TxitST_Ak)k=1%O&JO#A$L}xWhetW z7H(8wJ2I{}T)cS6^Jic1;L%&W_rZ6Nl==AMPk8?E$LMBF+1Q@5zjuIkiG#yK_Od_@ zn!GZO1*zeE7tU8JUcGu@b?6aN>PababacYK$B+2I55LblhX))jEQBm~nS0;=fDhh! z#NU7RYyRs0_&=@eAfp+&hXj2gRogo)Hs6GX8GPKYojrewBr9|42J)0TXJ3>MgC^sX zmx&z)F0U@Q+N^nSuy5rEs~L$BUal}z4`mo9R!~x?GI{RR^1NsgiU_$>a;!z4n_=9u zZ6eB$I^)C>O6CMQHwv{CGE?xJZIXmGkI|`2vG_C8(NjgYjmGC<6Gox0#F}f;f+$U} zV+8X$fKAq^_qE0UyRMTGx!)s+mlO8I5^@T48E&RgPm)n>MyV!6M5?C_)RK~|V{z}l z3`WM2dVp-tNsDg~5#OTY+i0}7J>EEO%K+XUzv*K#!`i>}<_X0@;RUQ3z|um_a#cF_ zjU<6AYUyv(%&k>a%{c2?pok_lV}fXS=%NP!A>wn_m`!<%asz(e90klk!QA2If9?EGY}Gy5T4ai=jlLv{ zr&kM?Xd8D^2Grs$m0$wk6ms9f6;u;lzhM9FT@LO&;O;w*IXXV!?%g{K9`Bg@p7V=y z&R@Oc_0uOToGM?&3^F=!G~%;uW$W)!D=FueAg`9hdc8(H z*`bIsREyEKZ2JZAEdDy0fy4|YYBRtS>#0JN?6VScG0SQL{pv_eiz_pVQ9-?|RM2}3 z4^;Qw6OI&%<($W!#DonUY^I2{--B))b5jGf2r5(Gz0Hpdg#ySb_R(mwlxZN2#v2QRIjd+Z7Bvwof)bHv; z4Sf5(JeR4<7=I>cUi+ZrM|*;K<4wlA(Wd_%BOy(QxbY-SzblciB6Ru*)P_+Tkl!qO~dIbIHXa(>0EfW|OFi6JRm~ z%u+Y(ifM0WZXB6j)O25FU(dug!gRA%%8;4V*Cw5(Lz%^e#J5xYLgaLjS*POFv{V58 z{wB(^PJ2;I7(;NA(ao<)PCcpK_xbdUoUt+QQS;bKHTkR__aBxY>tm%#_3Y=K8#zNePTSPFe_#_H#nS8Q+Atk)Zc zv7lm(g8t}$qkH#w@9|?!_V$saY}N9#EK}nByC>BAT|WEtV}AMch3(xr0~IO8oXEMO zGBN8SA#qBIGBiV|gQNj+E_|%d=OUu5Nhe|_=Jht&yY<{X zS_f(!-B{~kjdgdfCYNVz5{5_L!Esen#>9n!`W#iyYtV%Z4;BM957e8B&tqLi`M;SU z^Qbp7ZqzbN!ZQre#L`KG>2h~%M1N`5PEFW+l-WAf5IR*o?Sh2^lGEg^f{C^iMgswn z$uws+l4PouN#2xFMXRKwDQl@oK}sf-#0YDduCFlZLz5?fyTT*dKgC)x<~uBIeu)@C9R-dq8;jRSB4 zK<7$Anss>l3}%Fy;?D@SFFx1xO(-9 z)%7LiX3cPO;|u`v#+c{Je~)*Oq|p%7b5B@BD35Kd6^c^p=%8P%^j{5%xPyN8`cq9& zsg8M)4yzEHotCmKXLDBiigHPZJJ#p*vrX^#|%%8(Y$!=cau30!W{rO zg~IBc5oZ5f(T@2NB2T?v^-U3%1h=6zrMb@fqTb)?44BT1jKO-Sg?5ji{TuUWcC8I; zdrz%h2f6C(0T;7@6(^uB({;$qaG*P{z|M`&zCmrBzw7q(j;MD4CG&Hny|ZY$jego` z34Gp8hOyav_7~N<5LTDe{xHwJgJtmtRUh0i>V=2ZQifDF7Ni!6V}C22k&TuE0H@&3 zm=2LlHc4{hxmkO(v2=n}U`bs?6v+-)i&q^t-XR%w$u$@eVa$ z;pcyY{&>rNzt3X1a07E?td-}lUhw+qSJcghy4_NW?^$g<#Qba0*h`nr@}j7hc@>|A zGhHD>u#*aW4r_DJhw!MC!x_+Y8wm5J-O?xk8y^2>tb`2*$-uOKPM2jQ?f=MN+NLR^uL8^&P46h+-6>YF^#jdkJ z{cMfOj;@R<>RAGt&hL9fa?gbXAZZd^8vP94oSGtsc!`_j+v8}l;PVF$_-cQN zoI{rr!)W8A0gNR<>L7RY2L~M9yU+6EgyVY;x%==TfBfU$=eqqf)-PYX(p4$rz;?A|y3JoV+FaPEt)HkW5W*?4-3N2XLKn2r*V}o1-?`0VevaWl zmkYS}%qYC`l9r5bK8BVPBY=Ys5uWKh zd1!i?!UX2A{8^wB8|SP_c|(Na<2=dW-FMsC^8PgO-!_Kn^A-Ud-+j{@k=>sSAcef0 zcdTVwr%g*Yn>M4sRMv&IE^O^ZmKNW>yyL+bn+zG!)`Y}96(j_&un}R$I7qZTPunt# z0Z|kki@&4fd!BpyRoV+`9{lPLCm!ygbw)`rk9}iAB(beo-84BUB&Cu`$-~36Qbs|N z$HI%W{4HJ! z`8l<07;aWj@ckak!=l*!+6iI;KV!q=m^VYcFN>No{{JcU8mO9|6`MtE zUe}$EiTFz2*8;fDe>RO?XS7`ZEP$0v^tCd#nL84x9vkOr;LtW$xDw@>eh%8Fjo(-c zDR=B=q4Np~lC3OX^^$TaTSoscY+2^aAOGNcJh*>{|NK|~g`pG{>kaF=0TG5Wve}MYT&%di-;+{D zt;$fWrtrmf!}F^Po__Hq!^IV4v!VorD$8fV^d+DW;s!~g7$?a+>2J%a> zxczZ3<+N6)rM+b>Gr;YyYaFIsQq<}HSoZ!_4$osZTO5CJ<4}ZXR96ViSLzDU{9gXf z6sPzH?(lisSOODBZqwaY;Y15>3&*B}I)&JkwblW@NlQ-XK+W{W`Sm(AG(k+q)3flG z0779X@cZce(it5zo<;&ZF@dRFuf1K6+w5EDIghiIy7I%s{IkjR_FuNtq+y=sVK9=t(`Kp+=V@ ztb>WVEz?*V6Tp<`z=&j1o>giyK1FB}3N=~Qbz}ZGE_QjG5^dgPbtn}5Y@RwBvng_Z z`gmuvk*Qr`9?lFfK~`zw5YII&qxm#!dq=e0Y+LGcIt;WLyF`Ey2iz^+inf~txC#bE zYttuh>|YWci_iUmcAmA3fwoYdhIurWsuCF}!vIY6xPQf%U%o?3_Q3i5f-bH8j_t)H ze{PGtOQ?*#m!@gGqSWe1d}9A}J3=I0BPiowp5_Qq6RRkq3esh_B2}am3In-x~l63mu%N-1dH)kl+-QR-`k__Efhf`8HPYkiLeU&mvrEc2xb4-#ZgSsI zML9S*ra!tze{{nB-8*z$CJBt=NZqdKUcX{EJGFjauNXEf-&>8N*!JQ&P_~632{)&e zyjoB$uDMz~LsCYvt(0Lqprw$;fz8zwHNwnFC6(eb#PkMRlQCBnyW{BVKnRUUzP9pW zzG~YathmcGhbGV+x0u+65q2o5BzL3~H3!K!j?@~CkeH9DEpV0EJoCvLuc_`V@}|>; zilca;3Ufl3Tqx~*Y86PH8%mwY=j$fnRcH*5jIQ@~ z2D0=j9J`Zgc)-S+nQmL0bYfZOA@eKb|oqk%>DR>RFsaS<^aG zLL1;wkHw9SMX+bY<5_=_SPf~5aW;=qODKoclCN&1?~;`PDy6V4P?CA}JNH^?f-)MQ z9?HmSwPM(A+B1b}Z0%d(r_?W4?jO(}9`f+Lclq~!{-=EB@X%`sTN1-QWxBp&+4bBx zI_CW9nx9=?v%OhUwbBWog{NPA$&26rJ(hcS$q6=ESPz9So`1!!zxa%2&z|!7*PpPt zyztolO5JSzeZepeNEOCzL%C8?cBQ$FO#v>oqFb+3tqQduS}C4k-&h*jy+t3j)adb*)UM%pMaa&nUF}N69*N z`V)=CSI$|tljo%H$_8Vx>H|5kK0jkv->^Nq z;C#8yowpzI@{7;ds&IIG%;xHf&5KuTE-%?`HWXEIpDBA=YB5HchynhbjP+8smcjqJ zjJ$gNnz~*=85y=)E77N(4L>Vg*VFGE(La31AN|>%@q_QYOYSq9n=R|@7P9jE=~I63 zH-F9fr=M7EnKH~m0mA!S9h}0r*-*!UZd^jQWuuoMiN4Q_W3ke+9xkEy*mVgRv4vM` z|2HFGK^1bH7SJR?LMBg+lqTOjPe2P9Bel6R*HJ7%2Rny?jk6np#%cyq0ZUqlhwAAp zkTc|@;Cn_!G}|0Zg_i8ksR}A(XRX^_=4(#XSvPK!a$|4K9VzD~YnjR6$WLRA3^xpG zk|f1QTyeTD4@>e;M2*-WsoKx6lFA9PKKpuptZ&(&|NJSp$G_y`)&OvO{5FqCFLDeb zzJIWXL0sdTTHJu?PkxZA=L(D2s*4x4nnIgjGSX`^3UBs~`r>m)7sHX6W zcw(&JthsXU5y3&PRM&pzG}NF|JMyrHXq%HMUa}KJ9HU?xPZ^8FuzF_v02yc$hjqk| z1RW!JkSk&8;LbN;QSmAPlfGJ;$Jed%F*3o`(>SNnN>aI!Dqa?_R?j3~D#N&?S7mj1 z#^+C-aPPZ6;0ViVoO1T;_GbL3RT;+7yy3Mt5HMB%;K`LTsWbY2cYMr`zV{*DKR%*M z8ORL9l+Ml=bL0$Z9Qo-7@AJi1Pq=*X8Y*ndKuYlH(~tR&f3@US4<9m)%4)r0eRIRb z>r+mjJ!5@w!EkZT>h&3vfjVp%)*HG`&}v!tB_%8epPJj!CK9Sfx36O{>SR@m>vXVQ zYj_Z}QFOy&9*U5~%<67texHk$sL#JMEtsmcdD(ng_^i|htU;Y+JVP?ku5+~``X8{2 z*WrEfTms@AnlK`%KXY6Z$=wLR7c*aVqO8v!$+f?)g+chwR&H-X@&szrhN|PD~2(8O}Gu$dVRU;TX7 zgTEF6kf$(=gu0P(W&nWZbtZ{Rr|L`B8cm``qjgykMuQ|_SaBd2H*RS@y()ufi{qC@ z+ZQrA%NZapZ=3}+^X5k}2xbzedC#f|aIm!yFDIINjd_NM#< z)4Ogl{@S`VrEr;_Kbthc_Wgf5EarU*_E!f9s_Z0RH8CHPOs3e0+5M3j&#dC*aAdku zGYZ!>?m?lREjwCe2MLd=zh?(yEe0B2y))}q0HJ0mL0Y1?SQW{=>+R5qRn}ml4`g*v zC^ChOD4=6SvP43A15dGki?wfw1Wgtu&j%vaD-DRiC>D3G8Lh@T5G+%E1uN^TLP?37 z5)~oUjC38Pj_7t^Q1KmW&n zB>moxd9b%f+Usmy7DbEl`Sa(z`1}jX%?+EIYsz*@%0kYSQb1B-@9>D_@iD*u$A84X z|C2xDe&3Vxg3WeIsn9PwuHJi(%D~SqF1c9`NZPnz#ui9b2k1=usAL$o8yG8HpCBdb zn5pB)FvR>ez&cbV7Yz-}3G9h(0L=H>+vC5#W3Hm_YKJ&0th5iYe5i-8w4I7pYZN`-{I4b{)yaYhB8vuTejmFzxvC+;@5k z-n%wgk{nlJ$2~G{J-Vj5XE4Bk07wi7E+sC-4_etSC7Fz7(odI3A7m@Z3@d^p$R+V2 z9)o#xcXf5uy_w;z4}RPuZUbC?!H#jjO0${1b#Fc*BRnGfxF2^vZMgsRCGKC}!TS!e z9mh9sfNoH6?8gmJHYoaQ6pv(h^x%6BBY@{PQDI4?NBAzG0Q3C| zjKuvVg@g&vY-j&_0RFgm@~_g%H^wOkGleS^7Ap227?fAi@>Ac9a6@qq#M1DGCmRr640}^4uEOA#Qn} zGx>T;p3dZ$f^o)DnLdbkO~(C~!-Jwf^?uv(33jDI+KmA|-4_>{v#lQLRL;U_%-^Zmk9F_%dtmDT&`x#z+{4rjC z_IV_h^$t5p>~)A-0qfNjp1k)SzWd>~@%-ulxZ>DP0iLx%`i^&&1HSRqZ{csAKEd|# z68(4wI|(Z@fb+_sopZ2h0BHfNb)2k2o1)7Wp#UOKjmifK2Nna+r-~cVw#Xx^fbC;{ z$aNc0wP*oo;Eb@3GIlov3sDT+5IGPuEnzuhY1k1*)>(B3yiK#gxkelJ&EA=0Hw4X@ zKsfgo@yv+AiZ&A8#X4Z{3~&@w_-2Jw@*c*H$UUE0VpS)isx{4(hEWPLevEgIlGG4U zQH_wm$WW~wB&Z-Dd27~A+5~#qA!)$O72->Hd|BK5cudC^#Q-=*C6CAN>hYV@s{G!7 zVtD}o4i4D`wg4b&xyu5BV2#wo5#gVf;_#LSJ3tVu^&qWkC5+1W*9vqMgcpG}2NC7~ zXv{!MFRIUtF3?I%WePrxZzttxdgYA2cNNw>PH#~F$ng3*y6x314k}RT*`=}t@8v}r zI%F~u^6_zjoq2&LC6TGAQ}HV2F{EOME$_{HS|$X9N4%gJ_Pzt#hW>EG_WCtG{_JC% zzWpIC7moyY)O7cK$IH80ym@ttoweFtT*H?J&>IyE3-8!0UB^X>Z zyjWd;)$o;`mD*EcsfEuZ23v|-Q&w>%K*L=8Vvz6s{24e8Fz0U9+U(}1&gw64F4zuH7V?82rJt(WoplU7(jQPB+0mu z2z!|3&Ol(ObKk;FZvn2jMkX0e06iZ*edpt01?a24>KTI;pPBu`29hzQbiUD8QbqyN zv$M}K%m{)i-v^(-eO`|#9Dp(HSyn6Ku9cq!3Ebnpjqe^_{=APu$pnIiu_{3)_0~hV>>jeHj#8SbGe^B}#%&`h_5ySXK$p=fIqsQwQd-jd zr;raBV&N#_c`+y|l8JaRm$|tVU@e35jkuH-Yb0NPdS1zpk8!Rww|213*N+@a<)=Rb3|)LA~=xaQ>fI|*|HfGj0on6=AD z`DS`zhb(anv$nlBOOg^LN(U@=YQ()V{)|tI#kTXg0J=aV!VMH!L_1)EN`viT zxOFk8b};W6bF1_S4Ors4ZQIfJ6{;KB#foKJVdmJukO5l5y+^{Rt;UV$| z{M2@Q{G*@X=J_)`|H^xK{_eZ@?A1&B{a^kS_Rn8oyT8Zwa6)U2-3-zd%VC8^fjC^> z+~DTo8ch~BqNLxV4LccMi!?M<9Imd>E)Nk4?*^Jc;MTd1E5rpIEXTMgx-q%pLeI4d z4p*00)(aRMSCizMaUU}$i3>u}p*O_tavZF1C<+eIS0!CkR zZJaN~c9_^mLU|TxXl<=(_ZYu$Q<0IUYx zI`sDx_<6LVD{cjQ^|8^AQF=(@vr{pb2#pBFp@#uuahPvty~7`lc>VcHwCfwV06PqO4-bY5ux}j>!JE?w zcQ0Sz;qFZ^0D6yDdP^ldk_KuEQ_b2M4l1~44I7mQ(WDo5EN#KT8%_drmuNRanOGLZ z>EVR?;|AY0*w(|-uMK@a1@+Vb*bcLfemWsi@B-fV@S0lGgZA#&yOX^T{b^K)-6JVr zdejRecgASiOnXn|J(cGKr0I>1an8TY*)NuY0zjt17f!50V?u5DgK=XChLNBHqaENwlK+#>mkB?e0j<$z1=M^1 z*E6FSuRX(MGQ9Pe&zV6F+dF`8fD#n~@1oy37NjTEYgN#^PZ}2_GT9f{Y-9?^2nA9J zz?^GJ>b?Q`<82~|8CM^1G#V+=L8^RFRjTKt>8j9+P6L4>7y;2%D)URe!GPD=93?6V z069L9`8(yAl}Maryi%qS3;<_hx#kGKrjDNB0UqO@VO=D@@ZLb;)=m$x$ZC3rYhoj)GGppEqyfQLiaaRk<@ zU|TPt?=}pb-_21)f;^U0kh~=XDPuKGz(a8><1$887DZ6wnkx9HsmW757CDQYuOprB zBVG>Y+GTA@QX8RAu}Ug@Bz@aM3&C39y}YK85omZ?+#nuVgZpWNEgLSj6Hag5KvmGU9lb?eEQu=+kkyX zKkdxSzXNiFZ$YuQy`y`Ndzqu}(GK5xQeZ`*6UJC{LJgFHp7dy^uOXQR@tIx;PY?b8dI{zV^iVM`Z>LB5 z>v!?NM#+Ds{u!D&>ir`&dY%e0?lVcT;QaD@_fkId`vhGWUS&hDOGN_N8D*%hO|lKY z5E=Iye>3(tQ`FbFUTXv=8w4aBiDwe?aW}@*>eS$TUdgo#ASg0>`!Ok&3HrT&Tmnp$ zm?tey)+scAAX#FXqe-Ow)Jn1z?P;3S*QCTUo;*8F5T4o0)J+3~JD?U6V{@Urgv@lt z!a5L{+W~?ovSyrsL1Nxy!mwmHSWXL$aoUEk2zrKU@V8*phG8agLoo|%^xUX%NpWIC`&K~fSGPu`;1^J&zZ6~$IBB4Oa3<2+ceyaSYxTVmu)Kp z!4&Qib>>G*eZ270xdNcV2MT?~9y90hU<_O4k*GeBke>+QNcaVSG;9@)XHr(of|>`w zyVhKZ8`6-F-dKh+Ib;5Vwjb+}8*!DARVPL-KiPE^~jV4d~YPY+G8whM?ZsK6qLc1bHiiSQaQM8*Z{qR_Si zsyJL-0&Rs{T;cieeGO0Ed4}#gj(02e(>=D^S3$2&V4QX=5%eyAIhHA&KMXlx)KOMu zFn25&0_6b2kbe2R(Cg+YWU&vH0o@$l^6z9hNQ4!*!O2jFC#OD^6P)^vHO^g+M27I7 z{A-!tA(ixU$aA(+%BV-(%cH;7wkEL8>BHF{7mGS1efEU@A+xRmX$lb$S+Z~7A#%D$ zx|r6{GUDOi0`gaRr?FjqS&lDbn;(zq_@Wp9^3R|0c>E3=v)Yu00>D=R>44)EfNS8u z+*y8tU=0mA$#<6;QjWm;s%o<6MY8eE@pyIE6O~L?MjTp@k=I zMY%^kmGlHNq_lZ@Xtk1UDZ!%kUdlU>V!&M{G_x)HvqSq1wWMwcj;9Co1^D>x4IZ`= zcH8m#?hZfthyRS@?F;m6!=4%Uw_c$ZkrldQzrTlV_xS9ykMZM|pX288>)3ZgR za;qm5C_S@D>o)UACV`}KrZ=agH@$G?s5;)W+*Rzq4Ff@CKF(K6B@9!$5+_Z%K=yAb zTqrpfih@jF43ikvHGGHqH@jIJi)7FNf9PQSZ-U6-pdEx60;d421cU;5(ns49ggfH5 zCJFMUcA8h>s|5Xd?>zGRH1x~{0Ht!N%qlKw0oV}+FO{J8hv7h3GR4mCxeTL)id5Ep z6_mGBYm8%Tl|Wh3o64oq2p-dTJ*4H1Qrf0IR+ZRVi^v2U#sznn--YYFeFrp7ti+_kzBE=Oy&4E>VgCW2~ek5 zSJdP5dQbC!{aZ4UKh^#*WH7meRW;_zkv39^N>f+JuYQghetOJzNB`= z+X&YVQtPuV$nl7Y4{#6h0&+vvKx1PWuq{}2kN`*VHjJ6hL8c+XY*=rEKn$X+juY}8 zp-ob(193is8TldH&&3$Rqp`0_8vG>^4?egc%BTpAp}(`WDC`uYl6?`RtLh(2?82Na40 zg6$alrhBk!R1o>{EEqe^aT5TtG>9_)kM%IdOT)#JC(!F_^yPqKcU)axz)vSQ6dU*A z)>>3+pkX}bwuiCZC)sA67>E~hr+AV%$wfmhCFk(OvYPJ|n*_Z(0$GBok&+)q00+z> z{||M5Vq7KzfT1Jm3m|~`9`X5z`-{aw=+a@ZDGxx(6Za~v|J?`gMt};Xs5z^#cPM0# zFcE91Xvk-rLNl{M)u19K5(|7Y0M?+Z0S^br)dG3-`b(b+;LF(N$74Fa2m?S0iToGO zdOUs?j-kc8_3y`kKL_;Y9jNXQ>S*E%v^g3&U<-UvG*}pS8}~`^AiyD08;daSRH%JX zt6PVFc`9rH-m12-c__`=c)pYtnQ>(Uaxk^06-_^3PWmDlHDJddPe(V`)WV zv+g~t)uHN9%QONx6I2X2HE1cyC6Mfd&=B~lu0b_sXu$~hmr27-`ex~Ys2aOk+ixhp zEZyXNhpPg%L*39%M?Ac~#oe3Nc(5J!ukZ19Kl}+^-`?W>{vM~h*LeBS&+%}3hle+> z(N9}|1T%P#ssZkX?kDUIN1W~+@cP9I{GWgMJ$!uo0>A&25AgfX-^J2`&baLz$IZ}N z$D4h_-~Hkjc>URDIK6(2f=R{!UH9MM;4Z&XsTbXsxCsOr2~(GD=y#D|3*l#Ju>kTYJHmX(^g*U;Y3LJ^s?4AS=R*1Mn)FHRk8w5e zSTl1TioiMmWJ$j)>q!Gb-YeT9!nJ7HTUjC?7zoS-&=`u+f;r$2D5)P|qzs@RHp(o) zD-#<@XowGiaO;35x-NiNC>UfVgz<8LNSL^~?a(Ih9WW&$OJg1dQ-RC|&bsM9ECR zvI4E4T^?|K^8~7jH*fB-z1ea5i(g^8eT73?v1hVFRk)?4%&3Np5FD>L<47{0$XNAg z^2w<)=1+<{7rbO&r96$<2xJZ#k?GycV0}BU$l;T)bGpW2#YMAbH;qN^Os;8cR|_UU zS|z8snNFWjnFOsJSoMJ8n`6wiK|R*!2xm-=r2@@FOcd@av6@DK7%0?5%%Pk1);qNK z=(@i;+v&bE$6G7U2|FUKnQo9zb2kZXtU4Kdr?803ZNKL_t)=_4W{| zNTYAxb3chHSeYr$RpBlfxfMH!h&V*U#?N&4PVF+R1|9H5#d=mgBK9xhXeUK@xPr#t zmI`w!h+aTGyhOPZo_PS3u^;In&SY@8&!{syeJW}MX$1V`JZ*9>PRDi3=gyh2S0KHpx#$oyxD%*aJoNYTW|5RAN^;vrZ^st`0S&P zaJqYg;n69bl}!z#=@L_sB+V z262LaBe}m%h5*tf98}&sz0fwc=VKm3Qfs|rFVO{`zKU0WI0vCLGgd< zn1D)l?f5PJ7`WWe=+-{nBaadHKh4EFr9k7D;~8I`+Nn(Eo*4(&-{srn?Uf6JO82+N9aihW2SwTo+zAnn}FchOu zn1Il>9sL-|XJ5T~i5GXT@$AVBUfsRHehP~Fw(W2@o?czx(>Hf`xPL(3V{eNlrgbLw zgplur?;Y)KFaYba;QHnUaK-D}H@MLiVjXv%eTwb&7H#jbUv>+_Gsh`Q|K`MsUd*tb z+%SB|865{PUco4-H6ybM0vzw$Hf*|{QcXrnB)?4^A>_t-c{9c$TYD3W?WHvqfLJ7m zjy=vu5mG?*TIM+3m)@!LG)zwn(Hp!yEncYX%o4&4Ab zAei}*AzzLKP22@7*a8vII#X=nNwN=f{JB>!Ht1}E5cyR38{}4yyV9(=CDBb#sn_Z0 z4M0V;Qh?!k$RtU?;2=+HWPu!qdoO@cN}F@jr3U4|R9AU)qgiC%O#nJ^OAE7=GMo$q zIGpvC%jl7)NU~l$BjKWWF@O#h|3Wu|Z#(vV!*V>~qaXYoKKaLA;_AsY)H`lJeZd&~ z2kZ|gzzyDaZjAB1@v=di?z_QHC&)itqpJ z53p|!xV^i@-Nzr}#V>z}j=pd3zJ=0n;rWk@{T&r{U^X)RSInQ4f*aSR z2Vs^YCyT)Anu@h$^0Po7PBF5PnVb~QOvIHU;Fih*JqrXY1(rEB>8&h@QN?e|^j-FwBoG)=V5nU< zyAR$vulk7}qLwv^Ql6xonih4Q6bMala^^Xorny!>1`^D5C8K&~EC~!Cp2IU61C$vP z^I36!MEHOPsLyid)ZYWRD>MA3L7+tgqMBJSb|MVGNbe72UB$wHNd|+mJv#jzZDjQg zjCrpRg72|5j8!Anwyp_2N!NBq)1V={JL{|mXxE96(mfJ&CSyPd7CIMdZ6Q;g{nY#D zL~XIIWp0dA?M2D5b`-!)`N?sJ5Cd?{3^`Tu{^#-P6v}DIj9!=+R_UBhL)-u#GL^3z zy*D2zig_;|mrlTV+7Om#m7sSC);7q>^!c?l%eS2soG>b1pCiMzlcJ*aj}S;3aSe48kKzZ9+ZCRuufx80>rLNo~vPy zU?mybfrazx^yU`7`q@9?$KU=Cm$xtQqo4d3x1W59bva=k*DgU@7PP|xSyng%dbq&h>Kd0%pP^k{V|{Xg{dk0*9&oyi>O8h} z=(0q9hK{hLiJe^qTN7%F9^msK=eLJ*Ng6*9K`z?4x;Q8ujZn*((AXBti_e zTgJ?UK|lrAy)}n!&N9~>H~@I#khQ^1Z}s4pSxfJAMtB~K7|Mb<=tyjv~EB%8U&W`*6bVX{sHKQe*b{|)dJfM$NN)& z95M9Xp&q64)KH!RU4jmo6${{q%>2iD+5 zKL6FHc>Veob~@tpaEwHM?&w=2`HSqn4(mIdi3d?(02T=d)4M>*gWHf1%gO+0R7vf| zhC&|req5glNl{U~G}Y+psVs%fi3aD%LgPajs@w;d&vR3uCKtNCW1_7DyiTC*^~@5! z@@9vg6*`I)?O6)I4eCD6mVAQ&J_cAwIh}Q=ncO)|v)N7s>R~fKXcFPkIqcIy<~%jQ z{}eMl<^l>hMOdl~kS8(6G9Eb-8wz7r#ZmF_nLrdsDWdoIQ{-XTsY_E)P298PN^F<_7U;^!AFG%fi8DM7#0Qc|?cL%yUnn%pNOT@D`1NIhKwapwxH@j0No#71b(SC7Z&JC%t z%N&g<&rOEM+{+U>05Y*Y0pkSBOE>3Oa!$@6B+CEI`u)@~W8%;%;gl!HSclKn*|$K@ zOv#s&0kjntmj_(E^BhmU{tbNRPyPg7dG9@(e8*>>{|dkSf#c<`K7p(as~&*OU|X;U zd{;8s1Y!|>k?KpVb78d8dHgA8!@=_Q;>~Xg9DAxBVC;aYRL)ZHIYh$Op;@ z6-H5zp#n%I%>-azvOgI!T#91pkq;ncF2%6cdd^}|w6z5-HO!^R@T$@po!12`z{&m+ zcZGBpS5xm0bZtO~1L6w71}uPV4!Ly5(xIQe-Em)z<84*u@%WM+j|PCp%rGFdGN;NCUi;Xcs)lwdNcpxEb4jH-J>n8~Fdqu36O4i$%1~GYFcVm}piOqic7H_Q4Xbzf)_`L}H;3&( ztCt1XPaBX)8Qp`PFG1Z5Ak30ty+f>H-%hxHeFy*SbA0~?KfwK|VBPX1}rYq-ru$ zBk8rE(mTalS3{F3oUD?bYW8SP_DRv4Wm5h_m!2DT=0&gBQd21zFw;~TSSdRzb;8k( z-*ix`t6QaFHv_T)Qk=0KkW6(>>g4Qq)Dj?Xy-&VF+-C&RD9d7IyncGMh2`v8+Oo(@ zs_O{2RcR0)KyS1x6z!j%7a7WQc=coDY67%2u301ucdaF(f!=?e{>wHh(6mj-@Yq>o z5>x?IT45m(V{8Ot#(V(YJu>PmGj%({7+`>y6!kyq&pUPt5Z(doT)d$)IB~sFmx%Ia z*7xdLWb`*d{UkSvSguq;uIKFdxl!~qx)GSxeBgPt9P>SrWl&Wvz^Oz=M*@VrM{XmM z@|XALhs2*L=VvPNTLuHq=Z3|tVz19)__NK(_nhuI%|VG}HD6}xKnfIyzMS82|BAVw zwf2o2aiVLRRlCFoTdcs7@Il7w1Taa4RjyB?PXr(>+<={){M^?PzJ`XL*DZ9$w zLc8*+m7McHFq|$_3_U6xnHUs3+7z`V;S8n92>mhpat=*xOC_;%%C(HCxu2zdU$_`+ z4|bttZ9{Qn9;$izIhZfDC+{himWLGGsYQ>+@LsZYdAL;amikhkw7p#l3g5Twm<*&f?*QR(t0n|w?JIr&G_ zu5H=G(cNM`gvAD7BQGj(#NF*3dOyMXhJJs9*%tj|Js1Sr4(%OoI~fN-|3~l0 za(<~0c&00_KJBTA$2n;^@gk{?-{H&+FzEF{njjF0avF;&j8!lp0*pKeNYF9KNP7AR zh|&w6;6IZMI^{8dIA>0J=zMB3+Z1;pFim}@3?9zs$<(F+niI6V4Lmdzxk<)SC(hS( zg4THo2&$Q9p$=!i7cF@J@%i`Bu|63w*l+29Px+N`UD&r$>7)0MzXiQsvh&NxP+b53 z^xo$xkOl+lgHx!%RL&15k9%XkW;wtpb28mmP~QCv4G;-X5QaI8L}6URiUGj3H${X6 zh?P+Q8i~d7$e1gk!mF9Y4-uE$1gh+`FXQtxE*^Wq_O3BLJ}8M-ouR z?6_t7ybM25#!w&Ys0fU4+1g?qPUA{;lzR`)ak6Cyesc_6I?x-%$)J+uL^uco!R{ryLYsvaO>E%2dwJQysx%sZtAI|o{tWOkw0 zLze~1#U-w8p5gM@b3A$W4xZdR!ISsi$9MnW+xW_|;z}AWuC5^8{sX+ee~lm9y@3A= z(2Gl;@95madXm{#k|Wk=4IPEzBmkUDAgw(o#}>sd8sFvkdkK2T_SlUApevk)fP7tT zX`tCB_Q*7+K-#}>O%X+xDPKU&!TI@|jKcp{4g#O&a2O91incCe;^ssy*{42uHVNmp zA$S3Bfp%bbQ8V-~+6qgn;9$^)*-m}7Q$8M##}{)v8UP-T-}dpgYCmwztiuDo0`O%x zYXF2NfhPH(x&p8W^NPKNM6i}vmOt{*>7htPH`R7?K@*{pEr86>el$O}jws&~UI+pM zq#niC#G&2sCAslA5+c^kV;_l)!ltWhQpa&H3a_9x+ z&G6_99Pb`rCRi?3^f&jV^zYk-(`kpDI=15p=sQ$_9fs|+L3;FyS^V3v1ABP>#U0Xv zCD5~GqJ`q&^zdhpaMJD*xre8VS+32hpAvxQ?w`qvkV-OvA3n*k%TFX|WW(paA7TM|%G?WF0cR>ygEuphO0!ulq^(tTfpIQ5Y3XfhGYC7Cuv( zpaD@U6`+wIfj>h8mJv=64!(5%18Zw#5LyoFu+&hQw%s8J%EQ)2sXKGPJV1NjLwwpA zcFgW^UhlvzAR{2&XEy;Fuynv0&^z-Wc!m$8A<2fpCHtsH-AVQIAzE_L0Dtlrg}6Jzmn= z%R!RSp&3hFrt)+f=e*$r%M(B``ipTUhkmidcr!7e_yRRWSA$EGW)w0VYrRWd&8Ddm zi#(RY0jkR|lp@$UJ=YzOS;7R&A)9Fhalm$3zcf;|s4BWN^{x*NZ7bCFAWbdvv_D@p z{-qyZw)Q?Azu|Z^06ZSQ&0|(O@<=t{Y_YJ!0UM(FPGZ#ZU8J2IP?1R7?*=7aauXNs z5R!@mmAwSCJ}s@GkaMHa<*jC(H#yacDl8aQfT2gF;#6o`@-<5#$qgnqR0u8GZj52i z&C%I8K_C=o^8K=DScq^A2}~EY6LaioSJh$0ORhVDBBC<(Vv!F-dDs zHJBUr;|A;wF#~)La9|dmA`8h9^GHINFI6Df0x)+&1&DA1PcOTW2{7pPG2oS0FR7(I z;&#&u6*d4XY4TYB6OfnuP`RN};yptO=5uY7os%*t6~I52IzTWoxDN`j0B%){0B;#6 zN>P{D8{!kfLMhfL>BexY<|%pl1ZMIv1mt2^SFa_nhzUYXuIy)wS zomCVnKZPK2KR7Bbz782%0}1i90j9liJ~!sc6w)>Ar1PC?Ntq3HX^g`38*=@Tw{9S3 zMz?b$a>B%gY*t*inbi!z9Ses3hcesJ-0|8TJYK(dRU?Bf_8a< z<>m%o`_8xV@BiojfDhhzil!?r)&=igUB=q92%5*Uua^T_ThUrW-_w~OL(xiEV80GS zP6`Ld$m#u_w}l+fr0h(B8{<4Y@wsEE3S1+n!cymjoTL%0n;~b8<(`uJ2t)VaLM<(H z2~!%14e(6#STE>9yhr0}dgKlo@%-yl31$+=sRW`hfv|$-MO+iPsv=NV3riHYx2OQH z0N6Q2`cugM;@4K3$K&z%!j3P}0O0@pDUZjO{FoQBVqVVQn={#UGWjwLv_agkVMRDB z0l2%nhkM3Vq{F2V^@>IwVk&%6%10rQSt*i4S`b*3916wWtBC{R&^n#q?5(@y=0P7t zSjTfStTyo6L_$vQlLe47$Bx%=jz>b8I02YO1%>^TdY&E*QbEnbn3-(+Pd=kQSS_G(|rVktR@U zH0!X&^U@Sp4mez2K@S%YDB59xwuXm?BkXt&)1XN9t;0^ym!cW~LM(jSsgS$DtXH3l z2UR~k3*oOz3bIdBUI)xZxT+<+6qN^{V(B@=g%=!%n8ow47>NKWOo?JsqX8<0wekz( zxnO^#my5=T;WcA>2!2O`vJ#+Dsw-=GYEf}9sz&nAF-x`}(RcOU$loxWcKN8GL7jn? zGw*(V??X(1)Ut-G3NY$2d(ErRKI7lnV;t8^N;1x$U+suq9y+Q;UssvEyq68&7I=Y* zY17Dk;M@o>*b7pd3{g$RI81Gro>zwG=`kYX*BBV`!2!UHAfBypROfp371vjY zR6uj)6mU|4&X$E*d#3$Xyuf_5?<|qR)J-lx2fWP-R<2RT`wc@tR74qzQD# z@Nip4?+#dp?@<*)1QC+M(6zN4fTqxO!Fqj-n`ck)^=HrU!SxepJ3z$HH0H&k8r4Do zXfon*T%)8189~EG@6=UX7~10!Yq2JD&rM~7e&9@Q!LxWCWv(hGP*x*Bt(6SqzLrL# z@DVgINJAF)WYO5uX)KK}OJHPY8T+c2EYm4dVix1wmQX^IX(vkk!ZW0f z?=1>Z6R5aEiIfmu01y?0$qqyUz)n+qgZ2(Jhu~!pR4~+u$K&z%LXR)P05I=EkH^2B zW7fstL)9-`9~e5j0Iq8Ux{1L|;U3yI%>hPz#33T##EwifT;hdrJi&v3+aF3*7Y~J= z^tWh$3<)hY3sh=QQhVmiMJixHjRWs5QtBfLDHXEtDD8!a^CR9I_pN&pLD=y4#w*2N zCWzlAZLXBXvm=$Gbkj;P87hl2-=r7{AlQeZLji5!@n05PTwOsAmsqc#psg!(S)m6i zB(0&JHt3ss*nYx(I^p={9x#h|Od|^*Z9-JW^{}8_T;Ss7DK2kraCmYZc?H%5+wp{} zr%!Qw^BT9GIkw{oA_pvo9cF@UJE4<;7sEwGDN!Unz}>=&K4RX5*~Kl~jp7xPT!$gk zOq62l6at?<4-XgEkCTR-_3BuCKzOh8aEH=kXR;OYWRy@v(xgiN}2QUMZB&wma9WnYg=5@Zh$GR_@gGUM45F6sj$r7@vIm~vXo6#{5r zj75U4xjiWdVZ4~y#racUgdZZITr^Nhy!YCi_jN3!^S2fr>Ly`5X`Q(#001BWNklUmA-gtwfHJ~&5UsChKsTM{6h(`{w zoC7{^V2-tMzGVdm+EydyK+2a7Su8P;sfs{`m85Zkm!*d~SyVYcVy;j+lVu|{mCn}r z-+1`1e=Kn3<2$eYDuq8!m?l9^%#!QLJCCui)O#lV0^k6KRm=#~WeOY022Ghzkj8-k z#kqd5eJ1tHxWCtWHplpdC`IR{0VgYcgz-}A`Q}zeLZKHvy1Q0~@DjUKa>-mwqH72Q z8EO*!kS<^4-a$j7B=XeqE?d)BYi-I0Ai>OwbUKqx;V470n_#)Tz;d`kgdZ-5X`*l! z94;cPP7b}20SY_-DG=-j6)fuk>*Xa5hZUDlteJPj6}}mS6sKGl4sAs{v@(QRH+W_Z zHSUQJlqHvYf#)QsGPUf(6i5npu7N{@XTUAh|2f8$CudSk;<2$$c@HCg<_1*u@WHpfj(6UBj)N#( zy}rZ!n|plxi=X4_`Whbtc=`Gh_&z*@t`bU|Gnm2$7>7%E0T@nEiSIm=RHU&WLop4Ed~Ja z$b%sOMCpa+J*8B^w_^4+Z4dF?N@GLIkN_b82fVHUi-e(IQN~NFU{S@|!s8za0Uhf> zaA@)JixfcwCP2G7U~LUI@5J1D|C_&uwFy4?*)MUrdyU)M2i(1Rz+nl>|GstD67zOD z8DooMP@4;uRj`>sI@o7|-G!_OU}t90UW^HaErLE#$weabde5pR9$w5$n3y%|^W2`v z-h}&w0hs|NE^zEA+JZ_h-?%pBvUuj5=XzT*oy&tpdBdEF#ZKpi8455K=$w1`X_`wI z-{rgH8uFWtgjAz+*}PYc`6#&@&0DKa9@hHgNREup{~MbeZ^XoV>8a24#FM5yz3arF z1El5~xbMYsMs^hEyjhll9CNThRc6@n&*}b!!oobh8*-Xg5{J668d2CILKs1B##H%Xa(|E7s%jWjnqI1Hfue|pR%W}Z|>j%iPz`bKTop5{q8h`)Se~X|0_21xhdcb~qV7P?>-hm~; z3&70DSe5`GfB0?u`JewezWtT=adn7NO120-yM2TI`#*gjKl_Kj$9lMgUNkrs^er+3 zS1yC3@yM?5(W+B^k^YkUu&B z4B3^#bUYOPvoVB~kwNI;NN-AbHBSM)s$6}>xlA54P| z#STYX6?-QzODgp)WvJ`Pq;U^Jfek`%7obtrx&vx}u)lUIhb2qL3+GdeopJ1;QCe}% zh2p|edks~2ptble6U`?GR0li_e<{mI01*=@*<6r;8PgLwPh(BCz%&UY&-L_q{}cS* zoCq?-&-15Yh)yt@Pt1o%eKl=akTf0(azU8v7Bj6okLi6R*MJxRr)4F(r?UBTy^FOa zL#%pq4ULeo-h@$dw0W{1rcqNuIBbu3lX(fi_PYqO%1tEBEvsIHWk5#RUoyK`LO#|8 zkA1+vkO!bPgeYaF+&3j^(w9sG*pG0yxOZT5fwx$fl?$P^1(#2rV7<9PyMBsiAAAi@ zodmf$hq8cdk>d!FtEO2WLj5(ZCm(Sh4FKZ&D}3|vh1f!vpj?D zunDH*^L*~#!m;n0MNS4GbFxG;nI^*^rO6H%7Ubx6hEO`0TWO3fZbQxiNQqr6=L?gv z%2cK@_5*NDO_ej}U&N|Wrkt8{hN+7J9^NM9rmHd*_MrJ!et#-ikx4ky z!U$D!ovhn3H7Yj|oat14)^r~d?b9{m3!XXh0;IRsyM?mi9u&9KAggU&&&zOef!8Jq zVYXbS0+UTLdQ6zX*;%hVy&!hpv@_*Tl=Y0otCy9rikDAr@a%&R@TY(FXZY^7{s0$E zpt9ifY)9`w+g+E4{e17~bNnB-uW-73g?@LB-3_`bGG-(1Ef8E@UE=cDJNUyt`VRh^ zuYV0Ut)aCAee)=Nba{DDTB#m$&X2%C93!_W@p+^g;Vs zD1~6XaE1sZaYh_XHA;6;KvV~7ph-~pMFw?W85W@80pukB_1Ypirb^@h5V45!2N?h@ z&R;a|#qfYdv9?Iw7j26$fX3v2>#A6m1;C2KlS{n!!8h?|fAJT1{`C*Btj{1=;7`AW zCr>}X#nlCV`2D}ar=PsQc05){!lHt14VyZ474#mZty&i_c{z3knl)@JXA+@5g4UR% z%MoB32vCy%Eaj04l{A(obHFedE|LEw?wxYjQ;t3Q$jcdY1w33@izE4h)!qrHWRP#h~-V6ir{M*}10IB~0gAw%h;bSYRHDG$^ z*+X*fdaap*^`4vEG=b};^R4JP#TbiZA6WuDKYwn{<2*aTltUoqlP7;N#usxgE*2Wq zjQyY9TVW!HG(OC0-#iY^ULWrg@8|^hGBKs9+Z{D1f@D7gUEeyNZ3x*;?_Q;&9o{Rzqe21fR4FND2cA~GjX1gLS zI*!QtFTOymG3jF%N@|nw5e_qxcZMBWffoL!!Guc#MqHFkm8fYgBJM63CQ@t&6Sva3 zL0u|W zEE!!?2+C@k|IbZp-phRaU7N(L)p>5<#-ws%QxS>Se)G=qK`76NszMXEl_?hupwk3~pbjqU0q?x`KAt{#ipzGuX+J`wk4fvmdh)=|L*&^(FKilfu(hz z3$9zkAN|2MaNi&B%YXa{+F=D+gYTWnox({KbdYkI{m?_8+(1wOf_MqA@1xH=Qy+Vd zT?nVqXduZfLDK5S7!MHcrFf695-L?WK7#OSOuEdNA?f9#;(Ml~yp0Y#m5=hOhEhz0 zt>()MQS@yhm9L^S*rl zxpq4+V&%_n?85l_RL1$f(@mA{F9e%u^HN?^NxPT|TKKH2&s|yk5lXhuLz`axxSllr z7RJc%?2kl#d0xcvE0YMuc}xD?GzM}+-vKl1J8*yO z#dhc_=(|MuzXaR@Y_&vl4WbU-J=dwE>w=&W*qk8T5yq|a!3Qk7hD|)mp@~=cQ|1^5 zMwLTs*mRTnU2PDS2&BOR3t&6oDrijN*V4F3v6bmQg^M)-<5=ROoZ7V3XZv$Kk#WC@ zX_jGBtT`w-zj)TPlm1g$_t`o!f0=)Cy{XykNucJ5^8&^FE!MfoqdGNk;yoclmJ;{* z^lYJ7R$A24Z~z}xON|h>tT3UGi4#~BwDkh*@&@1hw||7c_+S1feE8mbxX^~a z?O3(purvU`{RbO<^0lwwf8RIU-`znU-az&p`|%X*24H)SHLG{r-oC~|H!O<)7Ik$j zJ?Txc?=g2zTL;`CzeV4o|Go2lM`&ABUh%<76V1I($dvFb6jTd!{3_Ii62P-hJ=$c= zOAo7&His-IhD^zoFu`Xbbl#f|53i)RUOHM(v*L1tVBxd#zJu|S8a5nhEQbsi0__l25!!Zx{LxhH6ykXVU@h_i_(R-q$x=eUd1^l%kH>%2LEoQU%fZOLqt^Axh@^l2`?F+y`ySS}5BK+$7A>4AX6;AwY7+5|M~y&*j=^txxfG zAibv*{F}GbNHCjQm%Bu~eC@AVzbS_GK0^qc9tg?fA!l~^cu>n;{CY8pg62IkoUif@BBN(x-9sI?|l!iU%dppLuH4y zhHV#|+;I|0JH7ql0(3{;yvh>B8m8Ppw(J{J2NkVs^ z^#pia?S#O{X$Dp)@azOFX#}Y8EV&Mbhta#Ql-bNi-Vy)`;0?tnNk-KW#<@_h}hNG8QAf{?+dIEh+5r+fX+$>%Sz!0D$*2zT`W} zAUjMf0yy_b?~Lasd(UH@YW9))R9%3BB@yc80HiIre)bNo-hU6@{_c12{>=>z%nfjH zSR;ur#pY&R@CWa`i?4t48~D{v{}B%_Uxcw72-ctio1L&6@3Gy#!HZ8n#xFkq9KZMU z9W;hRhzpjckbOt*JJv<G zi>QhyHGzhR&5~rf&kBBe3^QYNwnV8Ir~^$~A)Tt{D|oxP=d{dJ;tHIN*F39Po-Z!L zqFl-8A%J-#;wjVf(6GW|oj@xQ(C~y5%}yd&4LtT%+jBz-%~p$|$!Aj08cG&DFZ?s> zEQ|55|mhaHEdaM(IQ^4L2z|(!0B{E-?pGYFG1b!y<>-??>jU|Z|Js%Dv(N- zD0=s(p}i>g_lVzDq$f_X?;ZQ`gy+}S`0Cf*$1nbRp)%A%S(j*^s6_4OWHS8!?7jQ9 zEy+>m_ld}=z0c!5`YEZq^=L^5kPrwl#xu6pvX^K1KlgZS7=}SJ;28uOgb+f{e%^b} zIlC$|{6j=!=04p5%rpYor`GDeXYXB=Rh1bT&u>JCR|a+zfMTsWoLgKe@6m-Yu05#Z zijJ2{@G8?CKHtEtZRk+(Gx)zBEi_4Mv!Xo|!|tMK(9SgyzxSk^JNlq?!!!+=#G|B= zomNth98PrR^cz29OD=I^&CDD{k~APgH-kare*bfnz`RxZj+x>8eQJCjROv9;o?()< zKpJ!Rl{AZpe2k;B(I(Ti&G(wyY=Mek(6cbZ^~atb74pMa*Hj)OaxVkMpZ>xUdr9%U z{H6GvN}R0GO3d5*c_hDt!$D(?ib@pmBdYdCYrx{yEs=8Ie}{vh2qoGKE-IALSQOT^ zuoMl*zbmI>aUz7X{UVa^UjuQ{Miquk-dd{}-;FzCkG$w7ozn4yj%aEUH-BSk@yi zefo=(Z~BXW_m98D?S~)G4uy5!u@^gb1gXZh`P_STbf?S%>b=H;=J(prCe&5ftD}}g zGCRkksC5xvNAv2h(xBqd;np0+jN<7l8ctR7Gy%-hBHRJtg;=T1L$Z@cOI8|tPw-ZR z&Ig0nro$`JO5CI{ng~nmIwQtv(;l(l^;qv9(2+s+B%;dL=d)d%d#~F_@k1|EH$%{7 zwcDn&qxoK8%zxChm~V9Nr@Uu3gl1U%^m!I5mS_7M4CatVrIC*L!8?W^bva3wll^FE z;O9Kb_<=~C4u;bWxpu!;T||eIA0yo?laPn$%}Ixjg)FyNWGUHtH#5lmStRQZS;869 zp_7FxgKKL+N`dvrWko;!Y zZip%S?H#wzKV*IPXZ*n*{2o90>5sU&dc}UB0)W?dC(2})J1yKJ4q;@I^HQoyMyG+8=OKVMQ#vOlIVcc1lR7!y^1F&gdi|a ziL#V4Mt52`?B7f6x1<{hGu(t!C%bnlkO1f6%KG-mI#EfqUQDh-23D0ifPfv9wauo9&y1M0`tWAnYNZM@2Gh}NB z$x44ecIy@X-PrD8ElUF+>C+ZNqy$V>x*(_D&tb{7dcmNIayT4099Pz|V70Ps8#JS6 zp|(b~=EW6DaivTbcN|O;n6lF$(ca+^Q*?3Tzep%t5$#Zfi;Dxb`I?^YHkQKy5shlb z4JMeX^_h(MPa!V?(i{dVGMUk#xETz|ZXNDFkdQWl5YQ1A>7411R2yi7`x`*4VQtn? zgKotkl6~$isWaDK27Fj-G8E#TJ%TOalL$qs>+Y^ft4W7?CM44OmE*fvS(~;&SNc*3 z><)uK#pdFszd@2#Ct93qY~?Nl2AaWAshW*{MsO`RVkq|s&9__!8FS=g_(LWnzh9?5 zFF9^P`a9G=XisD~5$1O&BE34lXcYU?*2l=a{WSE6_i@PnKm!zMZsbd(3J4T!o(EMt zm7%23zeslkc)b8+DUmjy%JEnzi?^>j99GJ@0ENddzsg%*{W@Rx&40z!lh2^#666Sr zAi8wp-4M+2@T`YNT)*-~zVHoL)&qa_C*R`zcYcNyI3A&t#@*&^&$JrsjkdWmF;YGv zMkhiu@ooSNnw>k#QJp7jgdXkij4;GKf?P$0qfkJqJ5wyrH;eXwzJY|n_lmdyrxSe| z!{HW>n*r=01%z${M@*DC#inmJ%be@6Iv%2EzjP2kGpN-XFvQAhsz5N$4hs(5KgS!*l%C3J^PT;&wk3?v*)zaPUiRf;b{-u zu`EP-zx2);Npg0dxI%X@8S|Sz*-UC@qa+HDAq*$9q^H~XoLY^7A#E^=MEE(4N_24u zd5t1gA`N6XttE;fwZ5OnSaV$@e+x${mUZd8VRqza8l}X3K|98eW+uhZ&DXCqHAGCR zA=R2teU_R9*eH&#f&Sn3FbaRq<0Bm5;dnUy-y9EZ03VKjtV8C173>Lc0uF|92eQyA zG-h8EB;aobTt+wzwoo->GcKA2_|M?ubk-WEjCJsOX zm&47_qga!Tmg*^~9cD2?@=hTvX>PQL8p|S-QYa!+QT9`F~|Yh9Ug40 zPHzy(msv!l&Fcb~7Zu#w&LWLztIX{QDDy6z{B0JVbbAgy_n#9CGGl6jl9*_I_}N@5?X4VZnAM@SMbe-vJ_*rKy1u3(;?3J zMYDURLXIC}lFFI%)g8`?d$z-Uqa^-HLv_;A=OycgaQ7iWZ=ILgl!W3>p)2nCF-A() z&10Ob%-_cjqh(a=55psjfHbu8$L{(`{ax^VPAKYTWS;(r#*1Sx!_#nft&Gp zan8CdXepQ#mctbkj9Q1_!!=LZ};fzzWKbX z;H}8aJl{)j1dQQb8JgE&XkkEAaR_e&KG~|H8ZL>@*FjOOLPjW3|4yC#CCun!MI&%H^+G}%2w68@t?HeM6LN>;8$9CJRk8Mt|W|7K< zp)~gG#LWxiNM(C|L%Y6VJ1pGl3eC9NHs=)v``sP;%?SkQn5477!>cSihEtAGL1AG9~O-5XR7*3$w!Wv7|%!#uau-I0TdDoAurZ0cr# z@-xE&2|jj{HXP45k`F>oCmr|~_*;xUYw;|)tY}$6E>99SWVZ^S6M{gX!YY{tBb zwV|daIP9Ma9q|ew)`8PM+=%~&UiV2I_eJ}|@k@3*qyRh|pVT2g=WoD+JRf`rm)F?o zj&`wvWdN(VJYKTBy$8Y+!t$Ov?ELayHh5=y>mf9kkK?b>f zKxW;|<>{CMYD7?6J0Y`8^V)8TSwL9{Et@jtF$HXGSlel}Qct%$d;dLdwvELUvBu$W zpoq8R!;D1>g0i1>?r!hcZf{+|z%_nX_8cXE8ExO$Pbao|Vs9I*?QQ^=3rklLjN8+R zcc0(z!Oz~I6sQ$iYcwjY)xNg$*XgU^j+fmA;KMwJ-{;;K#S&-t`%qkmiXJo-G?5yw zMM?941#v?sTlQs+e~+LE!x5F&bl4=5vMz}^4Fe%Zx1JZ>73|r#==V7L*sqoG;Y?-g zhXt)=R6n+l_Uoh@`Wa%ZbguY^-zS^TZ{XUgR(y2^6BS!<2U{%bW#5NKl~Bz z{`kjeaR_s3#(t_Ss_0_K-l!TByb!svJ`ds+MW@NSda<-^^Y3abj4DVI#Itr-SFarq z$zNS@Zw*@Y`R&zG+Ca!uXYwrOyc7t-D|vb%rs$i*yG0E6eoF%&{z*EX+XJS_lZbLE zJ^Y>9W||lKsF3l^To){ z6CE_3J%;)_|C+Ri6jL@8y#OepKZvM!hi+txT}K^D()1lLCz zUQ6fhZgT^;ZnV~h6Wfexwac!P8K$?i(}}VcGRPnbceT>CjRm9bn;ZXar?raVg@v_N zQj++D*ZwSne_Btan4QY!!H-}Ue~oix)Lq!7&|p(8V_>yRX!OJ@b5 zDk9P2)YQbxqBRDksVX9+P-QoytSBcqRrK)Do%?V+9KVp`!2$4ad{ReBgh{3E-y?Jc zfY=3*@!wByy^m}y+yqtcYVEd^q#&0$+;0t`c)&HFcPX@d)YO^)v=<;t5B{u#3}tEN z#q%r3_$d^#UbVdo(R=3;YLSJKV*_5^Qw_o~kdbMBEOSqM|75*Iaw-E|;Yj6c@?Nw| zQ&4fG8^|!K5D>WvlmTB0wb={r$bd7qedG3n5BUC{e~175@{-Sf?u%SsUU7YO6-Cbq ztyT8AbJ}*k_g8<-?S~)uytKe|_lDfiYK{DBux*38TcqfSeu?lRiWTi5ymxcQx4-k3 z{OqrP!0iVga=N?qdIPt&)Idu#^T$8+0pNdbCRt!tBGI;S-0_kp@6I5r#pYIm2ga=(+AT z^zzyAPeUaB?XTS5CY=-sxu+Z4nz{Xq>%Bmq^?d7`OP!U-Nq^2qiMowp=#Fbr=}Kek z%y5_K8FP7c82CMvKm*dB<vdkx(R4i}Mu;SpINUc+0*p0yPl<>Yhr8d(k2)uidDh z5dlk)3_ALE3X3`lVZnNIU!zE%BLIw|e(j+MM9RRjz_KieHFPPcEXZ=?`pFYM^Y+_( z@pt|ek6!;0S}xIYjg}*A2i28UH>?_ZJo?-2C#+TE1adfFWp%o5CxnITm%qSgeoff7 zhWyF5_~6}lkUiqTRoFJD;)o*ePGY#DNIjCjr|K{4VrcV}fYv}(*qiI3CMN}&r(ZTx2OZ517&QJGq`g`1FunHU8E2+na;x= z`^-OV&~r~o7%X7o1NZh`jw9n=nXj8<5Yw~tL+*WNA3cR3Hpb?>f36S_Zo1>*{65w{ zON@~@*Oq9Tn1=zFI%6!%26K<%&&+F@kL1Y_WgXW|^f6!R5n2n!yd&ylVj?+K!|4Mv zdeuh=nGD&fLi;m9Pn$@2p0xntWk*$eu;!^}zJ|NYL=3Y=u@X`D08$v-)s5Tjj#ej(yFGE&pzU{9-8~(n?i6w4nRnJu8oMW^ z6YrG{oZ$717IZ%xEKXA+JdVzc%28VJYxUat|X2}3>BzS{M%N?duy8zFQmu0P;+EUzAM(ME zf5P2+AF|)wQup1{9(rM)faq1B?i>5*mKV>S@n_%p4j0SHOIOz%mxbf9(lBnD@u%PW zK7aP7-=?(2UhinzPTlvY?jORthO&>tQq7t>{X_X`oiJ?DTeGr)go2fpW-Ly^5tA%Z z0}qWcje<1p$Eh|i`vg54tJ4+9vydO5{|<-DFbo1_+OLcEDd$7aZSo8zsPXjvli@G( zAF0y`XNGh}@in2qvyPrdPFz1j_H(?{7l)NUuAhtfbq#7DZu^(rh`;w-s`Lun!_cQk z{4)wa94~?tI{ZHWb>lzhF0UJrdT_|N8~G#JuNqOl{7(JvBH0qqQv`JJngB(NMcu$J zDroWieeVjo?f-HEZR!bP_DTaGO2!r^$u<)bIO^_5@c3%~U*xqSKt zMJ`aeLJybh+fHjnSylu^773Jxx71vg6|DNM5Qi$ay?`tTg^R~;@VT%5k6c_H`LjR# zcf9k{pZa##8)h47ky^F;d?}4R=te}?YV&l7CP-^Y^GK)zg3Q;&V%}T!DIwOgIt_LS;&hf^ot1QY zPLVM)=wvsHar$1Fw)rG(#@e&x~t6=5xZ}dq3ZKtT7q= zef#_6A4ZP|4_+|Rr$7Sz6o#T@I$ZoN8skorB+}P1(2l6nJM*Ahj%P3A z1!>-i zN5bpo9cbuuDdKpEp0ags4Tf+X32CloByx^EuZTs8g)zEGNT;3FEF2~ieHo(&AaotZ zq;=urs1+B~CN+$IJ-g8Q)#(VB+fEH90T~6rj1^V)HxZ&Y=IR0sl2M55z@kt%CIx>Ify4IwJ96|1YOP8%e zalIB7BPGKot+mB8RQF~Ykre9&jby2p@a#(Z^iwfRmhQ?*!=rXu7C@(BF4I#Fi>Y6K zX0_y){Tk~U+^B*(6r5Bnvy!~kHVnBqES}f>$T3q98GxZ6+9Zt|32TOCI>8@3(xIY` zXE4LoDzpu41=`N`>=`daD9>-PyAvO*3*~sgBF#b(PPeygH@ED! zH*7DSv)$a$+U_>8gcCp{3VQ9Zomlo0H$Q!sKmPrH&yRlmV_tv#)BMJ-f0eghdj)C6 zNsMQ=&w2kxKjNLg`617L_RN)^eS?7iCwM6VHE@W2) z|J%rvjfCPGM1G`%MG=<5tc>Pj&Pw^L35Rmq*KW@lGX;1OdhCgA^Ul>-|an-kzT?9R*MXH{vyN z^fjyU6VP`H17BIx>i~$j-d>7CCjh!rAPWF4WuOE~ahSh`vb?C$%s7^Xb@j;q(^p^T z?ce%s-u$(1vRu9j?SL%TG+D5{VHjm8WTYGw%xXtOxMNXiwSortbt!=uxTA2v)ytpf zl`l2kt_}I)KjOWg{?Lt+1?mpES2jQjv|5n8x&vVM^-!RyAvG#`r`}$?u%DOkkj^s~ zafb~Iz7FEZA5m(J$fO2@I&#Kq6o^BdgKJ6tMn?o#dX-y9kP<Gz3Q2~KPY z=|}MPZmv>vx{x#Z*uYA6#A+0*&B%W`dL?dX&CzuG>5jW+AMm|D|8rh`{WX5&i(ll; zSC8Co8|}37=;DG$tJmddBD{BZ;)D0z<#h7`YQ?N#wT2_XQFT29LcP+xJM9YF-G&l1 zM`~6GHn7INSERN;EZE?ei9p<~`&fLIMgddkeiN4bZkp4Ke_O~!$vK-RKjldj%_CwC z-S^U>u0m^mV)MEO4rvIUfKkGsFLP2wVh!6MT&=2kG zJrHpefJ8cF@`OeQJ$y7b#~F(?6E###&6=q>7(v<&TB@`iZ0q1S-UTi?6@L77`dg0s zJNXxR{6n7i;rM5EJU9Rzj!*KKMZ=`xcRlmW5rA}=pQT}=ExTISuc;e|iK$7kN)_)w z@6K08{Wmj2yl_qkm>w>i%A@rGM>XGU8ZaJ}t~hvfn2%+#XRt;aN~_CUA&qJu%KETE zjb{qwG7?ekyof*uQApEPGQSku6p^7QS&SzWK3jySI`0K`viO|Kf9nEU%J`fRSuxL( zZ&tC>$zSn>Ap42B-+~qw!ewzgxHY6z>S_1f{%wm0eJU<3+Utd=ZA#lW?w&tqJM9?8 zhsTB6=Qlik`4ygCU(ik)wjOA;ak{o>4JUEf-J~GOtA1fIAHG+BK{G_wln3U|tJ{RaqB$vA|NiU0x~5vJ?>IaIvy3E0@=g zc>MaO`QkTzhu7c!O^%l@gB&Qw$5>ftr;2S2*5bu6xksZ(dQlBs)N_ejt8O@B2n$Uv zfrZOQZ}8Sv|0T!c!him~e+%!vOVPqzyF-tKqHx-p_r%5#0T$`WCWh@eaz)&sQ)3_P zNpIpQ0qkxuSW8EicRfJxw4Ye-+M;HN3R;6jn)CN+z9wxlxJwwi-jzk5sJAM_ylw!X zCF`>|>Y(ozP352Aor?56(68`fR6CSOXJQg}@)o_#o-V)CtV zx;vrIZ}{K`KjIJn&A;V4fA;6R@z$G^b*1jclgCea`sk92t4sD)`O|Oz89)2M4>`TK z;dFP~pI@SeQO;R*xT$;fIm`M4(TNfyqPs zod?1VQrGH49Yo(#0c3Pdm>It#4FZxMLdUFygWe`yH93d!8%f16YBh-S29wkWilc&3 zcE&686csE4S?Nv@QT6mH8MP4dmR+92+(>R#Gn(OyM-edzKvQ$Dnl{<@B4)MUd8#A$ z4?X1XKIP$fIDY=|-~f0yKFK3hqx;{T9k;-h|B@&!QAN!Ia79d2tclQ2wA*MBnVOIK2Qp1siEv6+Sy$zgob0LKz=YMwt=$`P5dpfMtM`+eU zD5ug8FPB0S8+K=YCFAq3+!*?rftYq>dgw*Q9wV9++|T0IhwVgdEo8ig0qO=l`%W}2 zM~c#(zrgm5dOA^br4=YzFje;5D|Xeo(YEwbH1BV`Z{4D^EZ}4YwNmdktP0QHc^9jd z>(_4iuYdlheCp*VT&;zDyW#y0-r>Xd-=oz#RE+(!)3%+qh4op7Ti&YYT6(>~76JU0 z#1lH%P#rba>DEA}0m&c#}5~9~wJEH3)4egPCD|q^m3YrD2l7aNrXPK|7eXgx} zdH`A|>w$WLa(INU$}3;^ZGNo@fB7H(13&$n?_=wNsj=H0DOY$E?czp=qbM4i2zB== z|5irrg`#k(QP;vE4M_#|k#13|uVL*3HwdjY!_-FW&M;7#dddMv=;=mNVKIrS+|5%- zEF2B7mvT#n-Pj}eW?3w7JVFsVXYF0(h^VR1gP6HdvNk}n_S{E_eDD6lbh6=Wsl>CS zulP)`PG3xc>yJG;Pq8qHLjKKjdRG4+f9tTfnV;oewLW(eW9T#o{rt0I7H*J&-eS;9 zKeAZ6v#uj;Ld+2caUwYKoMcK_T@;u*vv|TzJa-LV5;;xzy@s)xT?{}v%-fy07U+RA zVVgrlXns=LX!{-Y*)v{jJEwQvL9{r|nhX*}Y&D+C9S~j{Kr{*^W<8FWi|mvmTB6wSF!rPT;0RW4_9|GzurWBxsp?x{mHbF}42unV9VswH%OL#PPa zsGy6-=1im&u>^~Xcb3y$dE86KFKGZc`|f6SDEdGc0geDj`1-6_NGKi=2qy;WZ_$gP zK|dif5mICB&IX%y#ayVUL+u5+*E>APb1&Y0^H6|BJ3Akz+B~NAdt|iBz3TbkhWDsX zjr5*??&oK<{_2WF-Fx)K$_jVDUOCBzs?ruOVnnlh-3{D(?~#x;+J2dV7FV`PK@Z_H zxHE2^fv(E;{_`#C02CdQe8L zX^Y;>?h}SYY~r1ZebZa zoGS`73i}>tk?P#AdRad=`h!kd%ep0lfW2^+c^J-v zSf*G635If(auaKl;y9NosiUWOM6qB;2jTJ)-~YXO-b9nVB11ZN#OGUDasFjsvNP&3 z$q;ayVMxf1K&GxgsJCPBy?er+Nfqlbqad>wCmeXvXx=zLQERA5Q4vvEE8(NkeIK{| z1W*9~6vr>)Gd~<3b9@pGfCplDIA*&gKTjY@mkn*=;my!Zuq6x5MUtl~G{s8lWJVM9 zPQqz&h(>qdX5JXENB2t?)D8=#Yhy!Y5QseAt_aLRDJ-a=3e7(Z11uE}N8LBXv_s4W zLM>GnMu4TY9)+NfY8}=Wv(azok7@MERLG=R^gpwwV z-r8RLFuu#ZOzLHVlyEroC?I{`J7hi#2#sPRLNBlR~Nw6({EN@(`9_wr~29j0@_Vz0@$ zNz+A!q|36y==zboe@LnO4>X_1*>5v%%AK3*(CvFmo^^_ zP(E)}OdBmw5Z)mwXt&eRENtVS7+=>FEl$iy!&wZng`e5!E zmZHe1pzP!P{cKl091q7Y?s!N6csTwsj?^Ghl_^FzE1gf?yx%-<#b7{HePtGx&K}P%^^;x|R&t zdadW8F=EJxg%eUoiRgIG_fI3KTa~1TTJa)XZgk7AvMdCSNYBmAzP&ws!g#*^p5}tT ziFu#hj;q$m$V_0L1ccrVht?X+cCTD!0!u)HQKI|TNOPF9!Yo`gBHuAPc@d35p;@Dz zP9Va*RZcf|poQ&pq9AOiTW(&wa7Z%E2}JS2MO}`kDjrH;pY&X|NzDzVKT}0VgeTQK zA&Wn>j^9nKme5;e%=cMHE!QwV+K94Gh=Q~z{GW_eO}7z$;=Y1$&smi|d#oO5;p{on z5y13SkKD(h^LH_YnerO8yMIUr!XRyWN`BCMiM`gZzh_u>Cjj({>HduQL^56Ld&wOE zX;pZxN|a171jjf2#biS@6#d`*bWU zYLVlw-RZChtjlQk*HZ){^}vw;Ug>{b3Z+>5uI?ZxN?9(@<$~koHLrjEv%K}I-{9r9 zewF3osYm_wNO$yA-ubf~)ZA`WyK%tCuvmD|i*36@6ND=c2B#S3C7rk5P9 zU*~XnWH}sB6@K{L@AB-!XGq(SL&I(>a!{56rw#US=Ipyu_hIpM*!Jd1yITcrL?g*VwBUuv#gBFgs#O(WZMhjk>dCFR>!}XoM>Foe}Z2_Wq zW%_MppqGoB+wz@VoC%pBFtJz*4F_}hI6AB8n`vAy_KtOq@yevK%g0E-qP)R~*ZN?Kj9fg}bd{?XELnGtYcC zQNKr(D6R-%>bgSbC6N*l(;-Frd^`X3Wz066>8!}96p>DYUHu8(o$YEAV*X;@S`;$O z%9a}Eryi6#46UO}loGIg^JsmJZv~0&J)=fK3ZJ9{i`xjLEM0EM^qxIsFfZ%d$XyNNoKkwt5T|6AWw8w)3;NkeB54rcb2NEL%+|?G> z7j*T%Rl_ljLUeL*{wj!wiil~-SrrqLRMd#*VrW`RF!ctmNG^V}FsG!qc8T*7>pW>J z2`!sI^h25H29-_UPl66}<=Vz?@reD!=c&q^wXPM$?=3>~D#kWqP_E#oQX+!1GeG2c zu29qs38i`{KNf;BG75*`5Qd~9QH)A@3i9nz zp-iQwVZ%{yhNlh9rk4_wK2}im(C|AMS^p`fk$k|cUY`bk($al8Lx{qOd7A;R2YNMo zJHLd`PrK1C-1|HK)A5KhJ#rf8b8cs+-3dWZrd{6kcuhmnquO0<7NQq>K)Xp4OTfL; zQpftkCxSr8c6-tl@62uW_sAA~qguGP?n}e4QN*jx7nMHdKm&N8y-~4WD5?}4_bL!h z0e1|nC0g|r`gbD@K>Bx!xM812fFdAErU3Z(Sr~9BN-6$qWf8QfcMe!CFgx)0mDhOd zE5E{Uiutbu2H=}*9$i`i&F0@R!>kj?{pGX7!$g!$v+sT(xBNkSW|cnJXgJT znrj(pE#AwjHAS1!s`2EFukz*JEvy&+7k}}e{)E#VlyItSTce7v;j$}RAsiizR*hPn zr&)0xD5l8fH?4sJsWt63ivoVZeuDR_Hugpo2!y6WYmM4Gl|aqM@?2;qSerIfb|4TH z79%>Vcy!oPN1QJ-Kx$`m!|-VYYGW9|$+b06Zr0iMnTkSaplB?mK3?Cp;psW%`cOhKPcefTXW1>xvv!4p&!PJi12K zOP;*;DPDf#Qyedjy!*~i_{n#Sc6&#?d*Sd)7NiwyuilzB9Q8Ekm72u^8M5zeZKeei zbKX!&&_x={dGZ;l7^aE85IPLed_S6{+{Wd7tY4;=S#zG!V%!!mI!_l;JV4NB>><jT9AHb$urb1*#~j(KZn#I`Nk`HK-Ol*B{kO0W=L>>e*n1*MM%6 z*vF!ReL@I;Srzz29zTy!JRH9S$Abgl;rJwuzm4(O>#j334gKpPe*iJBq2+ElafR{J>qQXv>`@`kmCw9xI%b9c z%o#ABkT6-BhRY@C^pfY(9SF05eikK+^SVtD5!$z$Fm?LFZ+92k|u-hP-r=>(3^kyh#+Hi@6dFV;?uv z6W(8<;=f4q@5vT_?j%?v{Ix^`Um`ug3-|drJ;y)t{JpSWRPfKXf9iW(adbc_uoimc ze?2Ueb-^fHT|MT}E3fgnuYH|Qed#w@FF%cx3(9hd$bq`;L6g1^WhwNqIbn#*7Gv#T;eRCKx z43t)zd3`{F{N0+Dqe;#en0oE3E#^Xk&7@q2sgvSDug2ap=(%vSy_yiYbEiPZtapTs zOk?LB&y1_SjCwDPV@S}x%-x?kE&aVyKJw}Q0OvTQdq*cV884eZO(Lfc3z@5M&Ua=0 zEd3v!OLJ64FdDi4KFM_K{7dVLpuuP8vLKB}%iFcVqcxx#&Wb1JV^<>F*)HHldl954 zvZ(LlWx-HP3$iRM>p~ST*e8p+GrTq`TePV)zuqiTScvp2Z#{^Jx9F6GvaGC^R~)Xd zxp?}B!^Jh__=HzK`zBxcl`r!8OHcTVAN+v#e)wZvXhGH^rFkj>ng}S3L=R0Zf3INsq%Y;Q`6jp z>yj)a71D99RAwhK8ZE}ACGSyv8~=8rBU)tk2!Gtar@$J$qB%sAKBDO(w|_i%rqPtH zxF=MUa2zDG)uSo}$ZFRjqYAp3qXs0j)U4F)PKAi{OE?1*pky6pL@bK$NmStvC12=8 z`7&CcjsZsn_Po3}=^46of`;V2m(YDp`H zfeA=LBdx5UVMijR0xXFtXbn-Jw#sriI4{@=*ROnux4(Jhcy-BN{_!92tbM?;ENr^7 zx1F}pbATyA6QMLXMP)4sA}m$esy|mtnu~OctvYQ05%tGYnzTVP7V%<#OJ3WcMv8+q zJh$H@^1zKf_+CPQTl3swR5FXm-(MXNApu2Bhgoa%&ICgmxI;&#?|O%Tw1tBGbhS6GhsRAN4Upuw>EIvsQES%l2?@vTWBZJh$C2DP2aT{N!vX?at`H1O(Fr zG-?ZpfO@wM%7QK{QdabE;COijWu=sbPkfSQwBI)rx`9GV6roTHNrV>w0)#W@giWlETJ@jsX}!#qSZ<%QI$W84;Sz){&eG8 z@oGSlD;!mcz2`FQcWL|=_CP%Bq10(nnmBZkFgW|-_4m}6&ZwMhS=%6tA0j_AEa&W1 zZyAp>r;7oO$oYzM#5$7VOp$=NHYw*G3BWjz#EnpIdeiUO8`NTDnTE-$Zm^2$@* z{K~KKnXi14_0gv&>&uko3T&Z~IjNb>6uND~b|cLMG!Q!xx17mQEYdPYWHir7hmMn# z2JZ@*P6Ma;uF$fuZ!N~Upe&Wkr*HGwuX_&i_y71?y!Vrzuy2iZDV*xYq999Qv&Lp1 z*)CBEwKUjZGs9vZ*G$LA{nKg54UxU3gHZcBO7UWX4x1ORm!j%L!J4NXD1t3QNk^h( znnSYB=7LG0qd@N6dq%J+y(T~+1k4hJ6nkqj+=Z)cTbX#mhHGiIJKS`R8KjCA3Ig^F=`Bi?G8bVyq?~^auN4kF#>kPCP zX$5yYCL~{M6cfC6?~tG$(G8+dgpV8NB!jeAEC~c#?gj5c5{>~?ufo5&%%rT8!;y<8 zk6Ev-xp@49DxAI=v@>N5CPSDk)xa;k{U}J5g$DG^>68xxO>G*CceP z$hGj)f{J5J*JuOiT><)gG}n0y3&*uHzT9UmWRVf;n1ZlRj|4Izl?EfztOONNi_D3p zKxs~c0XI|kI~ZyO*^P2MA*Vrt_h#P~}*|IWRV4dM8 zQ|L3Iu`|B2pPJTG3ec2xMw{~KdPHvWB=>uF>ueZ&lb@k$iY5U~3}weGBBK%Y>jou| zZ2(&+MHY??3uvJWd2fXcjq#Wpx;1S;KJi&IekG=Q7saA^WF2Pym${e(`J< z=+Ej9Npy+GN%0EC8f7331;J?6II2)LPc2Ycv3;W#6cXwEzbWFbbWxB>t3FA+&vmSE zhmYob8^! z(T#MwcU{tTr*9n_a&{=q2$`%xpXiqSE%aQ!Afk_*rkEn~5=vTV?$WDx#yn`;Job{} zN_1wmH0zy`{n;Ywo+uiJ^;_S2g7pG@3Dr+OoFY+R&jN|iLOIXEd{K2j3j5`Ac(h*- z3&_8~nrMcS1pp^>K=JkQ)_>~vR3;~Y!~Ru_Wl@$zqL83F#8ezHpsFmgAnO5Ljy!(p zF|U30O+NSQzs-|3f0gCBUb0YwHYfF(x1#m~5iMxli2+GQ`C~tlBf8g@^F@N?4zeoM+A7HkjD7)_5 z-5IPB(J~M%)ZMUZ9F|zi-K&9n(!aoNgU8x{*Q*G7@H8#LzPq7z5ZH^*n$Xmpb~SC0 z;=H599s#c@P{QF)lrXnc_Z?4rJMY`=VUll5mY3wl8NYwrk*B2?`}-dK7H0$9|8n}Se?2kH z9?8$=mcipXIoQw&5_y;6Gw3;;=jr~){O)vsu%5@w3Ttbd{dYowi zSDvw`(o!39}I>(Cx?Nr(K%A(4%7tcAJZu#(MKjHAfB{%Q9 z!_E7yE41o;<4P8j5WkO>g|c4q@|&OGfBV<}GoO3%7%j?$77nGb-|keJJ1UDHhZQZw z?Nf!FL|o}KPeBq{V*V2inl?GO*f@hNnr}Kc;18< zMl)&t9wJRV`^+fXRGPI?-M69;U`?McgR>p+a6BBpkmJDt@Nj$*hur%Y&RIMHc5R4f zbs=&XHe9!r43**`t)`wz2O{P{y--EnY*7`o<*4zZ}PsWyi5>ISJG{g64IZ!NAU7hl&EA) zA2a5b)H+>B3BjHD_!wl4VR#!FhAa!Zt}Itqn64O#9*#&64#y+1D7EhFca^FehxLe* zJFn{BTtm&Aebfyeiy}rWh2?Nyy}V?(I6AVR8l^a7+YIh*@7PYa*mJnOt5{-w6aL3A za6Cd2*1fg9p7}QxH5hWCf(Cl$f_82L&F5t3V%A?J)-(;@VK~LQ>hydv-;>c9VOG>* zX%iLFZGcV$=Qpi_SQVu*1-wpmnJ>nk$oN$zQUjL#JRs9{p@2&l$*8o_HdK!SZpKDqC_eJ4wT>P0! zp#&WG>iP+fUV4d7efi6L`itM-;-xn! z*07k!u=B`Kdm^KrNfllRT+V1%0xct%Khg{{H+rmAMAkUJaq;L)Uj4$6AaV_t?{!jeh^ydxLPs6z?5_ zr$Go#2c*I~PfV>=o1RxY?F`V7 zU?s-OdL|?SKoWPT=yKrV`VogGPxe4eJ3e@EgOtMFj2E{z zeE%mu9tpR`FP=FGivj+Kq)Ni!a}8g@z%Zpt;#L{f=v4&&?;ST%9K9WU34Z84aF#BYSPBMq3$Y_?|F3BDSI8xsn>PSR%;OQXds-UOc{`Uc^bPDpm}!EVmn)gQcw& z_e+DLrGlkt+$d+!54xxt<8`a)yzG%*CTFK~B-aSJP1E6H2p*B_#v%sVuzj4KF+9tc z&r`Fvb$m|mx?rd&d&`sp$YlQ3g(bt96QaT~WY63TY`Zfd6d3`EqK6eZUa?+2La(kl zTwPNRD;JlSEQgi7HA-37P8+v3FW7FLQ(oL~`@x5_ZG(LST?U+01d#>QTNpih=@r)N zYu2kPF0L;SU1{cylEbRJ|K11OJ$ptIrQPjR@#0+jX-C4^m1eHM$Anp~nKdMG`nvKb zghC(A9kU)?YfQ>tU(>|yrXn%MNxdKyhpu=Gq8L(ooti7ZIC0=lBO{)G7z?B2!VSFx=whWB}qun9S`|ztBmNHN>-h36d8Gx8VciZ zLP$4cG~n4fL2Ok#9Yu}s2u9I9aj3f}Xs{X$M}h<#Kd)a>ubtk}tNa^FoRjVOLWd6r z!PF8^qGezH9@YIb-5^s0G#mt8?9b}}Xwh&oX*fvS^Uzx1^3fF+msfoHbD!g_U;hSA z-uP9@#Vf!8s~X0?Pp~WsR-;3Pd0Wg*%fx)A{+&v45{WOsKujgQjo(Jt*{P!CF#RW2 z?!C3AKa*izP%Kh|THR4SdRKyWq8y&`(p$g5)sxrw%jSKFNzp@Rf-rJE&Yg5o&EgA8vd|I5qbcYfhw| zH=_zs3&2~OwxFY|I-Y42YQi4(>kfh7p^Hq0sSGh-O*+3deBX8SP#07~U>f7vj>3s^ zQjR4rnD=1kNpil8J8)VEC-dN6J~ts-rbzpl74q{;lKc1nc}JUm{=3GqL`wkXU`W#9!Tak_`K!vgvbSdazVSV(7 zCvSd=Z~o@j_}$NcmLm;~`shet_3Petl(V$ zA`Q?C>B(&4!LnU+*Yq@sGj=DmKd@S)L!6Oab0Swnz15YwfJ8*ZM65YEnQBp4PFcLj zZ}UlY0mv8nq{jNYj!C#YI4yozj|T_9!|_QRGdrI@r%jsnO8+;-rY(-T&2Dzhn#Xm- zyRuj_WwA&n4s*r@mdoV1RJoCbocrCINIby!GX2E)WNFM>SCHs%`7RWC(JTpJ>0)Vc zKMT))6p*^lht1D!En(gMEN1F?YW{1#wxu$8CUnP_U35j1Jw4)GCMCSz3=0fi$en=_ zEC2u?07*naRK^g_J_}XG!lWImA~aDqGz>~vSRXy%jo#v^LB(+lzesIVN5Ts?Wp;qen*{_LB)@%hj4 z(km}RE5k6;7UBTu+AbB}7CY>(8L-lQ0|rzAsBQWsddnf_`DdL%{jn34o-N z!6WxeJX6lg8s}xIz!Dt>mPNeEy?C3yr4*JTZW%UM*Of(;rpmIcJbLt)S3dPJuYKXm zeELgY=jxTuBYK5!09icUMwg+KhM{1!I+7;yo})`gr*UM|7D+lKoh~xjRyGqH=^Yu- z*C{0ix)To(YHQsXR~2X{C-qh_Ssb!uE9hei7hJr2%pxPKxK8`;k-oT>4>r;>q` z!g4%t`Q#Cgp1#CukFL00l-7i;rfWjj0=2f9@JNol{?bz}9zEvSvh>agt(iLxW5JUT zmvv!TmRNJ6EGvd_+BeqXMLGrLa9B}Sq?s7s#n*7Eph=H2 zPf5u9qyzmw?7jJuWXF-`_i>MxSx0vR4K&cWND#ww$>DH!M>5kNATyciKbDz(k*#Da z*~(_;;E9~kBpRd$I-g0eA+GHYhPrNQslO`sjm{+5vIq0f*2*9Bp>CAsBhurx0_V^P$ zZVdpp$M52pV93!CkmE>Z`LXqXvf7g>y3nz?^omQ85JSR|n-oN4yHq*hjN@68N+Lkz!2+C?f@>un01I7y3y1vlD&`$M6wNRNR_zXusHV% zC*kW)&nC9e(vk{l;XyTvFT$hM!xxYqGuo3*G14KaXeYIq6{IX|@803w%P;ZP_rAk_ z`2G)g?&O4`3y+^%LorS_CtwXN@Q?5RivR6@`Cqxdyrk`Rl+EI_L;=;ssqbZBIXQuo zbMC(SkpJ<2{-1dB;Y(l@WdSK{R5={3sjYH)_l$q~$xpfX@DuFm1yIlvki*VvD;H>M zj8Oo4u{J3P@kS!l4!Er=%LKzD^{X*luFUk(iDRbpuz{Whe;UTTRL1b-RdEOFgO@tQ zY=r1~u8ezhU0dkJ36Y`XBI&gp%*TvD&idp)B)c2;%zQ>7gYB9gL?Pn*36R(4>#?OT z+tKNl5~^6-Us7oe1ApmVhw?b8wStFaDy%zjYOW7vcJ5Qzh)a0H2xdrJw1 zK+(wlABp?am21x(Ae3boHN2!><`eK3^QB+oWdh3*41p!`0u+rb|1l04h5-aAC!F0q z<<9-Py!yuLyz#yNj=QgX6XY(UC$t*sZgE4Ud;dM$pjCe-sg2gECm91WPf6~V$shs; zoEA!cpP13#xh2KMk~6n^GA)cW8Ta0))zqH!%+{#QvaTLquM5^zTJ)9Z7Lg6sl#{bp zc=+xAfs?z>@r%FtD?WMeS0IYDmFufUIrF_@w`-*P{=a#V^ zM_36rPRMySZ3;*2n!ZnbXg7YldEK+VpJifiKV8cZZNqS%_kWgV60{BJRCep_7tx6k zF)^?tf|Hu`adSXkB1Ya5h|07XC10g1Tec@BEEH-W#m!bj@iA;Yc%BL|>I#b%wr3l3 zvjIY1P-v}s6&$Qr-J!vDSvWn}QcA(3t`3T|s3+AdLJcpwc2-i2 z{VFD$(f5MDwnGA@^(k`j_+KG^d)_2BDwWia7*ob%o&w24jGRr9Yo-lmoP=}~=t&7O zxj-%m%em`wKx6Tk1dFIkE#Kpu+HYN#%ZVZ?UZJQ&Ric=B8Wz32PI3Y&$Qquem?90& z+9)8>5N#g4WLBj`I-gS_fAa6{_~%y8@A{Zm)$g+Xx5pp&xHSOW9>443rpVRSVS^vy z@=})g-l_a31yND;9PyZRmz5)!g5ZvA6BjKGX5E$J7UC@HC6?@bRjY+Rk(v{(ts-mT^*_3`uy{p3$(JOl!dmo@UFn= z*(opGf1Vc~KH$->&e=WLU~R*Cb$}4u?rrh$ud8*#2dxIq7T2wq5MiZkEAmg(nFqY)OeP527`3kwM^%BxMIL}?g9Iq= zniLF*zCbTI7%${;`VQDV#y_e91bx3C?%mN$5IB_$L_4it0qL>+QTDG0Mb%aN$ThGP z&_%p5f#3#$65#|YETvF3o;Xuw!`ayx58rr|ul&33@WN}~MbBRYx#LWry74L(5%{e| z0vxvCGAe?VLNBLiH)sf5BFnXjigHJoB&&&t^5!5RpKJd%<11ewy@ zsFHhaweVaEL=}&sC&+S-6IpoaYiFE4_kef*?!WNC+yBJHqeqlYb(%iLX7RncS6JC+ zOjxW59OR4PNo5d(hMG_#zTc_b4p6j!Y2*jUq~OI_5*gcEEsUt*EUij&a2AW&>Hluv zZ8$?f3vR?K@m*l<)^>1XWKs5q%DOf-Wnnd=HsfG$ zb$wtx9K2szi#4i4XRsE<>SJA48!V!Dx88>Vtii(VJ#?1b+ubNOjR~RoB#71o;qhBC z)^cu&8$5_aovlR(Nx7?q~0$Cz3P@Baw%8`V<6_}A4Y1@U{N zvnUyB7L^%NMtfI;e5z(2Ljf9%Jt z0pRxdZI4;>-~1jpVljqjq$i%ng5~P6MNNJGc6pG|c2gW5h)U$S7xUaMk&w&fn03_U zvLv?Y0LISnohh<&;|vm_jDW!*@N^PbGCWWHCOxF!xMTct2%1UpKEi_Wc(Xja#XHFG z)&$y=P{tEH^(Q78Y*YJ&{2rr}v^J9{FVzv9$Hy;%6m{AtE-W`^TNiSh1#QaW?oVoK zthi!gc;cRhvDt1|w+s7A2THZM*FwvJ>OvKvoNu}J-1D5u!lGMj5oZZR*}%F{>Y-xR zoJoK!ESle7M5$6v}c)sAkN$}Fk4kLUFN@>-d4R^@eV0{o5`dMtc;k*Llach#^q!{o-o4M#LB5DaTPMoDI5Rn5uN<_Z&EEj$Kp4OE zus3Q2Sp*SJnwHEJ)kbYz2_TcFDh{qz8KGA$Y>e6@@`l8EtFV-eua7V_ z{Cu1EI%NR-Qhe@N^>YKN5uw%y*2@Jh^L8M|06z@}McfGB%SggX?(Bz@6R}czu7FN( z%6%mEjJ_8o$jYZDtNg}3HDt?;tt$7%0C+vVf4;uc;CS|NbCa93hi7RM3SAiWXASwB zGxzACSOB>OESWT^fy5Xm_OIsQO3hrC$T1;U8J?RYI8Nr^Ug9@3Bf|;2|D9Q4%}54) zZH-zDkpfa#TV;P(StNj`3PNGo=H4RcW})Z;y7zFC;*20eTmY_n>h6lGrX%E)Whn<=q*AE(vTf(ZLtSre`anV%QBoY4dA3)Scc7{8rAoN z0NUoj-;ADXp-+eC>lR}xX0)~X-l8%Y%7+~GZOxfd04BBXUur^)G0d5fp$aW0cz8c@ z{z#6$fb^`dL$-R;a?-c)TfB6p8xlb*qdGxVOb*e*O`~{@ZxaI0UPpNUpIIxn$L;ZZ zJZ=pDx5saL*p0vC=J$Q?j14bvTH;fw70MF3cngMRu=fLkfQnYaDbw7jn~!lKv2X1X zUgo@d2>}^TH4g4ki*+O--M`vd4wF_1H8)Px@D6+;8S;-Vi?XZAZ^Z?;N*yTYn#K zn?%g0(*{#nYn@&if;lw*q@*I&YkUtto4E)4Cepk-S_>50^8LF&jJB&A1(rqF?|1Ci z%H8eaUb42Lo5JbY8Lh58u2wLXqV#GCDb%%uGJt3QKi_h8cFO5y!*(gG7-qG5KEw>& z6wXf0*le~S4o0*rNGZs=ddtPNUaQvWyOuS2S{rq?Gxj#5|KLQp3*0i1Qm3<~7MOz< ziUZ2-%q_XVFvnxtn>j8#SdeHYZqkOujUQCeUW%<&;HHQ!o zCHuzGmI!Td%Izi;#GZE`&ld-QL^XhdvMj@3(LugSZa|rJ3R4rp1g=I_k3??D_JJh=XvSW z_e^i^#uG(s4SKv`J@dJAmQ)_$73;u4^^9_=oNmu}{d>=GdgpoG`^O*g(Yx>RR1~4I zSoJvkW^6=}#aM-IEP!&U)qSeqQRGMe#R|#WQP~l_Et7`W$t~GRg z0thteY=hi$A&dpNuEckdVmRA#mq09nX=d>TKM=s({(lKEl=8NuaiINKR{2Q0S{ zpBpWJl|UFmbD!gA3lo_f>&CHVKK7Bk@P?uQ?7 z=Z!Zg>SgOhygaF>^5puO&p-K;b+@CK=e)35X`XG&5u7ynGsLw`E=xAFE zq71F!#^BEaN&B5ryGvu4pwzWtCyU>yHJ|s>7&}94#s^ zp>L1d;}3HDAq@bxllljs){`Ll`6IgD1y&E~8lI47MHePBN|QQy+ml*0bxtae zp_IFxVg1!I!Ip$)&w>i=j|!pN`Wp;IEbByt(jsa{WdPF^8uGDp9f4%p%DYWWikhEYe3ns$4 zHkPHJD(v?wvIu1%HV zRF~qjVqiJe`FTo7y!^(iyz%Wn=cPCQoO1dq zTJC~4)xTDEqe|=xM#V$}KnH_K1*>&Tx167?b>>r+-xBjud^vg2^B+DZ%F{>Gxg=WP; zzPe{OM zn!}KwKaG$vje;57$!{J$XMG*!e$}y(j5hT>Enb1?_t|#ZQQWKrPJ89JIpf2ZG{$N3 zoEUs#Q+VdT0(HLSL{PlDWNe+5&ctp|2bpYZv+zvO@aKmHS+ z{@^co>A^!bQrHy#uN33$_kP9oqc1pIT(G~oa@JgH?u}Q$_5pg+LzA)rka?i{KdHk+ zNEkMZRty$E>R>74a!>0*ua8w2KT`&Kj13uZQ-k?}fi~aIloD+l25E_q4-V0qmC(OB#2^13ED{NQ>Zp5S&3K_F6HHWS+QPc5t!cq?n1tO_ z;7bgEqm}SSe*7u5_4atiamxU>J$@g@EZXx!idYd~J8vAt9f{3Zlz=(gR3rMbA(T`z zA`iG*e=UNx>Rc z_UQWjenNL0qt5zGg1mliynZ$`PVOEmH(jF$Yk21Jd-t``!D&mxIRjzwexNpjuWuZu+wmq#j z%Enz@yWNh%&J&Ft4hO6@mQpzE_YAn`%5+09t1*j$vKR@my#G>}8l!D_E~)6I=XB_j z(r56|bf9p#y*l^jivKAh>P@8Ew@LSgz|j=dFRuf+LT;!fJ|=)>?X zdz`y#=^pzZ9{K>_$cSwg^$1Hdn_~2(H(00ksOEFR7ytq0!)qT?)(H(+axb49VE_={ z5lQ{%28N=(1vtguv-LZLHo^zOAmBy~iNt+Oc?1%;(}8zUWuwBf$-Z;mCgPsE?Wrf( zLJVCB%cfA4g;EOWhV#=c&p&*TSKj&t55N8cPM-S;s?S3?L&^pN)`PQ^WTq99Yk7oU z^Z{&RoeOU4a&N8m{jOQ{L~@bu!m88diwJFf%=MFBbN$&neE5r>@WlroveuPlv+(rE z1rNXZeO`R{CWm^L<@`R#5^RqHvMg9#p-zCXDQ(e+QP)0KjR;Ljv?(zY!y4r?tYOv9 zTb6TVd&>6i^PIo%689fI}^5n#6ZDo$SC>kFPKb zLz>VNG&JJ7a9Zbj?A`!|>=mc{dqUXcX4LKoI9%;mtFvYHyNV%P9ahwgvJ~pU!vUai zvJ`f^Jy#b`Sq}%0<`p*#FfU_g0=gOp8udv*mJRmqFZipAM=Yo3oZPv~+1Z)16Y9#7 z&p+kqhaa+ga>3zxk65MTy;}1;Eo%;{fYmN+tR>)$-s^xr`Xh`doei1i^}l1x6of2? znw>90*Dxa!67~U4T_kgj6zRH^sjqFqDD1JIh0MU8F$OX*1Crs9+Lt%K9Wkm>-;yX( zEFpJN5g2R1^*!kpI_q~tMWmWEv&`v?SW`h;0)I8eBpk<3O8zvCKc%+b9?v*#4FI>t zZ+rZ6V!MA1W4c#IIz?GsoUVb(PDB4)6c5a7DpC+JRTGi$^O%TADn!0jswBXb{#Vp`?P`N?@oEqE}g}{gD&=^0aP;*rICB-U0pCuqlZ}haUTL{Y(kcNda=B$K% zZFr?6Jq&Swvkp&jA!c1S=?SBIXI)bz;1kzkGh7yh~x)y8sCP#XKI9VaIz zh!)oM0IQ*`i+Uu$qZ!z`(rTkxn>>M`XovQxMI)QIQM7o>q%}&}P!!g-I%w2|lkK*b z=CK|V2xfI)?l$y|{;DC9jRBk-)wQ8ue|eyf`q6IwEc2NGaP#M(1Lbr$0_#(R$kD%f zKTZ8dCVg|#OXq858vi_pBjmGty8E+QE{Org(|}MUlI8gy9ugpu&SSdgBc7%4fBuv7 zWP6YveFsSzp8BLH3jrdvk#*ap8x6wKpYNyX*-zkaBUvC0pa0e)^k@7;Xi_S!mKbR+^!Spi-GS?iOYXn&RnDxjxpN=YlPHZv z_jZ=e;v|6PinE0`ZPKA*{(1<*_|5xll+O~(>+ykZ5VkC53om?iLALj}`@)a-;O(Dt z@%S@NP8<9EHS4-!RguNLtp(xG3^PTRz%OcOZC)NQlJYs5$&Ep^Hc#Lu9wWR))f8Db#&&5jCmm9xd!6$tOAhXU1`8eY$ZS|^pL3B?2ba1x{N*EQ*&=RLN7M`GjF~& z{U9i?>*As;9&?Jgx&�#%2WTO7JHso)2RLIeMnCFotD|0Tp7%>tComt{O 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 z�kKH%p1=A4ZMlLSS7KMv@#{bNDVKLOns>mPOpj@ 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�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

    ^be-4f#Nd33Alm(V`a2 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 I-ZP7IZ=690RBqR9u_dna&CxMasgODgmZfI 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 evW(^8c#`Ly%(a~vsQd}w{~T Date: Mon, 9 Mar 2026 15:47:12 -0500 Subject: [PATCH 041/129] Add Augur to ecosystem (#1515) --- .../partners-data/augur/metadata.json | 7 +++++++ typescript/site/public/logos/augur.png | Bin 0 -> 348697 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/augur/metadata.json create mode 100644 typescript/site/public/logos/augur.png diff --git a/typescript/site/app/ecosystem/partners-data/augur/metadata.json b/typescript/site/app/ecosystem/partners-data/augur/metadata.json new file mode 100644 index 0000000000..a948f51512 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/augur/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Augur", + "description": "Base mainnet smart contract bytecode risk scoring API for agents and the developers building them. Pay $0.10/call via x402 in USDC on Base and get deterministic findings plus a 0-100 score. \"safe\" is not an audit or guarantee.", + "logoUrl": "/logos/augur.png", + "websiteUrl": "https://augurrisk.com/", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/augur.png b/typescript/site/public/logos/augur.png new file mode 100644 index 0000000000000000000000000000000000000000..cb1b14c7c4619f426ff9b2d8d1d256bce2681409 GIT binary patch literal 348697 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

    Vo+m%rVW*0Qsf!qa9PyJ^C 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%0DCMT@2lXCPI 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

    l|phU;@iI(7=nK@;>WgzA(U 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ňTqzy8w32Bh=gS0&@uquK8!9cw3OgU_>NVW= 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 Ozjqz&t&`23^M3;F8>@%_ literal 0 HcmV?d00001 From 8a19b2c678cbb941b625601aafc8c15a4432fb98 Mon Sep 17 00:00:00 2001 From: obol-sh Date: Mon, 9 Mar 2026 15:31:33 -0600 Subject: [PATCH 042/129] =?UTF-8?q?Add=20Obol=20to=20ecosystem=20=E2=80=94?= =?UTF-8?q?=20x402-gated=20AI=20code=20generation=20API=20(#1513)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ecosystem/partners-data/obol/metadata.json | 7 +++++++ typescript/site/public/logos/obol.png | Bin 0 -> 1992 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/obol/metadata.json create mode 100644 typescript/site/public/logos/obol.png diff --git a/typescript/site/app/ecosystem/partners-data/obol/metadata.json b/typescript/site/app/ecosystem/partners-data/obol/metadata.json new file mode 100644 index 0000000000..1c3568f25f --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/obol/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Obol", + "description": "AI code generation via x402. Describe what you want β€” Obol generates production-ready code and opens a GitHub PR. 7 endpoints ($5 USDC/call on Base): site cloning, Farcaster mini apps, APIs, tests, docs, CI/CD, and refactoring.", + "logoUrl": "/logos/obol.png", + "websiteUrl": "https://obol.sh", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/obol.png b/typescript/site/public/logos/obol.png new file mode 100644 index 0000000000000000000000000000000000000000..3cfd0fbdd388e4e0d9f10db2b51f7e27dbb2e2ad GIT binary patch literal 1992 zcmV;(2RHbMP) zTaMgD5CnG@`Wg5BR{Y~#WK#_|Ia1;bO2a0GS#48YH9~8}0h*u!YHYiev5U)U( z=TMYjDZT?)enBCSVwDyyOZ4IqV>>NWl*mOR#(r9uC^3sgit}j!ve+*WF|MZ>i(2~x30klX)Kf>bLGjG@vTlsFhwDhSk~4L-aNPY~pQ%JcD+ym-*yHgHac34$D; zFfT&{K@L!vo9==j2Pn2e$q;a$?jX%|U?AfiINB2Ad4CP<1Lm83|QrClJ&C4#ui zp&&)7EbU}TP8Y;k4rMWtL}@2Vf*@gHB#6?g3gRY*vl#B8w38$`O%NwJlEiQprJW!N zA1f|Mmg6Vs>%SyH9MXfq@Jy3-Fhve02y*x`8`S0Ke10Yi;xGWcn1s{hNQxXv5ah^V z7OvNkIgLD|D>r*2b70**lhPxx!B;T}Zn^eswRR;4a=T(RPT4@*fK$sn&rf7Sa(Z70J;mJvb}PA zizzXS)PL(de>w@G(ww~)ZSL!auaO2a^1&JlzymgxZ8pQ(~4imWCG>7ggacTlT+DI$AONW-?|TDNN-%_ zNLk+{f>b?!^nUxK3{UTM&P7w?+1!&L04vA{LV8>aDIzXNPtxQ_U-w&rR6T$6B7I2G z*MD2gzeIwl#4-5wRYH(nq`y7yP={Y22*6fBDxN=j#V~KpG4+@WZnGXeAVC0DKoHX7 zTPEs)AONz0^w^*BmK(Q#rq4g>&Nb1+4sZ2%tT~-i)Qi44D6}SMY+LDoFZ&ds%@w{J(!KEeOD95QG%@mYKRB2*74RD&B=8|0=MNB>(EW z_TT{t0>FaNc`IktL-lPsm>blpE5u|q< zrwvQ*^-coYD=9$$$_P^R972j*1L^Vo+>;>TlDMz$C~|^~c>A~x(TH_TMbpDZkWsiv z;@7RekP}$O$v{wvEMJe3a{LK|9axQy>abI6=wtRDFC5YM(xiSgJu~m@G_aIfj@KtS&E0ak5 zx6ZTdMIk^BECo?{i@7lw*8MF(RJK{J&8o~KRPT4@*fK#Bo2JZUT<5n1QA!c_=2c)4 ztM9w>Yn>pfO;lkDsOv64)KVm+nLU{V>$zuc4-LA?<>3-86SKrP@=}l3V!1SVG*e*R z4hf>T)k`BwdoT#Yq>T z_tzXJP2 z2~AR=8P?ryK}$%J>uH8!+_7EQ5=1$lW-P`X`vpD&S@zQcq Date: Mon, 9 Mar 2026 17:51:52 -0700 Subject: [PATCH 043/129] feat: improve permit2 and extensions sdks (#1487) * feat: improve typescript implementation * feat: improve go implementation * feat: update examples * chore: update e2e clients * feat: improve typescript sdk for permit2 & gas sponsoring extensions * feat: improve go sdk for permit2 & gas sponsoring extensions * feat: update e2e tests accordingly * fix: lock/format/lint * chore: added changelog fragments * fix: x402.org usage of permit2 extensions * feat: pr feedback --- e2e/clients/axios/index.ts | 8 +- e2e/clients/fetch/index.ts | 8 +- e2e/clients/go-http/main.go | 10 +- e2e/clients/mcp-go/main.go | 8 +- e2e/clients/mcp-typescript/index.ts | 8 +- e2e/facilitators/go/main.go | 98 +- e2e/facilitators/typescript/index.ts | 41 +- e2e/pnpm-lock.yaml | 925 ++++++++++++++++-- e2e/scripts/permit2-approval.ts | 13 +- e2e/servers/hono/test.config.json | 2 +- e2e/servers/next/test.config.json | 2 +- e2e/src/discovery.ts | 4 +- e2e/src/types.ts | 1 + e2e/test.ts | 99 +- examples/go/clients/advanced/all_networks.go | 2 +- .../go/clients/advanced/custom_transport.go | 2 +- .../go/clients/advanced/error_recovery.go | 2 +- examples/go/clients/advanced/hooks.go | 2 +- .../advanced/multi_network_priority.go | 8 +- examples/go/clients/custom/main.go | 2 +- examples/go/clients/http/builder_pattern.go | 4 +- .../http/mechanism_helper_registration.go | 4 +- examples/go/clients/mcp-chatbot/main.go | 2 +- examples/go/clients/mcp/advanced.go | 2 +- examples/go/clients/mcp/simple.go | 2 +- .../go/clients/payment-identifier/main.go | 2 +- examples/typescript/pnpm-lock.yaml | 5 +- .../improved-permit2-gas-sponsoring.yaml | 3 + go/CLIENT.md | 40 +- .../resolve_signer_test.go | 68 ++ .../erc20approvalgassponsor/types.go | 43 +- go/mechanisms/evm/README.md | 4 +- go/mechanisms/evm/exact/client/eip2612.go | 2 +- .../evm/exact/client/erc20_approval.go | 8 +- go/mechanisms/evm/exact/client/rpc.go | 280 ++++++ go/mechanisms/evm/exact/client/rpc_test.go | 132 +++ go/mechanisms/evm/exact/client/scheme.go | 76 +- go/mechanisms/evm/exact/facilitator/errors.go | 16 +- .../evm/exact/facilitator/permit2.go | 140 +-- go/mechanisms/evm/exact/facilitator/scheme.go | 12 +- go/mechanisms/evm/types.go | 37 +- go/test/integration/evm_test.go | 12 +- go/test/integration/mcp_evm_test.go | 2 +- go/test/unit/evm_client_facilitator_test.go | 12 +- go/test/unit/evm_test.go | 6 +- .../improve-permit2-gas-sponsoring.md | 6 + .../erc20-approval-gas-sponsoring/index.ts | 1 + .../erc20-approval-gas-sponsoring/types.ts | 54 +- typescript/packages/mechanisms/evm/README.md | 24 + .../packages/mechanisms/evm/package.json | 1 - .../evm/src/exact/client/eip2612.ts | 8 +- .../evm/src/exact/client/erc20approval.ts | 25 +- .../mechanisms/evm/src/exact/client/index.ts | 5 + .../evm/src/exact/client/register.ts | 14 +- .../mechanisms/evm/src/exact/client/rpc.ts | 121 +++ .../mechanisms/evm/src/exact/client/scheme.ts | 87 +- .../mechanisms/evm/src/exact/extensions.ts | 176 ++++ .../src/exact/facilitator/erc20approval.ts | 2 +- .../evm/src/exact/facilitator/errors.ts | 2 +- .../evm/src/exact/facilitator/permit2.ts | 92 +- .../evm/src/exact/facilitator/scheme.ts | 6 +- .../packages/mechanisms/evm/src/signer.ts | 24 +- .../evm/test/unit/exact/client.rpc.test.ts | 123 +++ .../evm/test/unit/exact/facilitator.test.ts | 94 +- .../mechanisms/evm/test/unit/signer.test.ts | 8 +- typescript/pnpm-lock.yaml | 3 - typescript/site/app/facilitator/index.ts | 27 +- 67 files changed, 2489 insertions(+), 573 deletions(-) create mode 100644 go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml create mode 100644 go/extensions/erc20approvalgassponsor/resolve_signer_test.go create mode 100644 go/mechanisms/evm/exact/client/rpc.go create mode 100644 go/mechanisms/evm/exact/client/rpc_test.go create mode 100644 typescript/.changeset/improve-permit2-gas-sponsoring.md create mode 100644 typescript/packages/mechanisms/evm/src/exact/client/rpc.ts create mode 100644 typescript/packages/mechanisms/evm/src/exact/extensions.ts create mode 100644 typescript/packages/mechanisms/evm/test/unit/exact/client.rpc.test.ts diff --git a/e2e/clients/axios/index.ts b/e2e/clients/axios/index.ts index 0b30a8def1..9923e9a033 100644 --- a/e2e/clients/axios/index.ts +++ b/e2e/clients/axios/index.ts @@ -4,7 +4,7 @@ import { wrapAxiosWithPayment, decodePaymentResponseHeader } from "@x402/axios"; import { createPublicClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { baseSepolia } from "viem/chains"; -import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactEvmScheme, type ExactEvmSchemeOptions } from "@x402/evm/exact/client"; import { ExactEvmSchemeV1 } from "@x402/evm/v1"; import { toClientEvmSigner } from "@x402/evm"; import { ExactSvmScheme } from "@x402/svm/exact/client"; @@ -34,6 +34,10 @@ const publicClient = createPublicClient({ const evmSigner = toClientEvmSigner(evmAccount, publicClient); +const evmSchemeOptions: ExactEvmSchemeOptions | undefined = process.env.EVM_RPC_URL + ? { rpcUrl: process.env.EVM_RPC_URL } + : undefined; + // Initialize Aptos signer if key is provided let aptosAccount: Account | undefined; if (process.env.APTOS_PRIVATE_KEY) { @@ -52,7 +56,7 @@ if (process.env.STELLAR_PRIVATE_KEY) { } const client = new x402Client() - .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("eip155:*", new ExactEvmScheme(evmSigner, evmSchemeOptions)) .registerV1("base-sepolia", new ExactEvmSchemeV1(evmSigner)) .registerV1("base", new ExactEvmSchemeV1(evmSigner)) .register("solana:*", new ExactSvmScheme(svmSigner)) diff --git a/e2e/clients/fetch/index.ts b/e2e/clients/fetch/index.ts index 57dc68e396..809b7bc292 100644 --- a/e2e/clients/fetch/index.ts +++ b/e2e/clients/fetch/index.ts @@ -3,7 +3,7 @@ import { wrapFetchWithPayment } from "@x402/fetch"; import { createPublicClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { baseSepolia } from "viem/chains"; -import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactEvmScheme, type ExactEvmSchemeOptions } from "@x402/evm/exact/client"; import { ExactEvmSchemeV1 } from "@x402/evm/v1"; import { toClientEvmSigner } from "@x402/evm"; import { ExactSvmScheme } from "@x402/svm/exact/client"; @@ -31,6 +31,10 @@ const publicClient = createPublicClient({ const evmSigner = toClientEvmSigner(evmAccount, publicClient); +const evmSchemeOptions: ExactEvmSchemeOptions | undefined = process.env.EVM_RPC_URL + ? { rpcUrl: process.env.EVM_RPC_URL } + : undefined; + // Initialize Aptos signer if key is provided let aptosAccount: Account | undefined; if (process.env.APTOS_PRIVATE_KEY) { @@ -46,7 +50,7 @@ if (process.env.STELLAR_PRIVATE_KEY) { } const client = new x402Client() - .register("eip155:*", new ExactEvmScheme(evmSigner)) + .register("eip155:*", new ExactEvmScheme(evmSigner, evmSchemeOptions)) .registerV1("base-sepolia", new ExactEvmSchemeV1(evmSigner)) .registerV1("base", new ExactEvmSchemeV1(evmSigner)) .register("solana:*", new ExactSvmScheme(svmSigner)) diff --git a/e2e/clients/go-http/main.go b/e2e/clients/go-http/main.go index c912626ddf..2f85ab762b 100644 --- a/e2e/clients/go-http/main.go +++ b/e2e/clients/go-http/main.go @@ -74,11 +74,13 @@ func main() { return } - // Create x402 client with fluent API - // EIP-2612 gas sponsoring is handled internally by the EVM scheme - // when the server advertises support - no separate extension registration needed. + var evmConfig *evm.ExactEvmSchemeConfig + if evmRpcURL != "" { + evmConfig = &evm.ExactEvmSchemeConfig{RPCURL: evmRpcURL} + } + x402Client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(evmSigner)). + Register("eip155:*", evm.NewExactEvmScheme(evmSigner, evmConfig)). Register("solana:*", svm.NewExactSvmScheme(svmSigner)). RegisterV1("base-sepolia", evmv1.NewExactEvmSchemeV1(evmSigner)). RegisterV1("base", evmv1.NewExactEvmSchemeV1(evmSigner)). diff --git a/e2e/clients/mcp-go/main.go b/e2e/clients/mcp-go/main.go index 52cd2a41b2..4befd7e31d 100644 --- a/e2e/clients/mcp-go/main.go +++ b/e2e/clients/mcp-go/main.go @@ -69,9 +69,13 @@ func main() { } defer session.Close() - // Use X402MCPClient - payment is transparent in CallTool + var evmConfig *evm.ExactEvmSchemeConfig + if rpcURL := os.Getenv("EVM_RPC_URL"); rpcURL != "" { + evmConfig = &evm.ExactEvmSchemeConfig{RPCURL: rpcURL} + } + paymentClient := x402.Newx402Client() - paymentClient.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + paymentClient.Register("eip155:*", evm.NewExactEvmScheme(evmSigner, evmConfig)) x402Mcp := mcp402.NewX402MCPClient(session, paymentClient, mcp402.Options{AutoPayment: mcp402.BoolPtr(true)}) result, err := x402Mcp.CallTool(ctx, endpointPath, map[string]any{ diff --git a/e2e/clients/mcp-typescript/index.ts b/e2e/clients/mcp-typescript/index.ts index 10d2d2c35b..9029b796a5 100644 --- a/e2e/clients/mcp-typescript/index.ts +++ b/e2e/clients/mcp-typescript/index.ts @@ -8,7 +8,7 @@ */ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; -import { ExactEvmScheme } from "@x402/evm/exact/client"; +import { ExactEvmScheme, type ExactEvmSchemeOptions } from "@x402/evm/exact/client"; import { createx402MCPClient } from "@x402/mcp"; import { privateKeyToAccount } from "viem/accounts"; @@ -35,12 +35,14 @@ if (!serverUrl || !endpointPath || !evmPrivateKey) { async function main(): Promise { const evmSigner = privateKeyToAccount(evmPrivateKey); + const evmSchemeOptions: ExactEvmSchemeOptions | undefined = process.env.EVM_RPC_URL + ? { rpcUrl: process.env.EVM_RPC_URL } + : undefined; - // Create x402 MCP client with auto-payment enabled const x402Mcp = createx402MCPClient({ name: "x402-mcp-e2e-client", version: "1.0.0", - schemes: [{ network: "eip155:84532", client: new ExactEvmScheme(evmSigner) }], + schemes: [{ network: "eip155:84532", client: new ExactEvmScheme(evmSigner, evmSchemeOptions) }], autoPayment: true, onPaymentRequested: async () => true, // Auto-approve all payments for e2e }); diff --git a/e2e/facilitators/go/main.go b/e2e/facilitators/go/main.go index 99ed985563..ff55ada83d 100644 --- a/e2e/facilitators/go/main.go +++ b/e2e/facilitators/go/main.go @@ -220,15 +220,6 @@ func (s *realFacilitatorEvmSigner) ReadContract( // 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, @@ -236,12 +227,9 @@ func (s *realFacilitatorEvmSigner) ReadContract( 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) @@ -429,7 +417,7 @@ func (s *realFacilitatorEvmSigner) GetCode(ctx context.Context, address string) return code, nil } -func (s *realFacilitatorEvmSigner) SendRawTransaction(ctx context.Context, signedTx string) (string, error) { +func (s *realFacilitatorEvmSigner) sendRawTransaction(ctx context.Context, signedTx string) (string, error) { txBytes, err := hexutil.Decode(signedTx) if err != nil { return "", fmt.Errorf("failed to decode signed transaction: %w", err) @@ -447,6 +435,30 @@ func (s *realFacilitatorEvmSigner) SendRawTransaction(ctx context.Context, signe return tx.Hash().Hex(), nil } +func (s *realFacilitatorEvmSigner) SendTransactions(ctx context.Context, transactions []erc20approvalgassponsor.TransactionRequest) ([]string, error) { + var hashes []string + for _, tx := range transactions { + var hash string + var err error + if tx.Serialized != "" { + hash, err = s.sendRawTransaction(ctx, tx.Serialized) + } else if tx.Call != nil { + hash, err = s.WriteContract(ctx, tx.Call.Address, tx.Call.ABI, tx.Call.Function, tx.Call.Args...) + } else { + return hashes, fmt.Errorf("transaction_failed: empty transaction request") + } + if err != nil { + return hashes, fmt.Errorf("transaction_failed: %w", err) + } + receipt, err := s.WaitForTransactionReceipt(ctx, hash) + if err != nil || receipt.Status != evmmech.TxStatusSuccess { + return hashes, fmt.Errorf("transaction_failed: %s", hash) + } + hashes = append(hashes, hash) + } + return hashes, nil +} + // Helper functions for type conversion func getStringFromInterface(v interface{}) string { if v == nil { @@ -491,6 +503,11 @@ func createPaymentHash(paymentPayload x402.PaymentPayload) string { return hex.EncodeToString(hash[:]) } +func hashBytes(data []byte) string { + hash := sha256.Sum256(data) + return hex.EncodeToString(hash[:]) +} + // Real SVM facilitator signer type realFacilitatorSvmSigner struct { privateKey solana.PrivateKey @@ -807,11 +824,7 @@ func main() { 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()) + paymentHash := hashBytes(ctx.PayloadBytes) verificationMutex.Lock() verifiedPayments[paymentHash] = time.Now().Unix() verificationMutex.Unlock() @@ -870,10 +883,7 @@ func main() { }). 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()) + paymentHash := hashBytes(ctx.PayloadBytes) verificationMutex.RLock() verificationTimestamp, verified := verifiedPayments[paymentHash] verificationMutex.RUnlock() @@ -902,10 +912,7 @@ func main() { }). 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()) + paymentHash := hashBytes(ctx.PayloadBytes) verificationMutex.Lock() delete(verifiedPayments, paymentHash) verificationMutex.Unlock() @@ -917,10 +924,7 @@ func main() { }). 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()) + paymentHash := hashBytes(ctx.PayloadBytes) verificationMutex.Lock() delete(verifiedPayments, paymentHash) verificationMutex.Unlock() @@ -937,12 +941,6 @@ func main() { // 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{ @@ -951,14 +949,6 @@ func main() { 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{ @@ -992,12 +982,6 @@ func main() { // 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{ @@ -1006,17 +990,6 @@ func main() { 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{ @@ -1033,9 +1006,6 @@ func main() { []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) diff --git a/e2e/facilitators/typescript/index.ts b/e2e/facilitators/typescript/index.ts index 464fafdaeb..8e6579cbde 100644 --- a/e2e/facilitators/typescript/index.ts +++ b/e2e/facilitators/typescript/index.ts @@ -165,10 +165,12 @@ const evmSigner = toFacilitatorEvmSigner({ abi: readonly unknown[]; functionName: string; args: readonly unknown[]; + gas?: bigint; }) => viemClient.writeContract({ ...args, args: args.args || [], + gas: args.gas, }), sendTransaction: (args: { to: `0x${string}`; data: `0x${string}` }) => viemClient.sendTransaction(args), @@ -221,10 +223,47 @@ if (stellarSigner) { facilitator.register(STELLAR_NETWORK as Network, new ExactStellarScheme([stellarSigner])); } +const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3" as const; +const erc20AllowanceAbi = [ + { + inputs: [ + { name: "owner", type: "address" }, + { name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, +] as const; + +const erc20ApprovalSigner = { + ...evmSigner, + sendTransactions: async ( + transactions: (`0x${string}` | { to: `0x${string}`; data: `0x${string}`; gas?: bigint })[], + ): Promise<`0x${string}`[]> => { + const hashes: `0x${string}`[] = []; + for (const tx of transactions) { + let hash: `0x${string}`; + if (typeof tx === "string") { + hash = await viemClient.sendRawTransaction({ serializedTransaction: tx }); + } else { + hash = await viemClient.sendTransaction(tx); + } + const receipt = await viemClient.waitForTransactionReceipt({ hash }); + if (receipt.status !== "success") { + throw new Error(`transaction_failed: ${hash}`); + } + hashes.push(hash); + } + return hashes; + }, +}; + facilitator .registerExtension(BAZAAR) .registerExtension(EIP2612_GAS_SPONSORING) - .registerExtension(createErc20ApprovalGasSponsoringExtension(evmSigner, viemClient)) + .registerExtension(createErc20ApprovalGasSponsoringExtension(erc20ApprovalSigner)) // Lifecycle hooks for payment tracking and discovery .onAfterVerify(async (context) => { // Hook 1: Track verified payment for verifyβ†’settle flow validation diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index efd36bd42e..6cb78a3757 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -786,10 +786,10 @@ importers: 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)) + version: 1.38.4(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.19.0(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@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) express: specifier: ^4.18.2 version: 4.21.2 @@ -1171,9 +1171,6 @@ importers: '@x402/core': specifier: workspace:~ version: link:../../core - '@x402/extensions': - specifier: workspace:~ - version: link:../../extensions 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) @@ -1538,6 +1535,148 @@ importers: 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@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(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/external-proxies/cdp-dev-new: + 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.19.0(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/external-proxies/x402.org: + dependencies: + '@coinbase/x402': + specifier: ^0.7.3 + version: 0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(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/typescript: dependencies: '@aptos-labs/ts-sdk': @@ -2756,6 +2895,9 @@ packages: '@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==} engines: {node: '>=18'} @@ -9434,6 +9576,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'} @@ -10357,6 +10502,26 @@ snapshots: - utf-8-validate - zod + '@base-org/account@1.1.1(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.3(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) + 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-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))) @@ -10364,8 +10529,31 @@ snapshots: '@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.12.2 - axios-retry: 4.5.0(axios@1.12.2) + axios: 1.13.4 + axios-retry: 4.5.0(axios@1.13.4) + jose: 6.1.3 + md5: 2.3.0 + uncrypto: 0.1.3 + viem: 2.45.1(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.2(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.2(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.2(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.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.13.4 + axios-retry: 4.5.0(axios@1.13.4) jose: 6.1.3 md5: 2.3.0 uncrypto: 0.1.3 @@ -10387,8 +10575,8 @@ snapshots: '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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) + axios: 1.13.4 + axios-retry: 4.5.0(axios@1.13.4) jose: 6.1.3 md5: 2.3.0 uncrypto: 0.1.3 @@ -10504,6 +10692,67 @@ snapshots: - utf-8-validate - zod + '@coinbase/wallet-sdk@4.3.6(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.3(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) + transitivePeerDependencies: + - '@types/react' + - bufferutil + - immer + - react + - typescript + - use-sync-external-store + - utf-8-validate + - zod + + '@coinbase/x402@0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(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)(fastestsmallesttextencoderdecoder@1.0.22)(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + x402: 0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(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' + - '@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: esbuild: 0.25.5 @@ -11455,14 +11704,13 @@ snapshots: - utf-8-validate - zod - '@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-controllers@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.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) + '@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.3) + viem: 2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -11491,14 +11739,14 @@ snapshots: - utf-8-validate - zod - '@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-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: '@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-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.1) + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -11527,17 +11775,89 @@ 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.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-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: '@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) + '@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 + - ioredis + - react + - typescript + - uploadthing + - utf-8-validate + - zod + + '@reown/appkit-pay@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(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.3)(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.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(zod@3.25.71) + lit: 3.3.0 + valtio: 1.13.2(react@19.2.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-polyfills@1.7.8': + dependencies: + buffer: 6.0.3 + + '@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: + '@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: - '@azure/app-configuration' @@ -11605,6 +11925,43 @@ snapshots: - valtio - zod + '@reown/appkit-scaffold-ui@1.7.8(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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.3)(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.3)(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.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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-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: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) @@ -11675,6 +12032,41 @@ snapshots: - utf-8-validate - zod + '@reown/appkit-ui@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(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-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) @@ -11751,6 +12143,44 @@ snapshots: - utf-8-validate - zod + '@reown/appkit-utils@1.7.8(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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.3)(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(react@19.2.3) + viem: 2.45.1(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-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) @@ -11848,6 +12278,49 @@ snapshots: - utf-8-validate - zod + '@reown/appkit@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(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.3)(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(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(zod@3.25.71) + '@reown/appkit-ui': 1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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(react@19.2.3) + viem: 2.45.1(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 + '@rollup/rollup-android-arm-eabi@4.52.5': optional: true @@ -11997,6 +12470,10 @@ snapshots: 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.2(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.2(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.19.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -12024,6 +12501,10 @@ snapshots: 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.2(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.2(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.19.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -12582,7 +13063,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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.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) @@ -12596,11 +13077,11 @@ snapshots: '@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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(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(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(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 @@ -12608,27 +13089,27 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/kit@5.0.0(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@8.19.0(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) - '@solana/codecs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/errors': 5.0.0(typescript@5.8.3) - '@solana/functional': 5.0.0(typescript@5.8.3) - '@solana/instruction-plans': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/instructions': 5.0.0(typescript@5.8.3) - '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/programs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@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@7.5.10(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@7.5.10(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) + '@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.19.0(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.19.0(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 @@ -13149,23 +13630,23 @@ snapshots: 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.19.0(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.19.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@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.19.0(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) + '@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) + ws: 8.19.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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: @@ -13260,7 +13741,25 @@ snapshots: - 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))': + '@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.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) @@ -13268,7 +13767,7 @@ snapshots: '@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-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) @@ -13296,24 +13795,6 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/rpc-subscriptions@5.0.0(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': 5.0.0(typescript@5.8.3) - '@solana/fast-stable-stringify': 5.0.0(typescript@5.8.3) - '@solana/functional': 5.0.0(typescript@5.8.3) - '@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@7.5.10(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) - '@solana/subscribable': 5.0.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 5.0.0(typescript@5.8.3) @@ -13441,7 +13922,7 @@ snapshots: '@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 + undici-types: 7.22.0 '@solana/rpc-transport-http@5.0.0(typescript@5.8.3)': dependencies: @@ -13765,7 +14246,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(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) @@ -13773,7 +14254,7 @@ snapshots: '@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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(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) @@ -13782,18 +14263,18 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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) - '@solana/errors': 5.0.0(typescript@5.8.3) - '@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@7.5.10(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) + '@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.19.0(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 @@ -14210,6 +14691,11 @@ snapshots: '@tanstack/query-core': 5.90.8 react: 19.2.1 + '@tanstack/react-query@5.90.8(react@19.2.3)': + dependencies: + '@tanstack/query-core': 5.90.8 + react: 19.2.3 + '@trysound/sax@0.2.0': {} '@tybys/wasm-util@0.10.1': @@ -14870,6 +15356,53 @@ snapshots: - wagmi - zod + '@wagmi/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.71) + '@coinbase/wallet-sdk': 4.3.6(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.71) + '@gemini-wallet/core': 0.2.0(viem@2.45.1(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)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(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.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + viem: 2.45.1(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/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 @@ -14915,6 +15448,21 @@ snapshots: - react - use-sync-external-store + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) + zustand: 5.0.0(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) + optionalDependencies: + '@tanstack/query-core': 5.90.8 + typescript: 5.8.3 + transitivePeerDependencies: + - '@types/react' + - immer + - react + - use-sync-external-store + '@wallet-standard/app@1.1.0': dependencies: '@wallet-standard/base': 1.1.0 @@ -15099,6 +15647,47 @@ snapshots: - utf-8-validate - zod + '@walletconnect/ethereum-provider@2.21.1(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': + dependencies: + '@reown/appkit': 1.7.8(bufferutil@4.0.9)(react@19.2.3)(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/events@1.0.1': dependencies: keyvaluestorage-interface: 1.0.0 @@ -15704,9 +16293,9 @@ snapshots: axe-core@4.11.0: {} - axios-retry@4.5.0(axios@1.12.2): + axios-retry@4.5.0(axios@1.13.4): dependencies: - axios: 1.12.2 + axios: 1.13.4 is-retry-allowed: 2.2.0 axios@1.10.0: @@ -16279,6 +16868,10 @@ snapshots: dependencies: 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.3)): + dependencies: + valtio: 1.13.2(react@19.2.3) + des.js@1.1.0: dependencies: inherits: 2.0.4 @@ -18433,6 +19026,26 @@ snapshots: - immer - use-sync-external-store + porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.45.1(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(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) + optionalDependencies: + '@tanstack/react-query': 5.90.8(react@19.2.3) + react: 19.2.3 + typescript: 5.8.3 + wagmi: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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 + poseidon-lite@0.2.1: {} possible-typed-array-names@1.1.0: {} @@ -18777,7 +19390,7 @@ snapshots: buffer: 6.0.3 eventemitter3: 5.0.1 uuid: 8.3.2 - ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: bufferutil: 4.0.9 utf-8-validate: 5.0.10 @@ -19532,6 +20145,10 @@ snapshots: dependencies: react: 19.2.1 + use-sync-external-store@1.2.0(react@19.2.3): + dependencies: + react: 19.2.3 + use-sync-external-store@1.4.0(react@19.2.0): dependencies: react: 19.2.0 @@ -19540,6 +20157,10 @@ snapshots: dependencies: react: 19.2.1 + use-sync-external-store@1.4.0(react@19.2.3): + dependencies: + react: 19.2.3 + utf-8-validate@5.0.10: dependencies: node-gyp-build: 4.8.4 @@ -19580,6 +20201,14 @@ snapshots: '@types/react': 19.2.2 react: 19.2.1 + valtio@1.13.2(react@19.2.3): + dependencies: + derive-valtio: 0.1.0(valtio@1.13.2(react@19.2.3)) + proxy-compare: 2.6.0 + use-sync-external-store: 1.2.0(react@19.2.3) + optionalDependencies: + react: 19.2.3 + vary@1.1.2: {} viem@2.23.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71): @@ -19929,6 +20558,45 @@ snapshots: - utf-8-validate - zod + wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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.3) + '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + react: 19.2.3 + use-sync-external-store: 1.4.0(react@19.2.3) + viem: 2.45.1(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 + webextension-polyfill@0.10.0: {} webidl-conversions@3.0.1: {} @@ -20063,6 +20731,54 @@ snapshots: bufferutil: 4.0.9 utf-8-validate: 5.0.10 + x402@0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10): + dependencies: + '@scure/base': 1.2.6 + '@solana-program/compute-budget': 0.11.0(@solana/kit@5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@solana-program/token': 0.9.0(@solana/kit@5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@solana-program/token-2022': 0.6.1(@solana/kit@5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@solana/transaction-confirmation': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(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.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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 + xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} @@ -20128,6 +20844,11 @@ snapshots: react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) + zustand@5.0.0(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): + optionalDependencies: + react: 19.2.3 + use-sync-external-store: 1.4.0(react@19.2.3) + 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 @@ -20140,6 +20861,11 @@ snapshots: react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) + zustand@5.0.3(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): + optionalDependencies: + react: 19.2.3 + use-sync-external-store: 1.4.0(react@19.2.3) + 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 @@ -20151,3 +20877,8 @@ snapshots: '@types/react': 19.2.2 react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) + + zustand@5.0.8(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): + optionalDependencies: + react: 19.2.3 + use-sync-external-store: 1.4.0(react@19.2.3) diff --git a/e2e/scripts/permit2-approval.ts b/e2e/scripts/permit2-approval.ts index 819068b055..b8df93cd6c 100644 --- a/e2e/scripts/permit2-approval.ts +++ b/e2e/scripts/permit2-approval.ts @@ -5,8 +5,10 @@ * It can grant unlimited approval or revoke existing approval. * * Usage: - * pnpm tsx scripts/permit2-approval.ts approve # Check and approve if needed - * pnpm tsx scripts/permit2-approval.ts revoke # Revoke Permit2 approval (set allowance to 0) + * pnpm tsx scripts/permit2-approval.ts approve [tokenAddress] + * pnpm tsx scripts/permit2-approval.ts revoke [tokenAddress] + * + * If tokenAddress is not provided, defaults to Base Sepolia USDC. * * Environment variables required: * CLIENT_EVM_PRIVATE_KEY - Private key of the client wallet @@ -19,6 +21,7 @@ import { http, parseAbi, formatUnits, + getAddress, } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; import { baseSepolia } from 'viem/chains'; @@ -60,8 +63,10 @@ async function main() { Permit2 Approval Script Usage: - pnpm tsx scripts/permit2-approval.ts approve # Check and approve Permit2 if needed - pnpm tsx scripts/permit2-approval.ts revoke # Revoke Permit2 approval (set allowance to 0) + pnpm tsx scripts/permit2-approval.ts approve [tokenAddress] + pnpm tsx scripts/permit2-approval.ts revoke [tokenAddress] + +If tokenAddress is not provided, defaults to Base Sepolia USDC. Environment variables required: CLIENT_EVM_PRIVATE_KEY - Private key of the client wallet diff --git a/e2e/servers/hono/test.config.json b/e2e/servers/hono/test.config.json index 3eddf60e4e..be39d73b3d 100644 --- a/e2e/servers/hono/test.config.json +++ b/e2e/servers/hono/test.config.json @@ -19,7 +19,7 @@ "description": "Protected endpoint requiring Permit2 payment", "requiresPayment": true, "protocolFamily": "evm", - "permit2": true + "transferMethod": "permit2" }, { "path": "/protected-permit2-erc20", diff --git a/e2e/servers/next/test.config.json b/e2e/servers/next/test.config.json index 7347eb089c..0e984768ac 100644 --- a/e2e/servers/next/test.config.json +++ b/e2e/servers/next/test.config.json @@ -19,7 +19,7 @@ "description": "Protected Permit2 endpoint using proxy middleware", "requiresPayment": true, "protocolFamily": "evm", - "permit2": true + "transferMethod": "permit2" }, { "path": "/api/protected-permit2-erc20-proxy", diff --git a/e2e/src/discovery.ts b/e2e/src/discovery.ts index 7f9b062ffb..7a01ef55f7 100644 --- a/e2e/src/discovery.ts +++ b/e2e/src/discovery.ts @@ -257,7 +257,6 @@ export class TestDiscovery { }) || []; for (const endpoint of testableEndpoints) { - // Default to EVM if no protocol family specified for backward compatibility const endpointProtocolFamily = endpoint.protocolFamily || 'evm'; // Only create scenarios where client supports endpoint's protocol family @@ -336,9 +335,8 @@ export class TestDiscovery { const transport = client.config.transport || 'http'; const evmTransferMethods = client.config.evm?.transferMethods || ['eip3009']; const evmInfo = protocolFamilies.includes('evm') ? ` evm:${evmTransferMethods.join(',')}` : ''; - log(` - ${client.name} (${client.config.language}) [${transport}] v[${versions.join(', ')}] [${protocolFamilies.join(', ')}]${evmInfo}`); const extInfo = client.config.extensions ? ` {${client.config.extensions.join(', ')}}` : ''; - log(` - ${client.name} (${client.config.language}) [${transport}] v[${versions.join(', ')}] [${protocolFamilies.join(', ')}]${extInfo}`); + log(` - ${client.name} (${client.config.language}) [${transport}] v[${versions.join(', ')}] [${protocolFamilies.join(', ')}]${evmInfo}${extInfo}`); }); log(`πŸ›οΈ Facilitators found: ${facilitators.length}`); diff --git a/e2e/src/types.ts b/e2e/src/types.ts index f4c200557f..cfa2c2940c 100644 --- a/e2e/src/types.ts +++ b/e2e/src/types.ts @@ -50,6 +50,7 @@ export interface TestEndpoint { requiresPayment?: boolean; protocolFamily?: ProtocolFamily; transferMethod?: TransferMethod; + extensions?: string[]; health?: boolean; close?: boolean; } diff --git a/e2e/test.ts b/e2e/test.ts index c08b83a266..9188a2a3a6 100644 --- a/e2e/test.ts +++ b/e2e/test.ts @@ -16,58 +16,20 @@ import { FacilitatorManager } from './src/facilitators/facilitator-manager'; import { waitForHealth } from './src/health'; /** - * Run Permit2 setup script to ensure the client wallet has approved the Permit2 contract + * Revoke Permit2 approval so that gas sponsoring extensions are exercised. + * Sets the Permit2 allowance to 0 for the given token (or USDC by default), + * forcing the client into the EIP-2612 or ERC-20 approval extension path. */ -async function setupPermit2Approval(): Promise { +async function revokePermit2Approval(tokenAddress?: string): Promise { return new Promise((resolve) => { - log('\nπŸ”‘ Setting up Permit2 approval for EVM client wallet...'); + const label = tokenAddress ? `token ${tokenAddress}` : 'USDC (default)'; + verboseLog(` πŸ”“ Revoking Permit2 approval for ${label}...`); - const child = spawn('pnpm', ['permit2:approve'], { - cwd: process.cwd(), - stdio: 'pipe', - shell: true, - }); - - let stderr = ''; - - child.stdout?.on('data', (data) => { - verboseLog(data.toString().trim()); - }); - - child.stderr?.on('data', (data) => { - stderr += data.toString(); - verboseLog(data.toString().trim()); - }); - - child.on('close', (code) => { - if (code === 0) { - log(' βœ… Permit2 approval setup complete'); - resolve(true); - } else { - errorLog(` ❌ Permit2 setup failed (exit code ${code})`); - if (stderr) { - errorLog(` Error: ${stderr}`); - } - resolve(false); - } - }); - - child.on('error', (error) => { - errorLog(` ❌ Failed to run Permit2 setup: ${error.message}`); - resolve(false); - }); - }); -} - -/** - * Revoke Permit2 approval so that EIP-2612 gas sponsoring extension is exercised. - * Sets the Permit2 allowance to 0, forcing the client to use the EIP-2612 permit path. - */ -async function revokePermit2Approval(): Promise { - return new Promise((resolve) => { - verboseLog(' πŸ”“ Revoking Permit2 approval for EIP-2612 test...'); - - const child = spawn('pnpm', ['permit2:revoke'], { + const args = ['scripts/permit2-approval.ts', 'revoke']; + if (tokenAddress) { + args.push(tokenAddress); + } + const child = spawn('tsx', args, { cwd: process.cwd(), stdio: 'pipe', shell: true, @@ -356,31 +318,29 @@ async function runTest() { } log(''); + // Branch coverage assertions for EVM scenarios + const evmScenarios = filteredScenarios.filter(s => s.protocolFamily === 'evm'); + if (evmScenarios.length > 0) { + const hasEip3009 = evmScenarios.some(s => (s.endpoint.transferMethod || 'eip3009') === 'eip3009'); + const hasPermit2 = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2'); + const hasPermit2Eip2612 = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2' && !s.endpoint.extensions?.includes('erc20ApprovalGasSponsoring')); + const hasPermit2Erc20 = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2' && s.endpoint.extensions?.includes('erc20ApprovalGasSponsoring')); + + log('πŸ” EVM Branch Coverage Check:'); + log(` EIP-3009 route: ${hasEip3009 ? 'βœ…' : '❌ MISSING'}`); + log(` Permit2 route: ${hasPermit2 ? 'βœ…' : '❌ MISSING'}`); + log(` Permit2+EIP2612 route: ${hasPermit2Eip2612 ? 'βœ…' : '⚠️ not found (may be covered by permit2 route if eip2612 extension enabled)'}`); + log(` Permit2+ERC20 route: ${hasPermit2Erc20 ? 'βœ…' : '⚠️ not found'}`); + log(''); + } + // Auto-detect Permit2 scenarios const hasPermit2Scenarios = filteredScenarios.some( (s) => s.endpoint.transferMethod === 'permit2' ); - // Check if eip2612GasSponsoring extension should be tested - const hasEip2612Extension = selectedExtensions?.includes('eip2612GasSponsoring') ?? false; - if (hasPermit2Scenarios) { - if (hasEip2612Extension) { - log('πŸ” Permit2 scenarios detected with eip2612GasSponsoring extension'); - } else { - // Standard permit2 flow: ensure approval exists - log('πŸ” Permit2 scenarios detected - checking approval...'); - const setupSuccess = await setupPermit2Approval(); - if (!setupSuccess) { - errorLog( - '\n❌ Failed to setup Permit2 approval. Cannot continue with Permit2 tests.' - ); - errorLog( - 'πŸ’‘ Make sure CLIENT_EVM_PRIVATE_KEY is set and the wallet has USDC.' - ); - process.exit(1); - } - } + log('πŸ” Permit2 scenarios detected β€” approval will be revoked before each test to exercise extension paths'); } // Collect unique facilitators and servers @@ -682,8 +642,9 @@ async function runTest() { const tn = nextTestNumber(); const isEvm = scenario.protocolFamily === 'evm'; - if (hasEip2612Extension && scenario.endpoint.transferMethod === 'permit2') { + if (scenario.endpoint.transferMethod === 'permit2') { await revokePermit2Approval(); + await revokePermit2Approval('0xeED520980fC7C7B4eB379B96d61CEdea2423005a'); } if (isEvm && facilitatorName && evmLock) { diff --git a/examples/go/clients/advanced/all_networks.go b/examples/go/clients/advanced/all_networks.go index b4b508702c..229b102536 100644 --- a/examples/go/clients/advanced/all_networks.go +++ b/examples/go/clients/advanced/all_networks.go @@ -38,7 +38,7 @@ func runAllNetworksExample(ctx context.Context, evmPrivateKey, svmPrivateKey, ur if err != nil { return fmt.Errorf("failed to create EVM signer: %w", err) } - client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) fmt.Printf("βœ… Registered EVM networks (eip155:*)\n") } diff --git a/examples/go/clients/advanced/custom_transport.go b/examples/go/clients/advanced/custom_transport.go index 1ecf3a9bad..2206722bdd 100644 --- a/examples/go/clients/advanced/custom_transport.go +++ b/examples/go/clients/advanced/custom_transport.go @@ -90,7 +90,7 @@ func runCustomTransportExample(ctx context.Context, evmPrivateKey, url string) e // Create x402 client client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) httpClient := x402http.Newx402HTTPClient(client) diff --git a/examples/go/clients/advanced/error_recovery.go b/examples/go/clients/advanced/error_recovery.go index befc8fb3ed..8b65d2599e 100644 --- a/examples/go/clients/advanced/error_recovery.go +++ b/examples/go/clients/advanced/error_recovery.go @@ -38,7 +38,7 @@ func runErrorRecoveryExample(ctx context.Context, evmPrivateKey, url string) err // Create x402 client with comprehensive error handling client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) // Recovery counter recoveryAttempts := 0 diff --git a/examples/go/clients/advanced/hooks.go b/examples/go/clients/advanced/hooks.go index 1026cebb22..0a3bad969e 100644 --- a/examples/go/clients/advanced/hooks.go +++ b/examples/go/clients/advanced/hooks.go @@ -38,7 +38,7 @@ func runHooksExample(ctx context.Context, evmPrivateKey, url string) error { // Create client with scheme registration client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) // Register lifecycle hooks diff --git a/examples/go/clients/advanced/multi_network_priority.go b/examples/go/clients/advanced/multi_network_priority.go index 3eb32b9772..be2145585f 100644 --- a/examples/go/clients/advanced/multi_network_priority.go +++ b/examples/go/clients/advanced/multi_network_priority.go @@ -48,17 +48,17 @@ func runMultiNetworkPriorityExample(ctx context.Context, evmPrivateKey, url stri // Level 1: Specific networks (highest priority) fmt.Println("βœ… Registering Ethereum Mainnet (eip155:1) with mainnet signer") - client.Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner)) + client.Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner, nil)) fmt.Println("βœ… Registering Base Mainnet (eip155:8453) with base signer") - client.Register("eip155:8453", evm.NewExactEvmScheme(baseSigner)) + client.Register("eip155:8453", evm.NewExactEvmScheme(baseSigner, nil)) fmt.Println("βœ… Registering Base Sepolia (eip155:84532) with testnet signer") - client.Register("eip155:84532", evm.NewExactEvmScheme(testnetSigner)) + client.Register("eip155:84532", evm.NewExactEvmScheme(testnetSigner, nil)) // 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)) + client.Register("eip155:*", evm.NewExactEvmScheme(primarySigner, nil)) // Add logging to show which network is being used client.OnBeforePaymentCreation(func(ctx x402.PaymentCreationContext) (*x402.BeforePaymentCreationHookResult, error) { diff --git a/examples/go/clients/custom/main.go b/examples/go/clients/custom/main.go index 8181a23f13..fa1e0dd370 100644 --- a/examples/go/clients/custom/main.go +++ b/examples/go/clients/custom/main.go @@ -70,7 +70,7 @@ func main() { } x402Client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) // Make the request with custom payment handling fmt.Println("πŸ”§ Using custom payment implementation (no wrapper)\n") diff --git a/examples/go/clients/http/builder_pattern.go b/examples/go/clients/http/builder_pattern.go index ec9dd45dd7..1256006bdc 100644 --- a/examples/go/clients/http/builder_pattern.go +++ b/examples/go/clients/http/builder_pattern.go @@ -29,12 +29,12 @@ func createBuilderPatternClient(evmPrivateKey, svmPrivateKey string) (*x402.X402 client := x402.Newx402Client() // Register EVM scheme for all EVM networks - client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) // 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)) + // client.Register("eip155:1", evm.NewExactEvmScheme(ethereumSigner, nil)) // Register SVM scheme if key is provided if svmPrivateKey != "" { diff --git a/examples/go/clients/http/mechanism_helper_registration.go b/examples/go/clients/http/mechanism_helper_registration.go index cf4d79b403..d2fa8cee9c 100644 --- a/examples/go/clients/http/mechanism_helper_registration.go +++ b/examples/go/clients/http/mechanism_helper_registration.go @@ -31,7 +31,7 @@ func createMechanismHelperRegistrationClient(evmPrivateKey, svmPrivateKey string // Register EVM scheme for all EVM networks using wildcard // This registers: // - eip155:* (all EVM networks in v2) - client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) // Register SVM scheme if key is provided if svmPrivateKey != "" { @@ -48,7 +48,7 @@ func createMechanismHelperRegistrationClient(evmPrivateKey, svmPrivateKey string // The fluent API allows chaining for clean code: // client := x402.Newx402Client(). - // Register("eip155:*", evm.NewExactEvmScheme(evmSigner)). + // Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)). // Register("solana:*", svm.NewExactSvmScheme(svmSigner)) return client, nil diff --git a/examples/go/clients/mcp-chatbot/main.go b/examples/go/clients/mcp-chatbot/main.go index 34acea0b8b..4ecfaa5322 100644 --- a/examples/go/clients/mcp-chatbot/main.go +++ b/examples/go/clients/mcp-chatbot/main.go @@ -105,7 +105,7 @@ func run() error { // Create x402 payment client and wrap session paymentClient := x402.Newx402Client() - paymentClient.Register("eip155:84532", evm.NewExactEvmScheme(evmSigner)) + paymentClient.Register("eip155:84532", evm.NewExactEvmScheme(evmSigner, nil)) x402Mcp := mcp.NewX402MCPClient(clientSession, paymentClient, mcp.Options{ AutoPayment: mcp.BoolPtr(true), OnPaymentRequested: func(context mcp.PaymentRequiredContext) (bool, error) { diff --git a/examples/go/clients/mcp/advanced.go b/examples/go/clients/mcp/advanced.go index e08517c469..5855bc0583 100644 --- a/examples/go/clients/mcp/advanced.go +++ b/examples/go/clients/mcp/advanced.go @@ -81,7 +81,7 @@ func runAdvanced() error { // Step 2: Create x402 payment client manually paymentClient := x402.Newx402Client() - paymentClient.Register("eip155:84532", evm.NewExactEvmScheme(evmSigner)) + paymentClient.Register("eip155:84532", evm.NewExactEvmScheme(evmSigner, nil)) // Step 3: Compose into X402MCPClient with session x402Mcp := mcp.NewX402MCPClient(clientSession, paymentClient, mcp.Options{ diff --git a/examples/go/clients/mcp/simple.go b/examples/go/clients/mcp/simple.go index 9b324cbc61..1fc19d0530 100644 --- a/examples/go/clients/mcp/simple.go +++ b/examples/go/clients/mcp/simple.go @@ -73,7 +73,7 @@ func runSimple() error { // Create x402 payment client and wrap session paymentClient := x402.Newx402Client() - paymentClient.Register("eip155:84532", evm.NewExactEvmScheme(evmSigner)) + paymentClient.Register("eip155:84532", evm.NewExactEvmScheme(evmSigner, nil)) x402Mcp := mcp.NewX402MCPClient(clientSession, paymentClient, mcp.Options{ AutoPayment: mcp.BoolPtr(true), OnPaymentRequested: func(context mcp.PaymentRequiredContext) (bool, error) { diff --git a/examples/go/clients/payment-identifier/main.go b/examples/go/clients/payment-identifier/main.go index 602df521a7..5cc78af831 100644 --- a/examples/go/clients/payment-identifier/main.go +++ b/examples/go/clients/payment-identifier/main.go @@ -145,7 +145,7 @@ func main() { // Create client with scheme registration client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) // Generate a unique payment ID for this session paymentID := paymentidentifier.GeneratePaymentID("") diff --git a/examples/typescript/pnpm-lock.yaml b/examples/typescript/pnpm-lock.yaml index 58c3c84532..16ac03175f 100644 --- a/examples/typescript/pnpm-lock.yaml +++ b/examples/typescript/pnpm-lock.yaml @@ -1149,9 +1149,6 @@ importers: '@x402/core': specifier: workspace:~ version: link:../../core - '@x402/extensions': - specifier: workspace:~ - version: link:../../extensions viem: specifier: ^2.39.3 version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -25186,7 +25183,7 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.40.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color diff --git a/go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml b/go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml new file mode 100644 index 0000000000..15b5c015d5 --- /dev/null +++ b/go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml @@ -0,0 +1,3 @@ +kind: changed +body: Replaced SendRawApprovalAndSettle with a generic SendTransactions signer method that accepts an array of transaction requests (pre-signed or unsigned intents). Closed fail-open verification paths, aligned Permit2 amount check to exact match, and improved client extension fallback error handling +time: 2026-03-06T12:00:00.000000-08:00 diff --git a/go/CLIENT.md b/go/CLIENT.md index c78fa1d96a..90bbfbee00 100644 --- a/go/CLIENT.md +++ b/go/CLIENT.md @@ -39,7 +39,7 @@ func main() { // 2. Create x402 client and register schemes client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(signer)) + Register("eip155:*", evm.NewExactEvmScheme(signer, nil)) // 3. Wrap HTTP client httpClient := x402http.WrapHTTPClientWithPayment( @@ -109,7 +109,7 @@ Register mechanisms to enable payment creation for different networks. ```go // All EVM networks -client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) +client.Register("eip155:*", evm.NewExactEvmScheme(evmSigner, nil)) // All Solana networks client.Register("solana:*", svm.NewExactSvmScheme(svmSigner)) @@ -119,13 +119,13 @@ client.Register("solana:*", svm.NewExactSvmScheme(svmSigner)) ```go // Ethereum Mainnet -client.Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner)) +client.Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner, nil)) // Base Mainnet -client.Register("eip155:8453", evm.NewExactEvmScheme(baseSigner)) +client.Register("eip155:8453", evm.NewExactEvmScheme(baseSigner, nil)) // Base Sepolia -client.Register("eip155:84532", evm.NewExactEvmScheme(testnetSigner)) +client.Register("eip155:84532", evm.NewExactEvmScheme(testnetSigner, nil)) ``` #### Registration Precedence @@ -134,8 +134,34 @@ More specific registrations override wildcards: ```go client. - Register("eip155:*", evm.NewExactEvmScheme(defaultSigner)). // Fallback - Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner)) // Override for mainnet + Register("eip155:*", evm.NewExactEvmScheme(defaultSigner, nil)). // Fallback + Register("eip155:1", evm.NewExactEvmScheme(mainnetSigner, nil)) // Override for mainnet +``` + +#### Optional Extension RPC Config (Explicit-Only) + +`NewExactEvmScheme` supports optional RPC config used only for extension +enrichment when signer read/fee capabilities are unavailable. + +No chain-default RPC fallback is applied by the SDK. + +```go +// Per-network explicit registration +client. + Register("eip155:137", evm.NewExactEvmScheme(polygonSigner, &evm.ExactEvmSchemeConfig{ + RPCURL: "https://polygon.example", + })). + Register("eip155:8453", evm.NewExactEvmScheme(baseSigner, &evm.ExactEvmSchemeConfig{ + RPCURL: "https://base.example", + })) + +// Wildcard registration with chain-id map +client.Register("eip155:*", evm.NewExactEvmScheme(defaultSigner, &evm.ExactEvmSchemeConfig{ + RPCByChainID: map[int64]evm.ExactEvmChainConfig{ + 137: {RPCURL: "https://polygon.example"}, + 8453: {RPCURL: "https://base.example"}, + }, +})) ``` ### 4. HTTP Integration diff --git a/go/extensions/erc20approvalgassponsor/resolve_signer_test.go b/go/extensions/erc20approvalgassponsor/resolve_signer_test.go new file mode 100644 index 0000000000..f455a59db5 --- /dev/null +++ b/go/extensions/erc20approvalgassponsor/resolve_signer_test.go @@ -0,0 +1,68 @@ +package erc20approvalgassponsor + +import ( + "context" + "math/big" + "testing" + + evm "github.com/coinbase/x402/go/mechanisms/evm" +) + +type mockApprovalSigner struct { + id string +} + +func (m *mockApprovalSigner) GetAddresses() []string { + return []string{"0x0000000000000000000000000000000000000001"} +} +func (m *mockApprovalSigner) ReadContract(_ context.Context, _ string, _ []byte, _ string, _ ...interface{}) (interface{}, error) { + return big.NewInt(0), nil +} +func (m *mockApprovalSigner) VerifyTypedData(_ context.Context, _ string, _ evm.TypedDataDomain, _ map[string][]evm.TypedDataField, _ string, _ map[string]interface{}, _ []byte) (bool, error) { + return true, nil +} +func (m *mockApprovalSigner) WriteContract(_ context.Context, _ string, _ []byte, _ string, _ ...interface{}) (string, error) { + return "0xtx", nil +} +func (m *mockApprovalSigner) SendTransaction(_ context.Context, _ string, _ []byte) (string, error) { + return "0xtx", nil +} +func (m *mockApprovalSigner) WaitForTransactionReceipt(_ context.Context, _ string) (*evm.TransactionReceipt, error) { + return &evm.TransactionReceipt{Status: evm.TxStatusSuccess}, nil +} +func (m *mockApprovalSigner) GetBalance(_ context.Context, _ string, _ string) (*big.Int, error) { + return big.NewInt(0), nil +} +func (m *mockApprovalSigner) GetChainID(_ context.Context) (*big.Int, error) { + return big.NewInt(8453), nil +} +func (m *mockApprovalSigner) GetCode(_ context.Context, _ string) ([]byte, error) { + return []byte{}, nil +} +func (m *mockApprovalSigner) SendTransactions(_ context.Context, _ []TransactionRequest) ([]string, error) { + return []string{"0xtx"}, nil +} + +func TestResolveSigner_UsesNetworkResolverFirst(t *testing.T) { + defaultSigner := &mockApprovalSigner{id: "default"} + baseSigner := &mockApprovalSigner{id: "base"} + ext := &Erc20ApprovalFacilitatorExtension{ + Signer: baseSigner, + SignerForNetwork: func(network string) Erc20ApprovalGasSponsoringSigner { + if network == "eip155:8453" { + return defaultSigner + } + return nil + }, + } + + resolved := ext.ResolveSigner("eip155:8453") + if resolved == nil || resolved.(*mockApprovalSigner).id != "default" { + t.Fatalf("expected network-specific signer, got %#v", resolved) + } + + resolved = ext.ResolveSigner("eip155:1") + if resolved == nil || resolved.(*mockApprovalSigner).id != "base" { + t.Fatalf("expected fallback base signer, got %#v", resolved) + } +} diff --git a/go/extensions/erc20approvalgassponsor/types.go b/go/extensions/erc20approvalgassponsor/types.go index b60a4e32db..72bcaff908 100644 --- a/go/extensions/erc20approvalgassponsor/types.go +++ b/go/extensions/erc20approvalgassponsor/types.go @@ -50,19 +50,58 @@ type Extension struct { Schema map[string]interface{} `json:"schema"` } -// Erc20ApprovalGasSponsoringSigner extends FacilitatorEvmSigner with raw transaction broadcasting. +// WriteContractCall encapsulates arguments for a WriteContract call, +// used by SendTransactions to describe an unsigned contract call operation. +type WriteContractCall struct { + Address string + ABI []byte + Function string + Args []interface{} +} + +// TransactionRequest represents a single transaction to be executed by the signer. +// Either Serialized (pre-signed raw transaction) or Call (unsigned intent) must be set. +type TransactionRequest struct { + // Serialized is a pre-signed raw transaction hex (0x-prefixed). + // When non-empty, the signer broadcasts it as-is via sendRawTransaction. + Serialized string + // Call is an unsigned contract write for the signer to sign and execute. + // Used when Serialized is empty. + Call *WriteContractCall +} + +// Erc20ApprovalGasSponsoringSigner extends FacilitatorEvmSigner with multi-transaction execution. +// The signer owns the execution strategy (sequential, batched, or atomic bundling via +// Flashbots, multicall, or smart account batching). type Erc20ApprovalGasSponsoringSigner interface { evm.FacilitatorEvmSigner - SendRawTransaction(ctx context.Context, signedTx string) (string, error) + SendTransactions(ctx context.Context, transactions []TransactionRequest) ([]string, error) } // Erc20ApprovalFacilitatorExtension carries the signer; registered with the facilitator. // It implements x402.FacilitatorExtension so it can be registered and retrieved via FacilitatorContext. type Erc20ApprovalFacilitatorExtension struct { Signer Erc20ApprovalGasSponsoringSigner + // Optional network-aware signer resolver. When provided, this takes precedence + // over Signer and allows different settlement signers per network. + SignerForNetwork func(network string) Erc20ApprovalGasSponsoringSigner } // Key returns the extension identifier. func (e *Erc20ApprovalFacilitatorExtension) Key() string { return ERC20ApprovalGasSponsoring.Key() } + +// ResolveSigner returns the signer to use for a given network. +// SignerForNetwork takes precedence when configured. +func (e *Erc20ApprovalFacilitatorExtension) ResolveSigner(network string) Erc20ApprovalGasSponsoringSigner { + if e == nil { + return nil + } + if e.SignerForNetwork != nil { + if signer := e.SignerForNetwork(network); signer != nil { + return signer + } + } + return e.Signer +} diff --git a/go/mechanisms/evm/README.md b/go/mechanisms/evm/README.md index ea1ba8daa6..b290ec8761 100644 --- a/go/mechanisms/evm/README.md +++ b/go/mechanisms/evm/README.md @@ -22,8 +22,10 @@ github.com/coinbase/x402/go/mechanisms/evm/exact/client ``` **Exports:** -- `NewExactEvmScheme(signer)` - Creates client-side EVM exact payment mechanism +- `NewExactEvmScheme(signer, config)` - Creates client-side EVM exact payment mechanism - Used for creating payment payloads that clients sign +- Pass `nil` config for signer-only mode +- Use config to provide explicit RPC URLs for extension enrichment (`RPCURL` or `RPCByChainID`) #### For Servers diff --git a/go/mechanisms/evm/exact/client/eip2612.go b/go/mechanisms/evm/exact/client/eip2612.go index 8e77e088c9..9e1c00ff39 100644 --- a/go/mechanisms/evm/exact/client/eip2612.go +++ b/go/mechanisms/evm/exact/client/eip2612.go @@ -19,7 +19,7 @@ import ( // proxy contract enforces permit2612.value == permittedAmount. func SignEip2612Permit( ctx context.Context, - signer evm.ClientEvmSigner, + signer evm.ClientEvmSignerWithReadContract, tokenAddress string, tokenName string, tokenVersion string, diff --git a/go/mechanisms/evm/exact/client/erc20_approval.go b/go/mechanisms/evm/exact/client/erc20_approval.go index 57600a4020..99f626871e 100644 --- a/go/mechanisms/evm/exact/client/erc20_approval.go +++ b/go/mechanisms/evm/exact/client/erc20_approval.go @@ -47,8 +47,12 @@ func SignErc20ApprovalTransaction( return nil, fmt.Errorf("failed to get transaction count: %w", err) } - // Get fee estimates - maxFeePerGas, maxPriorityFeePerGas, _ := signer.EstimateFeesPerGas(ctx) + // EstimateFeesPerGas returns usable fallback values even on RPC error, + // but guard against nil to avoid panic in DynamicFeeTx construction. + maxFeePerGas, maxPriorityFeePerGas, feeErr := signer.EstimateFeesPerGas(ctx) + if feeErr != nil && (maxFeePerGas == nil || maxPriorityFeePerGas == nil) { + return nil, fmt.Errorf("failed to estimate fees and no fallback available: %w", feeErr) + } // Build EIP-1559 transaction toAddr := common.HexToAddress(normalizedToken) diff --git a/go/mechanisms/evm/exact/client/rpc.go b/go/mechanisms/evm/exact/client/rpc.go new file mode 100644 index 0000000000..c8a6d44182 --- /dev/null +++ b/go/mechanisms/evm/exact/client/rpc.go @@ -0,0 +1,280 @@ +package client + +import ( + "context" + "fmt" + "math/big" + "strings" + "sync" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + goethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + + "github.com/coinbase/x402/go/mechanisms/evm" +) + +// ExactEvmChainConfig configures extension RPC behavior for one chain. +type ExactEvmChainConfig struct { + RPCURL string +} + +// ExactEvmSchemeConfig configures extension RPC behavior for Exact EVM clients. +// If both RPCByChainID and RPCURL are set, chain-specific entries take precedence. +type ExactEvmSchemeConfig struct { + RPCURL string + RPCByChainID map[int64]ExactEvmChainConfig +} + +type rpcCapabilities struct { + client *ethclient.Client +} + +var rpcClientCache sync.Map // map[string]*ethclient.Client + +func getOrCreateRPCClient(ctx context.Context, rpcURL string) (*ethclient.Client, error) { + if existing, ok := rpcClientCache.Load(rpcURL); ok { + if cachedClient, ok := existing.(*ethclient.Client); ok { + return cachedClient, nil + } + } + + client, err := ethclient.DialContext(ctx, rpcURL) + if err != nil { + return nil, err + } + rpcClientCache.Store(rpcURL, client) + return client, nil +} + +func newRPCCapabilities(ctx context.Context, rpcURL string) (*rpcCapabilities, error) { + client, err := getOrCreateRPCClient(ctx, rpcURL) + if err != nil { + return nil, err + } + return &rpcCapabilities{client: client}, nil +} + +func (r *rpcCapabilities) ReadContract( + ctx context.Context, + contractAddress string, + abiBytes []byte, + functionName string, + args ...interface{}, +) (interface{}, error) { + contractABI, err := abi.JSON(strings.NewReader(string(abiBytes))) + if err != nil { + return nil, fmt.Errorf("failed to parse ABI: %w", err) + } + + data, err := contractABI.Pack(functionName, args...) + if err != nil { + return nil, fmt.Errorf("failed to pack method call: %w", err) + } + + addr := common.HexToAddress(contractAddress) + msg := ethereum.CallMsg{ + To: &addr, + Data: data, + } + + result, err := r.client.CallContract(ctx, msg, nil) + if err != nil { + return nil, fmt.Errorf("contract call failed: %w", err) + } + + outputs, err := contractABI.Unpack(functionName, result) + if err != nil { + return nil, fmt.Errorf("failed to unpack result: %w", err) + } + if len(outputs) == 0 { + return nil, nil + } + if len(outputs) == 1 { + return outputs[0], nil + } + return outputs, nil +} + +func (r *rpcCapabilities) GetTransactionCount(ctx context.Context, address string) (uint64, error) { + nonce, err := r.client.PendingNonceAt(ctx, common.HexToAddress(address)) + if err != nil { + return 0, fmt.Errorf("failed to get pending nonce: %w", err) + } + return nonce, nil +} + +func (r *rpcCapabilities) EstimateFeesPerGas(ctx context.Context) (*big.Int, *big.Int, error) { + gwei := big.NewInt(1_000_000_000) + fallbackMax := new(big.Int).Mul(big.NewInt(1), gwei) // 1 gwei + fallbackTip := new(big.Int).Div(gwei, big.NewInt(10)) // 0.1 gwei + + tip, err := r.client.SuggestGasTipCap(ctx) + if err != nil { + return fallbackMax, fallbackTip, err + } + + header, err := r.client.HeaderByNumber(ctx, nil) + if err != nil { + maxFee := new(big.Int).Add(tip, gwei) + return maxFee, tip, err + } + + baseFee := header.BaseFee + if baseFee == nil { + baseFee = gwei + } + maxFee := new(big.Int).Add(new(big.Int).Mul(big.NewInt(2), baseFee), tip) + return maxFee, tip, nil +} + +func (c *ExactEvmScheme) resolveRPCURL(network string) string { + if c.config == nil { + return "" + } + + if len(c.config.RPCByChainID) > 0 { + chainID, err := evm.GetEvmChainId(string(network)) + if err == nil { + if chainConfig, ok := c.config.RPCByChainID[chainID.Int64()]; ok && chainConfig.RPCURL != "" { + return chainConfig.RPCURL + } + } + } + + return c.config.RPCURL +} + +type resolvedReadSigner struct { + base evm.ClientEvmSigner + reader func(ctx context.Context, address string, abi []byte, functionName string, args ...interface{}) (interface{}, error) +} + +func (s *resolvedReadSigner) Address() string { + return s.base.Address() +} + +func (s *resolvedReadSigner) SignTypedData( + ctx context.Context, + domain evm.TypedDataDomain, + types map[string][]evm.TypedDataField, + primaryType string, + message map[string]interface{}, +) ([]byte, error) { + return s.base.SignTypedData(ctx, domain, types, primaryType, message) +} + +func (s *resolvedReadSigner) ReadContract( + ctx context.Context, + address string, + abi []byte, + functionName string, + args ...interface{}, +) (interface{}, error) { + return s.reader(ctx, address, abi, functionName, args...) +} + +type resolvedTxSigner struct { + base evm.ClientEvmSigner + signTx func(ctx context.Context, tx *goethtypes.Transaction) ([]byte, error) + getNonce func(ctx context.Context, address string) (uint64, error) + estimateFees func(ctx context.Context) (maxFeePerGas, maxPriorityFeePerGas *big.Int, err error) +} + +func (s *resolvedTxSigner) Address() string { + return s.base.Address() +} + +func (s *resolvedTxSigner) SignTypedData( + ctx context.Context, + domain evm.TypedDataDomain, + types map[string][]evm.TypedDataField, + primaryType string, + message map[string]interface{}, +) ([]byte, error) { + return s.base.SignTypedData(ctx, domain, types, primaryType, message) +} + +func (s *resolvedTxSigner) SignTransaction(ctx context.Context, tx *goethtypes.Transaction) ([]byte, error) { + return s.signTx(ctx, tx) +} + +func (s *resolvedTxSigner) GetTransactionCount(ctx context.Context, address string) (uint64, error) { + return s.getNonce(ctx, address) +} + +func (s *resolvedTxSigner) EstimateFeesPerGas(ctx context.Context) (*big.Int, *big.Int, error) { + return s.estimateFees(ctx) +} + +func (c *ExactEvmScheme) resolveReadSigner( + ctx context.Context, + network string, +) (evm.ClientEvmSignerWithReadContract, error) { + if signerWithRead, ok := c.signer.(evm.ClientEvmSignerWithReadContract); ok { + return signerWithRead, nil + } + + rpcURL := c.resolveRPCURL(network) + if rpcURL == "" { + return nil, nil + } + + rpcCaps, err := newRPCCapabilities(ctx, rpcURL) + if err != nil { + return nil, err + } + + return &resolvedReadSigner{ + base: c.signer, + reader: rpcCaps.ReadContract, + }, nil +} + +func (c *ExactEvmScheme) resolveTxSigner( + ctx context.Context, + network string, +) (evm.ClientEvmSignerWithTxSigning, error) { + signSigner, ok := c.signer.(evm.ClientEvmSignerWithSignTransaction) + if !ok { + return nil, nil + } + + var getNonceFn func(ctx context.Context, address string) (uint64, error) + if nonceSigner, hasNonce := c.signer.(evm.ClientEvmSignerWithGetTransactionCount); hasNonce { + getNonceFn = nonceSigner.GetTransactionCount + } + + var estimateFeesFn func(ctx context.Context) (maxFeePerGas, maxPriorityFeePerGas *big.Int, err error) + if feeSigner, hasFees := c.signer.(evm.ClientEvmSignerWithEstimateFeesPerGas); hasFees { + estimateFeesFn = feeSigner.EstimateFeesPerGas + } + + if getNonceFn == nil || estimateFeesFn == nil { + rpcURL := c.resolveRPCURL(network) + if rpcURL == "" { + return nil, nil + } + + rpcCaps, err := newRPCCapabilities(ctx, rpcURL) + if err != nil { + return nil, err + } + + if getNonceFn == nil { + getNonceFn = rpcCaps.GetTransactionCount + } + if estimateFeesFn == nil { + estimateFeesFn = rpcCaps.EstimateFeesPerGas + } + } + + return &resolvedTxSigner{ + base: c.signer, + signTx: signSigner.SignTransaction, + getNonce: getNonceFn, + estimateFees: estimateFeesFn, + }, nil +} diff --git a/go/mechanisms/evm/exact/client/rpc_test.go b/go/mechanisms/evm/exact/client/rpc_test.go new file mode 100644 index 0000000000..414b5a89e5 --- /dev/null +++ b/go/mechanisms/evm/exact/client/rpc_test.go @@ -0,0 +1,132 @@ +package client + +import ( + "context" + "math/big" + "testing" + + goethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/coinbase/x402/go/mechanisms/evm" +) + +type rpcTestSigner struct { + address string + signCalls int + nonceCalls int + estimateCalls int +} + +func (s *rpcTestSigner) Address() string { + if s.address == "" { + return "0x1234567890123456789012345678901234567890" + } + return s.address +} + +func (s *rpcTestSigner) SignTypedData( + ctx context.Context, + domain evm.TypedDataDomain, + types map[string][]evm.TypedDataField, + primaryType string, + message map[string]interface{}, +) ([]byte, error) { + return []byte{1, 2, 3}, nil +} + +func (s *rpcTestSigner) SignTransaction(ctx context.Context, tx *goethtypes.Transaction) ([]byte, error) { + s.signCalls++ + return []byte{0x01}, nil +} + +func (s *rpcTestSigner) GetTransactionCount(ctx context.Context, address string) (uint64, error) { + s.nonceCalls++ + return 7, nil +} + +func (s *rpcTestSigner) EstimateFeesPerGas(ctx context.Context) (*big.Int, *big.Int, error) { + s.estimateCalls++ + return big.NewInt(100), big.NewInt(10), nil +} + +func TestResolveRPCURL(t *testing.T) { + scheme := &ExactEvmScheme{ + config: &ExactEvmSchemeConfig{ + RPCURL: "https://default.example", + RPCByChainID: map[int64]ExactEvmChainConfig{ + 8453: {RPCURL: "https://base.example"}, + }, + }, + } + + if got := scheme.resolveRPCURL("eip155:8453"); got != "https://base.example" { + t.Fatalf("expected chain-specific rpc, got %q", got) + } + if got := scheme.resolveRPCURL("eip155:137"); got != "https://default.example" { + t.Fatalf("expected default rpc, got %q", got) + } +} + +func TestResolveTxSignerUsesSignerCapabilitiesFirst(t *testing.T) { + ctx := context.Background() + signer := &rpcTestSigner{} + scheme := &ExactEvmScheme{ + signer: signer, + } + + txSigner, err := scheme.resolveTxSigner(ctx, "eip155:8453") + if err != nil { + t.Fatalf("resolveTxSigner failed: %v", err) + } + if txSigner == nil { + t.Fatal("expected tx signer") + } + + _, err = txSigner.SignTransaction(ctx, nil) + if err != nil { + t.Fatalf("SignTransaction failed: %v", err) + } + _, err = txSigner.GetTransactionCount(ctx, signer.Address()) + if err != nil { + t.Fatalf("GetTransactionCount failed: %v", err) + } + _, _, err = txSigner.EstimateFeesPerGas(ctx) + if err != nil { + t.Fatalf("EstimateFeesPerGas failed: %v", err) + } + + if signer.signCalls != 1 || signer.nonceCalls != 1 || signer.estimateCalls != 1 { + t.Fatalf("expected signer methods to be used, got sign=%d nonce=%d fee=%d", signer.signCalls, signer.nonceCalls, signer.estimateCalls) + } +} + +func TestResolveTxSignerReturnsNilWithoutRequiredCapabilities(t *testing.T) { + ctx := context.Background() + scheme := &ExactEvmScheme{ + signer: &mockMinimalClientSigner{}, + } + + txSigner, err := scheme.resolveTxSigner(ctx, "eip155:8453") + if err != nil { + t.Fatalf("resolveTxSigner failed: %v", err) + } + if txSigner != nil { + t.Fatal("expected nil tx signer when signTransaction capability is missing") + } +} + +type mockMinimalClientSigner struct{} + +func (m *mockMinimalClientSigner) Address() string { + return "0x1234567890123456789012345678901234567890" +} + +func (m *mockMinimalClientSigner) SignTypedData( + ctx context.Context, + domain evm.TypedDataDomain, + types map[string][]evm.TypedDataField, + primaryType string, + message map[string]interface{}, +) ([]byte, error) { + return []byte{0x01}, nil +} diff --git a/go/mechanisms/evm/exact/client/scheme.go b/go/mechanisms/evm/exact/client/scheme.go index daddea3107..2a3aef2f1f 100644 --- a/go/mechanisms/evm/exact/client/scheme.go +++ b/go/mechanisms/evm/exact/client/scheme.go @@ -17,14 +17,16 @@ import ( // ExactEvmScheme implements the SchemeNetworkClient interface for EVM exact payments (V2) type ExactEvmScheme struct { signer evm.ClientEvmSigner + config *ExactEvmSchemeConfig } // NewExactEvmScheme creates a new ExactEvmScheme. -// The signer must implement ReadContract for EIP-2612 gas sponsoring support. -// Use NewClientSignerFromPrivateKeyWithClient to create a signer with RPC connectivity. -func NewExactEvmScheme(signer evm.ClientEvmSigner) *ExactEvmScheme { +// Base flows only require a signer that can sign typed data. +// Extension enrichment paths use optional runtime capabilities. +func NewExactEvmScheme(signer evm.ClientEvmSigner, config *ExactEvmSchemeConfig) *ExactEvmScheme { return &ExactEvmScheme{ signer: signer, + config: config, } } @@ -40,20 +42,15 @@ func (c *ExactEvmScheme) CreatePaymentPayload( ctx context.Context, requirements types.PaymentRequirements, ) (types.PaymentPayload, error) { - // Check asset transfer method assetTransferMethod := evm.AssetTransferMethodEIP3009 // default if requirements.Extra != nil { if method, ok := requirements.Extra["assetTransferMethod"].(string); ok { assetTransferMethod = evm.AssetTransferMethod(method) } } - - // Route based on method if assetTransferMethod == evm.AssetTransferMethodPermit2 { return CreatePermit2Payload(ctx, c.signer, requirements) } - - // Default to EIP-3009 return c.createEIP3009Payload(ctx, requirements) } @@ -66,26 +63,23 @@ func (c *ExactEvmScheme) CreatePaymentPayloadWithExtensions( requirements types.PaymentRequirements, extensions map[string]interface{}, ) (types.PaymentPayload, error) { - // Check asset transfer method assetTransferMethod := evm.AssetTransferMethodEIP3009 if requirements.Extra != nil { if method, ok := requirements.Extra["assetTransferMethod"].(string); ok { assetTransferMethod = evm.AssetTransferMethod(method) } } - if assetTransferMethod == evm.AssetTransferMethodPermit2 { result, err := CreatePermit2Payload(ctx, c.signer, requirements) if err != nil { return types.PaymentPayload{}, err } - // Try EIP-2612 permit first (preferred for compatible tokens) extData, err := c.trySignEip2612Permit(ctx, requirements, result, extensions) - if err == nil && extData != nil { + if extData != nil { result.Extensions = extData - } else { - // Fallback: ERC-20 approval (for tokens without EIP-2612) + } else if err == nil { + // EIP-2612 not applicable β€” try ERC-20 approval fallback erc20ExtData, erc20Err := c.trySignErc20Approval(ctx, requirements, extensions) if erc20Err == nil && erc20ExtData != nil { result.Extensions = erc20ExtData @@ -95,7 +89,6 @@ func (c *ExactEvmScheme) CreatePaymentPayloadWithExtensions( return result, nil } - // Default to EIP-3009 return c.createEIP3009Payload(ctx, requirements) } @@ -106,7 +99,6 @@ func (c *ExactEvmScheme) trySignEip2612Permit( result types.PaymentPayload, extensions map[string]interface{}, ) (map[string]interface{}, error) { - // Check if server advertises eip2612GasSponsoring if extensions == nil { return nil, nil } @@ -114,7 +106,6 @@ func (c *ExactEvmScheme) trySignEip2612Permit( return nil, nil } - // Check that required token metadata is available tokenName, _ := requirements.Extra["name"].(string) tokenVersion, _ := requirements.Extra["version"].(string) if tokenName == "" || tokenVersion == "" { @@ -128,8 +119,16 @@ func (c *ExactEvmScheme) trySignEip2612Permit( tokenAddress := evm.NormalizeAddress(requirements.Asset) + readSigner, err := c.resolveReadSigner(ctx, requirements.Network) + if err != nil { + return nil, err + } + if readSigner == nil { + return nil, nil + } + // Check if user already has sufficient Permit2 allowance - allowanceResult, err := c.signer.ReadContract( + allowanceResult, err := readSigner.ReadContract( ctx, tokenAddress, evm.ERC20AllowanceABI, @@ -161,7 +160,7 @@ func (c *ExactEvmScheme) trySignEip2612Permit( // Sign the EIP-2612 permit with the exact Permit2 permitted amount // (the contract enforces permit2612.value == permit.permitted.amount) - info, err := SignEip2612Permit(ctx, c.signer, tokenAddress, tokenName, tokenVersion, chainID, deadline, requirements.Amount) + info, err := SignEip2612Permit(ctx, readSigner, tokenAddress, tokenName, tokenVersion, chainID, deadline, requirements.Amount) if err != nil { return nil, err } @@ -181,7 +180,6 @@ func (c *ExactEvmScheme) trySignErc20Approval( requirements types.PaymentRequirements, extensions map[string]interface{}, ) (map[string]interface{}, error) { - // Check if server advertises erc20ApprovalGasSponsoring if extensions == nil { return nil, nil } @@ -189,9 +187,11 @@ func (c *ExactEvmScheme) trySignErc20Approval( return nil, nil } - // Signer must support transaction signing - txSigner, ok := c.signer.(evm.ClientEvmSignerWithTxSigning) - if !ok { + txSigner, err := c.resolveTxSigner(ctx, requirements.Network) + if err != nil { + return nil, err + } + if txSigner == nil { return nil, nil } @@ -202,20 +202,22 @@ func (c *ExactEvmScheme) trySignErc20Approval( tokenAddress := evm.NormalizeAddress(requirements.Asset) - // Check if user already has sufficient Permit2 allowance - allowanceResult, err := c.signer.ReadContract( - ctx, - tokenAddress, - evm.ERC20AllowanceABI, - "allowance", - common.HexToAddress(c.signer.Address()), - common.HexToAddress(evm.PERMIT2Address), - ) - if err == nil { - if allowanceBig, ok := allowanceResult.(*big.Int); ok { - requiredAmount, ok := new(big.Int).SetString(requirements.Amount, 10) - if ok && allowanceBig.Cmp(requiredAmount) >= 0 { - return nil, nil // Already approved + // If read capability exists, skip signing when Permit2 allowance is already sufficient. + if readSigner, hasRead := c.signer.(evm.ClientEvmSignerWithReadContract); hasRead { + allowanceResult, err := readSigner.ReadContract( + ctx, + tokenAddress, + evm.ERC20AllowanceABI, + "allowance", + common.HexToAddress(c.signer.Address()), + common.HexToAddress(evm.PERMIT2Address), + ) + if err == nil { + if allowanceBig, ok := allowanceResult.(*big.Int); ok { + requiredAmount, ok := new(big.Int).SetString(requirements.Amount, 10) + if ok && allowanceBig.Cmp(requiredAmount) >= 0 { + return nil, nil // Already approved + } } } } diff --git a/go/mechanisms/evm/exact/facilitator/errors.go b/go/mechanisms/evm/exact/facilitator/errors.go index 46dd1bb4bc..0c4d276633 100644 --- a/go/mechanisms/evm/exact/facilitator/errors.go +++ b/go/mechanisms/evm/exact/facilitator/errors.go @@ -37,14 +37,14 @@ const ( ErrUnsupportedPayloadType = "unsupported_payload_type" // Permit2 verify errors - ErrPermit2InvalidSpender = "invalid_permit2_spender" - ErrPermit2RecipientMismatch = "invalid_permit2_recipient_mismatch" - ErrPermit2DeadlineExpired = "permit2_deadline_expired" - ErrPermit2NotYetValid = "permit2_not_yet_valid" - ErrPermit2InsufficientAmount = "permit2_insufficient_amount" - ErrPermit2TokenMismatch = "permit2_token_mismatch" - ErrPermit2InvalidSignature = "invalid_permit2_signature" - ErrPermit2AllowanceRequired = "permit2_allowance_required" + ErrPermit2InvalidSpender = "invalid_permit2_spender" + ErrPermit2RecipientMismatch = "invalid_permit2_recipient_mismatch" + ErrPermit2DeadlineExpired = "permit2_deadline_expired" + ErrPermit2NotYetValid = "permit2_not_yet_valid" + ErrPermit2AmountMismatch = "permit2_amount_mismatch" + ErrPermit2TokenMismatch = "permit2_token_mismatch" + ErrPermit2InvalidSignature = "invalid_permit2_signature" + ErrPermit2AllowanceRequired = "permit2_allowance_required" // Permit2 settle errors (from contract reverts) ErrPermit2InvalidAmount = "permit2_invalid_amount" diff --git a/go/mechanisms/evm/exact/facilitator/permit2.go b/go/mechanisms/evm/exact/facilitator/permit2.go index e21ff78899..77ddc5fcf0 100644 --- a/go/mechanisms/evm/exact/facilitator/permit2.go +++ b/go/mechanisms/evm/exact/facilitator/permit2.go @@ -84,8 +84,8 @@ func VerifyPermit2( if !ok { return nil, x402.NewVerifyError(ErrInvalidRequiredAmount, payer, "invalid required amount format") } - if authAmount.Cmp(requiredAmount) < 0 { - return nil, x402.NewVerifyError(ErrPermit2InsufficientAmount, payer, "insufficient amount") + if authAmount.Cmp(requiredAmount) != 0 { + return nil, x402.NewVerifyError(ErrPermit2AmountMismatch, payer, "amount mismatch") } // Verify token matches @@ -104,36 +104,18 @@ func VerifyPermit2( return nil, x402.NewVerifyError(ErrPermit2InvalidSignature, payer, "invalid signature") } - // Check Permit2 allowance - allowance, err := signer.ReadContract(ctx, tokenAddress, evm.ERC20AllowanceABI, "allowance", + needsExtension := true + allowance, allowanceErr := signer.ReadContract(ctx, tokenAddress, evm.ERC20AllowanceABI, "allowance", common.HexToAddress(payer), common.HexToAddress(evm.PERMIT2Address)) - if err == nil { - if allowanceBig, ok := allowance.(*big.Int); ok && allowanceBig.Cmp(requiredAmount) < 0 { - // Allowance insufficient - try EIP-2612 first, then ERC-20 approval extension - eip2612Info, _ := eip2612gassponsor.ExtractEip2612GasSponsoringInfo(payload.Extensions) - if eip2612Info != nil { - // Validate the EIP-2612 extension data - if validErr := validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); validErr != "" { - return nil, x402.NewVerifyError(validErr, payer, "eip2612 validation failed") - } - // EIP-2612 extension is valid, allowance will be set during settlement - } else { - // Try ERC-20 approval extension - erc20Info, _ := erc20approvalgassponsor.ExtractInfo(payload.Extensions) - if erc20Info != nil && facilCtx != nil { - ext, ok := facilCtx.GetExtension(erc20approvalgassponsor.ERC20ApprovalGasSponsoring.Key()).(*erc20approvalgassponsor.Erc20ApprovalFacilitatorExtension) - if ok && ext != nil && ext.Signer != nil { - if reason, msg := ValidateErc20ApprovalForPayment(erc20Info, payer, tokenAddress); reason != "" { - return nil, x402.NewVerifyError(reason, payer, msg) - } - // ERC-20 approval valid, tx will be broadcast during settlement - } else { - return nil, x402.NewVerifyError(ErrPermit2AllowanceRequired, payer, "permit2 allowance required") - } - } else { - return nil, x402.NewVerifyError(ErrPermit2AllowanceRequired, payer, "permit2 allowance required") - } - } + if allowanceErr == nil { + if allowanceBig, ok := allowance.(*big.Int); ok && allowanceBig.Cmp(requiredAmount) >= 0 { + needsExtension = false + } + } + + if needsExtension { + if extErr := verifyPermit2Extensions(payload, payer, tokenAddress, facilCtx); extErr != nil { + return nil, extErr } } @@ -149,6 +131,41 @@ func VerifyPermit2( }, nil } +// verifyPermit2Extensions validates gas-sponsoring extensions when Permit2 allowance +// is insufficient or could not be read. Returns nil if a valid extension is found, +// or a VerifyError if none are present/valid. +func verifyPermit2Extensions( + payload types.PaymentPayload, + payer string, + tokenAddress string, + facilCtx *x402.FacilitatorContext, +) error { + eip2612Info, _ := eip2612gassponsor.ExtractEip2612GasSponsoringInfo(payload.Extensions) + if eip2612Info != nil { + if validErr := validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); validErr != "" { + return x402.NewVerifyError(validErr, payer, "eip2612 validation failed") + } + return nil + } + + erc20Info, _ := erc20approvalgassponsor.ExtractInfo(payload.Extensions) + if erc20Info != nil && facilCtx != nil { + ext, ok := facilCtx.GetExtension(erc20approvalgassponsor.ERC20ApprovalGasSponsoring.Key()).(*erc20approvalgassponsor.Erc20ApprovalFacilitatorExtension) + var extensionSigner erc20approvalgassponsor.Erc20ApprovalGasSponsoringSigner + if ok && ext != nil { + extensionSigner = ext.ResolveSigner(payload.Accepted.Network) + } + if extensionSigner != nil { + if reason, msg := ValidateErc20ApprovalForPayment(erc20Info, payer, tokenAddress); reason != "" { + return x402.NewVerifyError(reason, payer, msg) + } + return nil + } + } + + return x402.NewVerifyError(ErrPermit2AllowanceRequired, payer, "permit2 allowance required") +} + // SettlePermit2 settles a Permit2 payment by calling x402ExactPermit2Proxy.settle(). func SettlePermit2( ctx context.Context, @@ -222,7 +239,6 @@ func SettlePermit2( ValidAfter: validAfter, } - // Check for EIP-2612 gas sponsoring extension eip2612Info, _ := eip2612gassponsor.ExtractEip2612GasSponsoringInfo(payload.Extensions) erc20Info, _ := erc20approvalgassponsor.ExtractInfo(payload.Extensions) @@ -271,38 +287,29 @@ func SettlePermit2( signatureBytes, ) case erc20Info != nil && facilCtx != nil: - // ERC-20 approval path: broadcast pre-signed approve tx, then settle + // Branch: ERC-20 approval gas sponsoring (broadcast approval + settle via extension signer) ext, ok := facilCtx.GetExtension(erc20approvalgassponsor.ERC20ApprovalGasSponsoring.Key()).(*erc20approvalgassponsor.Erc20ApprovalFacilitatorExtension) - if ok && ext != nil && ext.Signer != nil { - // 1. Broadcast the pre-signed approve transaction - approveTxHash, broadcastErr := ext.Signer.SendRawTransaction(ctx, erc20Info.SignedTransaction) - if broadcastErr != nil { - return nil, x402.NewSettleError(ErrErc20ApprovalBroadcastFailed, payer, network, "", broadcastErr.Error()) + var extensionSigner erc20approvalgassponsor.Erc20ApprovalGasSponsoringSigner + if ok && ext != nil { + extensionSigner = ext.ResolveSigner(payload.Accepted.Network) + } + if extensionSigner != nil { + settle := erc20approvalgassponsor.WriteContractCall{ + Address: evm.X402ExactPermit2ProxyAddress, + ABI: evm.X402ExactPermit2ProxySettleABI, + Function: evm.FunctionSettle, + Args: []interface{}{permitStruct, common.HexToAddress(payer), witnessStruct, signatureBytes}, } - - // 2. Wait for approve tx confirmation - approveReceipt, receiptErr := ext.Signer.WaitForTransactionReceipt(ctx, approveTxHash) - if receiptErr != nil || approveReceipt.Status != evm.TxStatusSuccess { - msg := "approve tx failed" - if receiptErr != nil { - msg = receiptErr.Error() - } - return nil, x402.NewSettleError(ErrErc20ApprovalBroadcastFailed, payer, network, approveTxHash, msg) + txHashes, sendErr := extensionSigner.SendTransactions(ctx, []erc20approvalgassponsor.TransactionRequest{ + {Serialized: erc20Info.SignedTransaction}, + {Call: &settle}, + }) + if sendErr != nil { + err = sendErr + } else if len(txHashes) > 0 { + txHash = txHashes[len(txHashes)-1] } - - // 3. Call settle via extension signer - txHash, err = ext.Signer.WriteContract( - ctx, - evm.X402ExactPermit2ProxyAddress, - evm.X402ExactPermit2ProxySettleABI, - evm.FunctionSettle, - permitStruct, - common.HexToAddress(payer), - witnessStruct, - signatureBytes, - ) } else { - // Extension not properly configured, fall through to standard settle txHash, err = signer.WriteContract( ctx, evm.X402ExactPermit2ProxyAddress, @@ -315,7 +322,6 @@ func SettlePermit2( ) } default: - // Standard settle - no gas sponsoring extension txHash, err = signer.WriteContract( ctx, evm.X402ExactPermit2ProxyAddress, @@ -334,7 +340,15 @@ func SettlePermit2( } // Wait for transaction confirmation - receipt, err := signer.WaitForTransactionReceipt(ctx, txHash) + receiptWaitSigner := signer + if erc20Info != nil && facilCtx != nil { + if ext, ok := facilCtx.GetExtension(erc20approvalgassponsor.ERC20ApprovalGasSponsoring.Key()).(*erc20approvalgassponsor.Erc20ApprovalFacilitatorExtension); ok && ext != nil { + if extensionSigner := ext.ResolveSigner(payload.Accepted.Network); extensionSigner != nil { + receiptWaitSigner = extensionSigner + } + } + } + receipt, err := receiptWaitSigner.WaitForTransactionReceipt(ctx, txHash) if err != nil { return nil, x402.NewSettleError(ErrFailedToGetReceipt, payer, network, txHash, err.Error()) } @@ -442,6 +456,8 @@ func parsePermit2Error(err error) string { return ErrPermit2InvalidSignature case strings.Contains(msg, "InvalidNonce"): return ErrPermit2InvalidNonce + case strings.Contains(msg, "erc20_approval_tx_failed"): + return ErrErc20ApprovalBroadcastFailed default: return ErrFailedToExecuteTransfer } diff --git a/go/mechanisms/evm/exact/facilitator/scheme.go b/go/mechanisms/evm/exact/facilitator/scheme.go index a9dbe8c365..ca3e240ade 100644 --- a/go/mechanisms/evm/exact/facilitator/scheme.go +++ b/go/mechanisms/evm/exact/facilitator/scheme.go @@ -78,8 +78,9 @@ func (f *ExactEvmScheme) Verify( requirements types.PaymentRequirements, fctx *x402.FacilitatorContext, ) (*x402.VerifyResponse, error) { - // Check if this is a Permit2 payload and route accordingly - if evm.IsPermit2Payload(payload.Payload) { + isPermit2 := evm.IsPermit2Payload(payload.Payload) + + if isPermit2 { permit2Payload, err := evm.Permit2PayloadFromMap(payload.Payload) if err != nil { return nil, x402.NewVerifyError(ErrInvalidPayload, "", fmt.Sprintf("failed to parse Permit2 payload: %s", err.Error())) @@ -87,7 +88,6 @@ func (f *ExactEvmScheme) Verify( return VerifyPermit2(ctx, f.signer, payload, requirements, permit2Payload, fctx) } - // Default to EIP-3009 verification return f.verifyEIP3009(ctx, payload, requirements) } @@ -230,8 +230,9 @@ func (f *ExactEvmScheme) Settle( requirements types.PaymentRequirements, fctx *x402.FacilitatorContext, ) (*x402.SettleResponse, error) { - // Check if this is a Permit2 payload and route accordingly - if evm.IsPermit2Payload(payload.Payload) { + isPermit2 := evm.IsPermit2Payload(payload.Payload) + + if isPermit2 { permit2Payload, err := evm.Permit2PayloadFromMap(payload.Payload) if err != nil { network := x402.Network(payload.Accepted.Network) @@ -240,7 +241,6 @@ func (f *ExactEvmScheme) Settle( return SettlePermit2(ctx, f.signer, payload, requirements, permit2Payload, fctx) } - // Default to EIP-3009 settlement return f.settleEIP3009(ctx, payload, requirements) } diff --git a/go/mechanisms/evm/types.go b/go/mechanisms/evm/types.go index 5c705196e4..04a18cbc8a 100644 --- a/go/mechanisms/evm/types.go +++ b/go/mechanisms/evm/types.go @@ -189,32 +189,55 @@ func IsEIP3009Payload(data map[string]interface{}) bool { // Required for the ERC-20 approval gas sponsoring extension, where the client signs // (but does not broadcast) an approve(Permit2, MaxUint256) transaction. type ClientEvmSignerWithTxSigning interface { + ClientEvmSignerWithSignTransaction + ClientEvmSignerWithGetTransactionCount + ClientEvmSignerWithEstimateFeesPerGas +} + +// ClientEvmSignerWithSignTransaction extends ClientEvmSigner with raw tx signing. +type ClientEvmSignerWithSignTransaction interface { ClientEvmSigner // SignTransaction signs an EIP-1559 transaction and returns the RLP-encoded bytes. SignTransaction(ctx context.Context, tx *goethtypes.Transaction) ([]byte, error) +} + +// ClientEvmSignerWithGetTransactionCount extends ClientEvmSigner with nonce lookup. +type ClientEvmSignerWithGetTransactionCount interface { + ClientEvmSigner // GetTransactionCount returns the pending nonce for an address. GetTransactionCount(ctx context.Context, address string) (uint64, error) +} + +// ClientEvmSignerWithEstimateFeesPerGas extends ClientEvmSigner with fee estimation. +type ClientEvmSignerWithEstimateFeesPerGas interface { + ClientEvmSigner // EstimateFeesPerGas returns the EIP-1559 maxFeePerGas and maxPriorityFeePerGas. EstimateFeesPerGas(ctx context.Context) (maxFeePerGas, maxPriorityFeePerGas *big.Int, err error) } -// ClientEvmSigner defines the interface for client-side EVM signing operations. +// ClientEvmSignerWithReadContract extends ClientEvmSigner with on-chain read capability. +// Used by extension enrichment paths (EIP-2612 nonce lookup, allowance checks). +type ClientEvmSignerWithReadContract interface { + ClientEvmSigner + + // ReadContract reads data from a smart contract. + ReadContract(ctx context.Context, address string, abi []byte, functionName string, args ...interface{}) (interface{}, error) +} + +// ClientEvmSigner defines the minimal interface for client-side EVM signing operations. // -// Typically created via NewClientSignerFromPrivateKeyWithClient which provides -// both signing and on-chain read capability. The ReadContract method is required -// for EIP-2612 gas sponsoring (querying nonces and checking allowances). +// Base payment signing only requires address + typed-data signing. +// Optional extension flows can use additional capability interfaces like +// ClientEvmSignerWithReadContract and ClientEvmSignerWithTxSigning. type ClientEvmSigner interface { // Address returns the signer's Ethereum address Address() string // SignTypedData signs EIP-712 typed data SignTypedData(ctx context.Context, domain TypedDataDomain, types map[string][]TypedDataField, primaryType string, message map[string]interface{}) ([]byte, error) - - // ReadContract reads data from a smart contract - ReadContract(ctx context.Context, address string, abi []byte, functionName string, args ...interface{}) (interface{}, error) } // FacilitatorEvmSigner defines the interface for facilitator EVM operations diff --git a/go/test/integration/evm_test.go b/go/test/integration/evm_test.go index 5cbc3303b2..c1bc176dfb 100644 --- a/go/test/integration/evm_test.go +++ b/go/test/integration/evm_test.go @@ -161,7 +161,9 @@ func (s *realFacilitatorEvmSigner) sendTxWithRetry(ctx context.Context, to commo err = s.ethClient.SendTransaction(ctx, signedTx) if err != nil { - if strings.Contains(err.Error(), "replacement transaction underpriced") && attempt < maxRetries { + if (strings.Contains(err.Error(), "replacement transaction underpriced") || + strings.Contains(err.Error(), "nonce too low") || + strings.Contains(err.Error(), "already known")) && attempt < maxRetries { time.Sleep(time.Duration(2*(attempt+1)) * time.Second) continue } @@ -342,7 +344,7 @@ func TestEVMIntegrationV2(t *testing.T) { // Setup client with EVM v2 scheme client := x402.Newx402Client() - evmClient := evmclient.NewExactEvmScheme(clientSigner) + evmClient := evmclient.NewExactEvmScheme(clientSigner, nil) // Register for Base Sepolia client.Register("eip155:84532", evmClient) @@ -526,7 +528,7 @@ func TestEVMIntegrationV2Permit2(t *testing.T) { // Setup client with EVM v2 scheme client := x402.Newx402Client() - evmClient := evmclient.NewExactEvmScheme(clientSigner) + evmClient := evmclient.NewExactEvmScheme(clientSigner, nil) client.Register("eip155:84532", evmClient) // Create facilitator signer with Permit2 support @@ -827,7 +829,9 @@ func (s *permit2FacilitatorEvmSigner) sendTxWithRetry(ctx context.Context, to co err = s.ethClient.SendTransaction(ctx, signedTx) if err != nil { - if strings.Contains(err.Error(), "replacement transaction underpriced") && attempt < maxRetries { + if (strings.Contains(err.Error(), "replacement transaction underpriced") || + strings.Contains(err.Error(), "nonce too low") || + strings.Contains(err.Error(), "already known")) && attempt < maxRetries { time.Sleep(time.Duration(2*(attempt+1)) * time.Second) continue } diff --git a/go/test/integration/mcp_evm_test.go b/go/test/integration/mcp_evm_test.go index c2ce1a54d2..ce5c75c1c4 100644 --- a/go/test/integration/mcp_evm_test.go +++ b/go/test/integration/mcp_evm_test.go @@ -74,7 +74,7 @@ func TestMCPEVMIntegration(t *testing.T) { } paymentClient := x402.Newx402Client() - evmClientScheme := evmclient.NewExactEvmScheme(clientSigner) + evmClientScheme := evmclient.NewExactEvmScheme(clientSigner, nil) paymentClient.Register(TEST_NETWORK, evmClientScheme) // Get client address diff --git a/go/test/unit/evm_client_facilitator_test.go b/go/test/unit/evm_client_facilitator_test.go index 391b10c336..5b6970d300 100644 --- a/go/test/unit/evm_client_facilitator_test.go +++ b/go/test/unit/evm_client_facilitator_test.go @@ -190,7 +190,7 @@ func (m *mockFacilitatorSigner) VerifyTypedData( // TestExactEvmSchemeScheme tests the Scheme() method func TestExactEvmSchemeScheme(t *testing.T) { signer := &mockClientSigner{} - client := evmclient.NewExactEvmScheme(signer) + client := evmclient.NewExactEvmScheme(signer, nil) if client.Scheme() != evm.SchemeExact { t.Errorf("Expected scheme %s, got %s", evm.SchemeExact, client.Scheme()) @@ -201,7 +201,7 @@ func TestExactEvmSchemeScheme(t *testing.T) { func TestCreatePaymentPayloadEIP3009(t *testing.T) { ctx := context.Background() signer := &mockClientSigner{address: "0xClientAddress1234567890123456789012"} - client := evmclient.NewExactEvmScheme(signer) + client := evmclient.NewExactEvmScheme(signer, nil) t.Run("Creates valid EIP-3009 payload", func(t *testing.T) { requirements := types.PaymentRequirements{ @@ -299,7 +299,7 @@ func TestCreatePaymentPayloadEIP3009(t *testing.T) { func TestCreatePaymentPayloadPermit2(t *testing.T) { ctx := context.Background() signer := &mockClientSigner{address: "0xClientAddress1234567890123456789012"} - client := evmclient.NewExactEvmScheme(signer) + client := evmclient.NewExactEvmScheme(signer, nil) t.Run("Creates valid Permit2 payload", func(t *testing.T) { requirements := types.PaymentRequirements{ @@ -838,7 +838,7 @@ func TestCreatePaymentPayloadWithExtensions_EIP2612(t *testing.T) { t.Run("Creates EIP-2612 extension when server advertises and allowance is 0", func(t *testing.T) { signer := &mockClientSigner{address: "0xClientAddress1234567890123456789012"} - client := evmclient.NewExactEvmScheme(signer) + client := evmclient.NewExactEvmScheme(signer, nil) requirements := types.PaymentRequirements{ Scheme: evm.SchemeExact, @@ -879,7 +879,7 @@ func TestCreatePaymentPayloadWithExtensions_EIP2612(t *testing.T) { t.Run("No extension when server does not advertise eip2612GasSponsoring", func(t *testing.T) { signer := &mockClientSigner{address: "0xClientAddress1234567890123456789012"} - client := evmclient.NewExactEvmScheme(signer) + client := evmclient.NewExactEvmScheme(signer, nil) requirements := types.PaymentRequirements{ Scheme: evm.SchemeExact, @@ -909,7 +909,7 @@ func TestCreatePaymentPayloadWithExtensions_EIP2612(t *testing.T) { t.Run("No extension when token metadata missing", func(t *testing.T) { signer := &mockClientSigner{address: "0xClientAddress1234567890123456789012"} - client := evmclient.NewExactEvmScheme(signer) + client := evmclient.NewExactEvmScheme(signer, nil) requirements := types.PaymentRequirements{ Scheme: evm.SchemeExact, diff --git a/go/test/unit/evm_test.go b/go/test/unit/evm_test.go index a8ddb80ba0..e0363dc0aa 100644 --- a/go/test/unit/evm_test.go +++ b/go/test/unit/evm_test.go @@ -86,7 +86,7 @@ func TestEVMVersionMismatch(t *testing.T) { // Setup V2 client clientSigner := &mockClientEvmSigner{} client := x402.Newx402Client() - evmClient := evmclient.NewExactEvmScheme(clientSigner) + evmClient := evmclient.NewExactEvmScheme(clientSigner, nil) client.Register("eip155:8453", evmClient) // V2 requirements (typed) @@ -129,7 +129,7 @@ func TestEVMDualVersionSupport(t *testing.T) { client.RegisterV1("base", evmClientV1) // Register V2 implementation with CAIP-2 - evmClient := evmclient.NewExactEvmScheme(clientSigner) + evmClient := evmclient.NewExactEvmScheme(clientSigner, nil) client.Register("eip155:8453", evmClient) // V1 requirements use legacy network name @@ -195,7 +195,7 @@ func TestEVMDualVersionSupport(t *testing.T) { client.RegisterV1("base", evmClientV1) // Register V2 implementation with CAIP-2 - evmClient := evmclient.NewExactEvmScheme(clientSigner) + evmClient := evmclient.NewExactEvmScheme(clientSigner, nil) client.Register("eip155:8453", evmClient) // V2 requirements use CAIP-2 diff --git a/typescript/.changeset/improve-permit2-gas-sponsoring.md b/typescript/.changeset/improve-permit2-gas-sponsoring.md new file mode 100644 index 0000000000..612cb95178 --- /dev/null +++ b/typescript/.changeset/improve-permit2-gas-sponsoring.md @@ -0,0 +1,6 @@ +--- +'@x402/evm': minor +'@x402/extensions': minor +--- + +Replaced `sendRawApprovalAndSettle` with a generic `sendTransactions` signer method that accepts an array of pre-signed serialized transactions or unsigned call intents. The signer owns execution strategy (sequential, batched, or atomic bundling). Closed fail-open verification paths, aligned Permit2 amount check to exact match, and added `signerForNetwork` to the extensions package. diff --git a/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/index.ts b/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/index.ts index 3b73c68ab3..d12339b05d 100644 --- a/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/index.ts +++ b/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/index.ts @@ -39,6 +39,7 @@ // Export types export type { + TransactionRequest, Erc20ApprovalGasSponsoringInfo, Erc20ApprovalGasSponsoringServerInfo, Erc20ApprovalGasSponsoringExtension, diff --git a/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/types.ts b/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/types.ts index 69a13e651c..5876aa725a 100644 --- a/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/types.ts +++ b/typescript/packages/extensions/src/erc20-approval-gas-sponsoring/types.ts @@ -9,13 +9,22 @@ import type { FacilitatorExtension } from "@x402/core/types"; +/** + * A single transaction to be executed by the signer. + * - `0x${string}`: a pre-signed serialized transaction (broadcast as-is via sendRawTransaction) + * - `{ to, data, gas? }`: an unsigned call intent (signer signs and broadcasts) + */ +export type TransactionRequest = + | `0x${string}` + | { to: `0x${string}`; data: `0x${string}`; gas?: bigint }; + /** * Signer capability carried by the ERC-20 approval extension when registered in a facilitator. * - * Mirrors FacilitatorEvmSigner (from @x402/evm) plus `sendRawTransaction`. - * The extension signer owns the full approve+settle flow: it broadcasts the - * pre-signed approval transaction AND executes the Permit2 settle call, enabling - * production implementations to bundle both atomically (e.g., Flashbots, multicall). + * Mirrors FacilitatorEvmSigner (from @x402/evm) plus `sendTransactions`. + * The signer owns execution of multiple transactions, enabling production implementations + * to bundle them atomically (e.g., Flashbots, multicall, smart account batching) + * while simpler implementations can execute them sequentially. * * The method signatures are duplicated here (rather than extending FacilitatorEvmSigner) * to avoid a circular dependency between @x402/extensions and @x402/evm. @@ -41,11 +50,12 @@ export interface Erc20ApprovalGasSponsoringSigner { abi: readonly unknown[]; functionName: string; args: readonly unknown[]; + gas?: bigint; }): Promise<`0x${string}`>; sendTransaction(args: { to: `0x${string}`; data: `0x${string}` }): Promise<`0x${string}`>; waitForTransactionReceipt(args: { hash: `0x${string}` }): Promise<{ status: string }>; getCode(args: { address: `0x${string}` }): Promise<`0x${string}` | undefined>; - sendRawTransaction(args: { serializedTransaction: `0x${string}` }): Promise<`0x${string}`>; + sendTransactions(transactions: TransactionRequest[]): Promise<`0x${string}`[]>; } /** @@ -61,54 +71,48 @@ export const ERC20_APPROVAL_GAS_SPONSORING_VERSION = "1"; /** * Extended extension object registered in a facilitator via registerExtension(). * Carries the signer that owns the full approve+settle flow for ERC-20 tokens - * that lack EIP-2612. The signer must have all FacilitatorEvmSigner capabilities - * plus `sendRawTransaction` for broadcasting the pre-signed approval tx. + * that lack EIP-2612. * * @example * ```typescript * import { createErc20ApprovalGasSponsoringExtension } from '@x402/extensions'; * * facilitator.registerExtension( - * createErc20ApprovalGasSponsoringExtension(evmSigner, viemClient), + * createErc20ApprovalGasSponsoringExtension(signer), * ); * ``` */ export interface Erc20ApprovalGasSponsoringFacilitatorExtension extends FacilitatorExtension { key: "erc20ApprovalGasSponsoring"; - /** Signer with broadcast + settle capability. Optional β€” settlement fails gracefully if absent. */ + /** Default signer with approve+settle capability. Optional β€” settlement fails gracefully if absent. */ signer?: Erc20ApprovalGasSponsoringSigner; + /** Network-specific signer resolver. Takes precedence over `signer` when provided. */ + signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined; } /** - * Signer input for {@link createErc20ApprovalGasSponsoringExtension}. + * Base signer shape without `sendTransactions`. * Matches the FacilitatorEvmSigner shape from @x402/evm (duplicated to avoid circular dep). */ export type Erc20ApprovalGasSponsoringBaseSigner = Omit< Erc20ApprovalGasSponsoringSigner, - "sendRawTransaction" + "sendTransactions" >; /** * Create an ERC-20 approval gas sponsoring extension ready to register in a facilitator. * - * @param signer - The EVM facilitator signer (e.g. from `toFacilitatorEvmSigner()`) - * @param client - Object providing `sendRawTransaction` (e.g. a viem WalletClient) - * @param client.sendRawTransaction - Broadcasts a signed transaction to the network + * @param signer - A complete signer with `sendTransactions` already implemented. + * The signer decides how to execute the transactions (sequentially, batched, or atomically). + * @param signerForNetwork - Optional network-specific signer resolver. When provided, + * takes precedence over `signer` and allows different settlement signers per network. * @returns A fully configured extension to pass to `facilitator.registerExtension()` */ export function createErc20ApprovalGasSponsoringExtension( - signer: Erc20ApprovalGasSponsoringBaseSigner, - client: { - sendRawTransaction: (args: { serializedTransaction: `0x${string}` }) => Promise<`0x${string}`>; - }, + signer: Erc20ApprovalGasSponsoringSigner, + signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined, ): Erc20ApprovalGasSponsoringFacilitatorExtension { - return { - ...ERC20_APPROVAL_GAS_SPONSORING, - signer: { - ...signer, - sendRawTransaction: client.sendRawTransaction.bind(client), - }, - }; + return { ...ERC20_APPROVAL_GAS_SPONSORING, signer, signerForNetwork }; } /** diff --git a/typescript/packages/mechanisms/evm/README.md b/typescript/packages/mechanisms/evm/README.md index 9eb90f7337..429c0e475e 100644 --- a/typescript/packages/mechanisms/evm/README.md +++ b/typescript/packages/mechanisms/evm/README.md @@ -125,6 +125,30 @@ const client = new x402Client() .registerSchemeV1("base", new ExactEvmClientV1(signer)); ``` +### Extension RPC Configuration (Optional) + +`ExactEvmClient` only requires signer support for `address` + `signTypedData`. +Permit2 extension enrichment (EIP-2612 / ERC-20 approval gas sponsoring) can +optionally use explicit RPC config when signer read/fee helpers are unavailable. + +No chain-default RPC fallback is applied by the SDK. + +```typescript +// Per-network explicit registration +const client = new x402Client() + .register("eip155:137", new ExactEvmClient(signer, { rpcUrl: polygonRpcUrl })) + .register("eip155:8453", new ExactEvmClient(signer, { rpcUrl: baseRpcUrl })); + +// Wildcard registration with chain-id keyed config map +const wildcardClient = new x402Client().register( + "eip155:*", + new ExactEvmClient(signer, { + 137: { rpcUrl: polygonRpcUrl }, + 8453: { rpcUrl: baseRpcUrl }, + }), +); +``` + ### 3. Using Config (Flexible) ```typescript diff --git a/typescript/packages/mechanisms/evm/package.json b/typescript/packages/mechanisms/evm/package.json index 86fa94c5b5..c8efeba7ac 100644 --- a/typescript/packages/mechanisms/evm/package.json +++ b/typescript/packages/mechanisms/evm/package.json @@ -46,7 +46,6 @@ }, "dependencies": { "@x402/core": "workspace:~", - "@x402/extensions": "workspace:~", "viem": "^2.39.3", "zod": "^3.24.2" }, diff --git a/typescript/packages/mechanisms/evm/src/exact/client/eip2612.ts b/typescript/packages/mechanisms/evm/src/exact/client/eip2612.ts index f5887cbc36..f2b86dec53 100644 --- a/typescript/packages/mechanisms/evm/src/exact/client/eip2612.ts +++ b/typescript/packages/mechanisms/evm/src/exact/client/eip2612.ts @@ -1,7 +1,11 @@ import { getAddress } from "viem"; -import type { Eip2612GasSponsoringInfo } from "@x402/extensions"; import { eip2612PermitTypes, eip2612NoncesAbi, PERMIT2_ADDRESS } from "../../constants"; import { ClientEvmSigner } from "../../signer"; +import type { Eip2612GasSponsoringInfo } from "../extensions"; + +export type Eip2612PermitSigner = Pick & { + readContract: NonNullable; +}; /** * Signs an EIP-2612 permit authorizing the Permit2 contract to spend tokens. @@ -22,7 +26,7 @@ import { ClientEvmSigner } from "../../signer"; * @returns The EIP-2612 gas sponsoring info object */ export async function signEip2612Permit( - signer: ClientEvmSigner, + signer: Eip2612PermitSigner, tokenAddress: `0x${string}`, tokenName: string, tokenVersion: string, diff --git a/typescript/packages/mechanisms/evm/src/exact/client/erc20approval.ts b/typescript/packages/mechanisms/evm/src/exact/client/erc20approval.ts index b3928902f2..78d24b52a8 100644 --- a/typescript/packages/mechanisms/evm/src/exact/client/erc20approval.ts +++ b/typescript/packages/mechanisms/evm/src/exact/client/erc20approval.ts @@ -1,8 +1,4 @@ import { encodeFunctionData, getAddress, maxUint256 } from "viem"; -import { - ERC20_APPROVAL_GAS_SPONSORING_VERSION, - type Erc20ApprovalGasSponsoringInfo, -} from "@x402/extensions"; import { PERMIT2_ADDRESS, erc20ApproveAbi, @@ -11,6 +7,16 @@ import { DEFAULT_MAX_PRIORITY_FEE_PER_GAS, } from "../../constants"; import { ClientEvmSigner } from "../../signer"; +import { + ERC20_APPROVAL_GAS_SPONSORING_VERSION, + type Erc20ApprovalGasSponsoringInfo, +} from "../extensions"; + +export type Erc20ApprovalTxSigner = Pick & { + signTransaction: NonNullable; + getTransactionCount: NonNullable; + estimateFeesPerGas?: NonNullable; +}; /** * Signs an EIP-1559 `approve(Permit2, MaxUint256)` transaction for the given token. @@ -27,7 +33,7 @@ import { ClientEvmSigner } from "../../signer"; * @returns The ERC-20 approval gas sponsoring info object */ export async function signErc20ApprovalTransaction( - signer: ClientEvmSigner, + signer: Erc20ApprovalTxSigner, tokenAddress: `0x${string}`, chainId: number, ): Promise { @@ -42,13 +48,16 @@ export async function signErc20ApprovalTransaction( }); // Get current nonce for the sender - const nonce = await signer.getTransactionCount!({ address: from }); + const nonce = await signer.getTransactionCount({ address: from }); // Get current fee estimates, with fallback values let maxFeePerGas: bigint; let maxPriorityFeePerGas: bigint; try { - const fees = await signer.estimateFeesPerGas!(); + const fees = await signer.estimateFeesPerGas?.(); + if (!fees) { + throw new Error("no fee estimates available"); + } maxFeePerGas = fees.maxFeePerGas; maxPriorityFeePerGas = fees.maxPriorityFeePerGas; } catch { @@ -57,7 +66,7 @@ export async function signErc20ApprovalTransaction( } // Sign the EIP-1559 transaction (not broadcast) - const signedTransaction = await signer.signTransaction!({ + const signedTransaction = await signer.signTransaction({ to: tokenAddress, data, nonce, diff --git a/typescript/packages/mechanisms/evm/src/exact/client/index.ts b/typescript/packages/mechanisms/evm/src/exact/client/index.ts index fb10b8dd17..6d0958b019 100644 --- a/typescript/packages/mechanisms/evm/src/exact/client/index.ts +++ b/typescript/packages/mechanisms/evm/src/exact/client/index.ts @@ -1,6 +1,11 @@ export { ExactEvmScheme } from "./scheme"; export { registerExactEvmScheme } from "./register"; export type { EvmClientConfig } from "./register"; +export type { + ExactEvmSchemeConfig, + ExactEvmSchemeConfigByChainId, + ExactEvmSchemeOptions, +} from "./rpc"; export { createPermit2ApprovalTx, getPermit2AllowanceReadParams, diff --git a/typescript/packages/mechanisms/evm/src/exact/client/register.ts b/typescript/packages/mechanisms/evm/src/exact/client/register.ts index d28912074c..3e91e135af 100644 --- a/typescript/packages/mechanisms/evm/src/exact/client/register.ts +++ b/typescript/packages/mechanisms/evm/src/exact/client/register.ts @@ -2,6 +2,7 @@ import { x402Client, SelectPaymentRequirements, PaymentPolicy } from "@x402/core import { Network } from "@x402/core/types"; import { ClientEvmSigner } from "../../signer"; import { ExactEvmScheme } from "./scheme"; +import { ExactEvmSchemeOptions } from "./rpc"; import { ExactEvmSchemeV1 } from "../v1/client/scheme"; import { NETWORKS } from "../../v1"; @@ -26,8 +27,15 @@ export interface EvmClientConfig { policies?: PaymentPolicy[]; /** - * Optional specific networks to register - * If not provided, registers wildcard support (eip155:*) + * Optional Exact EVM client scheme options. + * Supports either a single config ({ rpcUrl }) or per-chain configs + * keyed by EVM chain ID ({ 8453: { rpcUrl: "..." } }). + */ + schemeOptions?: ExactEvmSchemeOptions; + + /** + * Optional specific networks to register. + * If not provided, registers wildcard support (eip155:*). */ networks?: Network[]; } @@ -55,7 +63,7 @@ export interface EvmClientConfig { * ``` */ export function registerExactEvmScheme(client: x402Client, config: EvmClientConfig): x402Client { - const evmScheme = new ExactEvmScheme(config.signer); + const evmScheme = new ExactEvmScheme(config.signer, config.schemeOptions); // Register V2 scheme // EIP-2612 gas sponsoring is handled internally by the scheme when the diff --git a/typescript/packages/mechanisms/evm/src/exact/client/rpc.ts b/typescript/packages/mechanisms/evm/src/exact/client/rpc.ts new file mode 100644 index 0000000000..b86e1fa404 --- /dev/null +++ b/typescript/packages/mechanisms/evm/src/exact/client/rpc.ts @@ -0,0 +1,121 @@ +import { createPublicClient, http } from "viem"; +import type { ClientEvmSigner } from "../../signer"; +import { getEvmChainId } from "../../utils"; + +export type ExactEvmSchemeConfig = { + rpcUrl?: string; +}; + +export type ExactEvmSchemeConfigByChainId = Record; + +export type ExactEvmSchemeOptions = ExactEvmSchemeConfig | ExactEvmSchemeConfigByChainId; + +type ExtensionRpcCapabilities = Pick< + ClientEvmSigner, + "readContract" | "signTransaction" | "getTransactionCount" | "estimateFeesPerGas" +>; + +const rpcClientCache = new Map>(); + +/** + * Determines whether scheme options are keyed by numeric chain id. + * + * @param options - Exact EVM scheme options provided by the client. + * @returns True when options are a chainId-to-config mapping. + */ +function isConfigByChainId( + options: ExactEvmSchemeOptions, +): options is ExactEvmSchemeConfigByChainId { + const keys = Object.keys(options); + return keys.length > 0 && keys.every(key => /^\d+$/.test(key)); +} + +/** + * Returns a cached viem public client for a specific RPC URL. + * + * @param rpcUrl - The RPC endpoint URL used to construct the client. + * @returns A cached or newly created viem public client instance. + */ +function getRpcClient(rpcUrl: string): ReturnType { + const existing = rpcClientCache.get(rpcUrl); + if (existing) { + return existing; + } + + const client = createPublicClient({ + transport: http(rpcUrl), + }); + rpcClientCache.set(rpcUrl, client); + return client; +} + +/** + * Resolves the RPC URL for a given CAIP-2 network from scheme options. + * + * @param network - CAIP-2 network identifier. + * @param options - Optional scheme configuration (single config or chain map). + * @returns The configured RPC URL for the network, if available. + */ +export function resolveRpcUrl( + network: string, + options?: ExactEvmSchemeOptions, +): string | undefined { + if (!options) { + return undefined; + } + + if (isConfigByChainId(options)) { + const chainId = getEvmChainId(network); + const optionsByChainId = options as ExactEvmSchemeConfigByChainId; + return optionsByChainId[chainId]?.rpcUrl; + } + + return (options as ExactEvmSchemeConfig).rpcUrl; +} + +/** + * Resolves extension RPC capabilities from signer methods and optional RPC backfill. + * + * @param network - CAIP-2 network identifier for chain resolution. + * @param signer - Client signer with optional RPC-like methods. + * @param options - Optional scheme configuration used for RPC backfill. + * @returns The best available capability set for extension enrichment flows. + */ +export function resolveExtensionRpcCapabilities( + network: string, + signer: ClientEvmSigner, + options?: ExactEvmSchemeOptions, +): ExtensionRpcCapabilities { + const capabilities: ExtensionRpcCapabilities = { + signTransaction: signer.signTransaction, + readContract: signer.readContract, + getTransactionCount: signer.getTransactionCount, + estimateFeesPerGas: signer.estimateFeesPerGas, + }; + + const needsRpcBackfill = + !capabilities.readContract || + !capabilities.getTransactionCount || + !capabilities.estimateFeesPerGas; + if (!needsRpcBackfill) { + return capabilities; + } + + const rpcUrl = resolveRpcUrl(network, options); + if (!rpcUrl) { + return capabilities; + } + const rpcClient = getRpcClient(rpcUrl); + if (!capabilities.readContract) { + capabilities.readContract = args => rpcClient.readContract(args as never) as Promise; + } + if (!capabilities.getTransactionCount) { + capabilities.getTransactionCount = async args => + rpcClient.getTransactionCount({ address: args.address }); + } + if (!capabilities.estimateFeesPerGas) { + capabilities.estimateFeesPerGas = async () => rpcClient.estimateFeesPerGas(); + } + + return capabilities; +} diff --git a/typescript/packages/mechanisms/evm/src/exact/client/scheme.ts b/typescript/packages/mechanisms/evm/src/exact/client/scheme.ts index d4e91904ee..b074fe8063 100644 --- a/typescript/packages/mechanisms/evm/src/exact/client/scheme.ts +++ b/typescript/packages/mechanisms/evm/src/exact/client/scheme.ts @@ -1,19 +1,20 @@ import { - PaymentRequirements, SchemeNetworkClient, + PaymentRequirements, PaymentPayloadResult, PaymentPayloadContext, } from "@x402/core/types"; -import { EIP2612_GAS_SPONSORING, ERC20_APPROVAL_GAS_SPONSORING } from "@x402/extensions"; import { ClientEvmSigner } from "../../signer"; import { AssetTransferMethod } from "../../types"; import { PERMIT2_ADDRESS, erc20AllowanceAbi } from "../../constants"; import { getAddress } from "viem"; import { getEvmChainId } from "../../utils"; +import { EIP2612_GAS_SPONSORING_KEY, ERC20_APPROVAL_GAS_SPONSORING_KEY } from "../extensions"; import { createEIP3009Payload } from "./eip3009"; import { createPermit2Payload } from "./permit2"; import { signEip2612Permit } from "./eip2612"; import { signErc20ApprovalTransaction } from "./erc20approval"; +import { ExactEvmSchemeOptions, resolveExtensionRpcCapabilities } from "./rpc"; /** * EVM client implementation for the Exact payment scheme. @@ -34,10 +35,15 @@ export class ExactEvmScheme implements SchemeNetworkClient { * Creates a new ExactEvmClient instance. * * @param signer - The EVM signer for client operations. - * Must support `readContract` for EIP-2612 gas sponsoring. - * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`. + * Base flow only requires `address` + `signTypedData`. + * Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally + * requires optional capabilities like `readContract` and tx signing helpers. + * @param options - Optional RPC configuration used to backfill extension capabilities. */ - constructor(private readonly signer: ClientEvmSigner) {} + constructor( + private readonly signer: ClientEvmSigner, + private readonly options?: ExactEvmSchemeOptions, + ) {} /** * Creates a payment payload for the Exact scheme. @@ -63,7 +69,6 @@ export class ExactEvmScheme implements SchemeNetworkClient { if (assetTransferMethod === "permit2") { const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements); - // Check if EIP-2612 gas sponsoring is advertised and we can handle it const eip2612Extensions = await this.trySignEip2612Permit( paymentRequirements, result, @@ -77,7 +82,6 @@ export class ExactEvmScheme implements SchemeNetworkClient { }; } - // EIP-2612 not applicable β€” try ERC-20 approval gas sponsoring as fallback const erc20Extensions = await this.trySignErc20Approval(paymentRequirements, result, context); if (erc20Extensions) { return { @@ -112,12 +116,20 @@ export class ExactEvmScheme implements SchemeNetworkClient { result: PaymentPayloadResult, context?: PaymentPayloadContext, ): Promise | undefined> { - // Check if server advertises eip2612GasSponsoring - if (!context?.extensions?.[EIP2612_GAS_SPONSORING.key]) { + const capabilities = resolveExtensionRpcCapabilities( + requirements.network, + this.signer, + this.options, + ); + + if (!capabilities.readContract) { + return undefined; + } + + if (!context?.extensions?.[EIP2612_GAS_SPONSORING_KEY]) { return undefined; } - // Check that required token metadata is available const tokenName = requirements.extra?.name as string | undefined; const tokenVersion = requirements.extra?.version as string | undefined; if (!tokenName || !tokenVersion) { @@ -127,9 +139,8 @@ export class ExactEvmScheme implements SchemeNetworkClient { const chainId = getEvmChainId(requirements.network); const tokenAddress = getAddress(requirements.asset) as `0x${string}`; - // Check if user already has sufficient Permit2 allowance try { - const allowance = (await this.signer.readContract({ + const allowance = (await capabilities.readContract({ address: tokenAddress, abi: erc20AllowanceAbi, functionName: "allowance", @@ -137,22 +148,23 @@ export class ExactEvmScheme implements SchemeNetworkClient { })) as bigint; if (allowance >= BigInt(requirements.amount)) { - return undefined; // Already approved, no need for EIP-2612 + return undefined; } } catch { - // If we can't check allowance, proceed with EIP-2612 signing + // Allowance check failed, proceed with signing } - // Use the same deadline as the Permit2 authorization const permit2Auth = result.payload?.permit2Authorization as Record | undefined; const deadline = (permit2Auth?.deadline as string) ?? Math.floor(Date.now() / 1000 + requirements.maxTimeoutSeconds).toString(); - // Sign the EIP-2612 permit with the exact Permit2 permitted amount - // (the contract enforces permit2612.value == permit.permitted.amount) const info = await signEip2612Permit( - this.signer, + { + address: this.signer.address, + signTypedData: msg => this.signer.signTypedData(msg), + readContract: capabilities.readContract, + }, tokenAddress, tokenName, tokenVersion, @@ -162,7 +174,7 @@ export class ExactEvmScheme implements SchemeNetworkClient { ); return { - [EIP2612_GAS_SPONSORING.key]: { info }, + [EIP2612_GAS_SPONSORING_KEY]: { info }, }; } @@ -190,22 +202,29 @@ export class ExactEvmScheme implements SchemeNetworkClient { _result: PaymentPayloadResult, context?: PaymentPayloadContext, ): Promise | undefined> { - // Check if server advertises erc20ApprovalGasSponsoring - if (!context?.extensions?.[ERC20_APPROVAL_GAS_SPONSORING.key]) { + const capabilities = resolveExtensionRpcCapabilities( + requirements.network, + this.signer, + this.options, + ); + + if (!capabilities.readContract) { return undefined; } - // Check that signer has the required capabilities for signing raw transactions - if (!this.signer.signTransaction || !this.signer.getTransactionCount) { + if (!context?.extensions?.[ERC20_APPROVAL_GAS_SPONSORING_KEY]) { + return undefined; + } + + if (!capabilities.signTransaction || !capabilities.getTransactionCount) { return undefined; } const chainId = getEvmChainId(requirements.network); const tokenAddress = getAddress(requirements.asset) as `0x${string}`; - // Check if user already has sufficient Permit2 allowance try { - const allowance = (await this.signer.readContract({ + const allowance = (await capabilities.readContract({ address: tokenAddress, abi: erc20AllowanceAbi, functionName: "allowance", @@ -213,17 +232,25 @@ export class ExactEvmScheme implements SchemeNetworkClient { })) as bigint; if (allowance >= BigInt(requirements.amount)) { - return undefined; // Already approved, no need for ERC-20 approval tx + return undefined; } } catch { - // If we can't check allowance, proceed with signing + // Allowance check failed, proceed with signing } - // Sign the approve(Permit2, MaxUint256) transaction - const info = await signErc20ApprovalTransaction(this.signer, tokenAddress, chainId); + const info = await signErc20ApprovalTransaction( + { + address: this.signer.address, + signTransaction: capabilities.signTransaction, + getTransactionCount: capabilities.getTransactionCount, + estimateFeesPerGas: capabilities.estimateFeesPerGas, + }, + tokenAddress, + chainId, + ); return { - [ERC20_APPROVAL_GAS_SPONSORING.key]: { info }, + [ERC20_APPROVAL_GAS_SPONSORING_KEY]: { info }, }; } } diff --git a/typescript/packages/mechanisms/evm/src/exact/extensions.ts b/typescript/packages/mechanisms/evm/src/exact/extensions.ts new file mode 100644 index 0000000000..f4ddba882d --- /dev/null +++ b/typescript/packages/mechanisms/evm/src/exact/extensions.ts @@ -0,0 +1,176 @@ +import type { PaymentPayload } from "@x402/core/types"; +import type { FacilitatorEvmSigner } from "../signer"; + +export const EIP2612_GAS_SPONSORING_KEY = "eip2612GasSponsoring" as const; +export const ERC20_APPROVAL_GAS_SPONSORING_KEY = "erc20ApprovalGasSponsoring" as const; +export const ERC20_APPROVAL_GAS_SPONSORING_VERSION = "1" as const; + +export interface Eip2612GasSponsoringInfo { + [key: string]: unknown; + from: string; + asset: string; + spender: string; + amount: string; + nonce: string; + deadline: string; + signature: string; + version: string; +} + +export interface Erc20ApprovalGasSponsoringInfo { + [key: string]: unknown; + from: `0x${string}`; + asset: `0x${string}`; + spender: `0x${string}`; + amount: string; + signedTransaction: `0x${string}`; + version: string; +} + +/** + * A single transaction to be executed by the signer. + * - `0x${string}`: a pre-signed serialized transaction (broadcast as-is via sendRawTransaction) + * - `{ to, data, gas? }`: an unsigned call intent (signer signs and broadcasts) + */ +export type TransactionRequest = + | `0x${string}` + | { to: `0x${string}`; data: `0x${string}`; gas?: bigint }; + +export type Erc20ApprovalGasSponsoringSigner = FacilitatorEvmSigner & { + sendTransactions(transactions: TransactionRequest[]): Promise<`0x${string}`[]>; +}; + +export interface Erc20ApprovalGasSponsoringFacilitatorExtension { + key: typeof ERC20_APPROVAL_GAS_SPONSORING_KEY; + signer?: Erc20ApprovalGasSponsoringSigner; + signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined; +} + +/** + * Extracts a typed `info` payload from an extension entry. + * + * @param payload - Payment payload containing optional extensions. + * @param extensionKey - Extension key to extract. + * @returns The extension `info` object when present; otherwise null. + */ +function _extractInfo( + payload: PaymentPayload, + extensionKey: string, +): Record | null { + const extensions = payload.extensions; + if (!extensions) return null; + const extension = extensions[extensionKey] as { info?: Record } | undefined; + if (!extension?.info) return null; + return extension.info; +} + +/** + * Extracts and validates required EIP-2612 gas sponsoring fields. + * + * @param payload - Payment payload returned by the client scheme. + * @returns Parsed EIP-2612 gas sponsoring info when available and complete. + */ +export function extractEip2612GasSponsoringInfo( + payload: PaymentPayload, +): Eip2612GasSponsoringInfo | null { + const info = _extractInfo(payload, EIP2612_GAS_SPONSORING_KEY); + if (!info) return null; + if ( + !info.from || + !info.asset || + !info.spender || + !info.amount || + !info.nonce || + !info.deadline || + !info.signature || + !info.version + ) { + return null; + } + return info as unknown as Eip2612GasSponsoringInfo; +} + +/** + * Validates the structure and formatting of EIP-2612 sponsoring info. + * + * @param info - EIP-2612 extension info to validate. + * @returns True when all required fields match expected patterns. + */ +export function validateEip2612GasSponsoringInfo(info: Eip2612GasSponsoringInfo): boolean { + const addressPattern = /^0x[a-fA-F0-9]{40}$/; + const numericPattern = /^[0-9]+$/; + const hexPattern = /^0x[a-fA-F0-9]+$/; + const versionPattern = /^[0-9]+(\.[0-9]+)*$/; + return ( + addressPattern.test(info.from) && + addressPattern.test(info.asset) && + addressPattern.test(info.spender) && + numericPattern.test(info.amount) && + numericPattern.test(info.nonce) && + numericPattern.test(info.deadline) && + hexPattern.test(info.signature) && + versionPattern.test(info.version) + ); +} + +/** + * Extracts and validates required ERC-20 approval sponsoring fields. + * + * @param payload - Payment payload returned by the client scheme. + * @returns Parsed ERC-20 approval sponsoring info when available and complete. + */ +export function extractErc20ApprovalGasSponsoringInfo( + payload: PaymentPayload, +): Erc20ApprovalGasSponsoringInfo | null { + const info = _extractInfo(payload, ERC20_APPROVAL_GAS_SPONSORING_KEY); + if (!info) return null; + if ( + !info.from || + !info.asset || + !info.spender || + !info.amount || + !info.signedTransaction || + !info.version + ) { + return null; + } + return info as unknown as Erc20ApprovalGasSponsoringInfo; +} + +/** + * Validates the structure and formatting of ERC-20 approval sponsoring info. + * + * @param info - ERC-20 approval extension info to validate. + * @returns True when all required fields match expected patterns. + */ +export function validateErc20ApprovalGasSponsoringInfo( + info: Erc20ApprovalGasSponsoringInfo, +): boolean { + const addressPattern = /^0x[a-fA-F0-9]{40}$/; + const numericPattern = /^[0-9]+$/; + const hexPattern = /^0x[a-fA-F0-9]+$/; + const versionPattern = /^[0-9]+(\.[0-9]+)*$/; + return ( + addressPattern.test(info.from) && + addressPattern.test(info.asset) && + addressPattern.test(info.spender) && + numericPattern.test(info.amount) && + hexPattern.test(info.signedTransaction) && + versionPattern.test(info.version) + ); +} + +/** + * Resolves the ERC-20 approval extension signer for a specific network. + * + * @param extension - Optional facilitator extension config. + * @param network - CAIP-2 network identifier. + * @returns A network-specific signer when available, else the default signer. + */ +export function resolveErc20ApprovalExtensionSigner( + extension: Erc20ApprovalGasSponsoringFacilitatorExtension | undefined, + network: string, +): Erc20ApprovalGasSponsoringSigner | undefined { + if (!extension) return undefined; + return extension.signerForNetwork?.(network) ?? extension.signer; +} diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/erc20approval.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/erc20approval.ts index e11d1a933b..2fccaaa977 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/erc20approval.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/erc20approval.ts @@ -9,7 +9,7 @@ import type { VerifyResponse } from "@x402/core/types"; import { validateErc20ApprovalGasSponsoringInfo, type Erc20ApprovalGasSponsoringInfo, -} from "@x402/extensions"; +} from "../extensions"; import { PERMIT2_ADDRESS, erc20ApproveAbi } from "../../constants"; import { ErrErc20ApprovalInvalidFormat, diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts index 9b0aabf166..4a22fc4316 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts @@ -14,7 +14,7 @@ export const ErrPermit2InvalidSpender = "invalid_permit2_spender"; export const ErrPermit2RecipientMismatch = "invalid_permit2_recipient_mismatch"; export const ErrPermit2DeadlineExpired = "permit2_deadline_expired"; export const ErrPermit2NotYetValid = "permit2_not_yet_valid"; -export const ErrPermit2InsufficientAmount = "permit2_insufficient_amount"; +export const ErrPermit2AmountMismatch = "permit2_amount_mismatch"; export const ErrPermit2TokenMismatch = "permit2_token_mismatch"; export const ErrPermit2InvalidSignature = "invalid_permit2_signature"; export const ErrPermit2AllowanceRequired = "permit2_allowance_required"; diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts index c88b35b548..feff32e0ff 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts @@ -9,11 +9,13 @@ import { extractEip2612GasSponsoringInfo, validateEip2612GasSponsoringInfo, extractErc20ApprovalGasSponsoringInfo, - ERC20_APPROVAL_GAS_SPONSORING, + ERC20_APPROVAL_GAS_SPONSORING_KEY, + resolveErc20ApprovalExtensionSigner, + type Eip2612GasSponsoringInfo, type Erc20ApprovalGasSponsoringFacilitatorExtension, -} from "@x402/extensions"; -import type { Eip2612GasSponsoringInfo } from "@x402/extensions"; -import { getAddress } from "viem"; + type Erc20ApprovalGasSponsoringSigner, +} from "../extensions"; +import { getAddress, encodeFunctionData } from "viem"; import { eip3009ABI, PERMIT2_ADDRESS, @@ -24,6 +26,7 @@ import { } from "../../constants"; import { ErrPermit2612AmountMismatch, + ErrPermit2AmountMismatch, ErrPermit2InvalidAmount, ErrPermit2InvalidDestination, ErrPermit2InvalidNonce, @@ -123,7 +126,7 @@ export async function verifyPermit2( ) { return { isValid: false, - invalidReason: "permit2_amount_mismatch", + invalidReason: ErrPermit2AmountMismatch, payer, }; } @@ -265,7 +268,7 @@ async function _verifyPermit2Allowance( // Try ERC-20 approval gas sponsoring as fallback const erc20GasSponsorshipExtension = context?.getExtension( - ERC20_APPROVAL_GAS_SPONSORING.key, + ERC20_APPROVAL_GAS_SPONSORING_KEY, ); if (erc20GasSponsorshipExtension) { const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload); @@ -280,15 +283,32 @@ async function _verifyPermit2Allowance( return { isValid: false, invalidReason: "permit2_allowance_required", payer }; } catch { - // If allowance check fails, validate extensions if present; otherwise proceed optimistically + // Allowance check failed β€” validate extensions if present; fail closed if none valid const eip2612Info = extractEip2612GasSponsoringInfo(payload); if (eip2612Info) { const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); if (!result.isValid) { return { isValid: false, invalidReason: result.invalidReason!, payer }; } + return null; } - return null; + + const erc20GasSponsorshipExtension = + context?.getExtension( + ERC20_APPROVAL_GAS_SPONSORING_KEY, + ); + if (erc20GasSponsorshipExtension) { + const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload); + if (erc20Info) { + const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress); + if (!result.isValid) { + return { isValid: false, invalidReason: result.invalidReason!, payer }; + } + return null; + } + } + + return { isValid: false, invalidReason: "permit2_allowance_required", payer }; } } @@ -337,15 +357,14 @@ export async function settlePermit2( if (erc20Info) { const erc20GasSponsorshipExtension = context?.getExtension( - ERC20_APPROVAL_GAS_SPONSORING.key, - ); - if (erc20GasSponsorshipExtension?.signer) { - return _settlePermit2WithERC20Approval( - erc20GasSponsorshipExtension.signer, - payload, - permit2Payload, - erc20Info, + ERC20_APPROVAL_GAS_SPONSORING_KEY, ); + const extensionSigner = resolveErc20ApprovalExtensionSigner( + erc20GasSponsorshipExtension, + payload.accepted.network, + ); + if (extensionSigner) { + return _settlePermit2WithERC20Approval(extensionSigner, payload, permit2Payload, erc20Info); } } @@ -408,18 +427,18 @@ async function _settlePermit2WithEIP2612( } /** - * Broadcasts the pre-signed ERC-20 approve tx then settles via the extension signer. - * Both operations use the extension signer, enabling atomic bundling by production implementations. + * Delegates the full approve+settle flow to the extension signer via sendTransactions. + * The signer owns execution strategy (sequential, batched, or atomic bundling). * - * @param extensionSigner - The extension signer with sendRawTransaction + writeContract + * @param extensionSigner - The extension signer with sendTransactions * @param payload - The payment payload * @param permit2Payload - The Permit2 specific payload * @param erc20Info - Object containing the signed approval transaction - * @param erc20Info.signedTransaction - The RLP-encoded signed EIP-1559 approval tx + * @param erc20Info.signedTransaction - The RLP-encoded signed ERC-20 approve transaction hex string * @returns Promise resolving to settlement response */ async function _settlePermit2WithERC20Approval( - extensionSigner: Erc20ApprovalGasSponsoringFacilitatorExtension["signer"] & {}, + extensionSigner: Erc20ApprovalGasSponsoringSigner, payload: PaymentPayload, permit2Payload: ExactPermit2Payload, erc20Info: { signedTransaction: string }, @@ -427,26 +446,7 @@ async function _settlePermit2WithERC20Approval( const payer = permit2Payload.permit2Authorization.from; try { - const approvalTxHash = await extensionSigner.sendRawTransaction({ - serializedTransaction: erc20Info.signedTransaction as `0x${string}`, - }); - - const approvalReceipt = await extensionSigner.waitForTransactionReceipt({ - hash: approvalTxHash, - }); - - if (approvalReceipt.status !== "success") { - return { - success: false, - errorReason: "erc20_approval_tx_failed", - transaction: approvalTxHash, - network: payload.accepted.network, - payer, - }; - } - - const tx = await extensionSigner.writeContract({ - address: x402ExactPermit2ProxyAddress, + const settleData = encodeFunctionData({ abi: x402ExactPermit2ProxyABI, functionName: "settle", args: [ @@ -467,7 +467,13 @@ async function _settlePermit2WithERC20Approval( ], }); - return _waitAndReturn(extensionSigner, tx, payload, payer); + const txHashes = await extensionSigner.sendTransactions([ + erc20Info.signedTransaction as `0x${string}`, + { to: x402ExactPermit2ProxyAddress, data: settleData, gas: BigInt(300_000) }, + ]); + + const settleTxHash = txHashes[txHashes.length - 1]; + return _waitAndReturn(extensionSigner, settleTxHash, payload, payer); } catch (error) { return _mapSettleError(error, payload, payer); } @@ -581,6 +587,8 @@ function _mapSettleError( errorReason = ErrPermit2InvalidSignature; } else if (message.includes("InvalidNonce")) { errorReason = ErrPermit2InvalidNonce; + } else if (message.includes("erc20_approval_tx_failed")) { + errorReason = "erc20_approval_tx_failed"; } else { errorReason = `transaction_failed: ${message.slice(0, 500)}`; } diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts index a4bf984e98..e44c338695 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts @@ -81,8 +81,9 @@ export class ExactEvmScheme implements SchemeNetworkFacilitator { context?: FacilitatorContext, ): Promise { const rawPayload = payload.payload as ExactEvmPayloadV2; + const isPermit2 = isPermit2Payload(rawPayload); - if (isPermit2Payload(rawPayload)) { + if (isPermit2) { return verifyPermit2(this.signer, payload, requirements, rawPayload, context); } @@ -104,8 +105,9 @@ export class ExactEvmScheme implements SchemeNetworkFacilitator { context?: FacilitatorContext, ): Promise { const rawPayload = payload.payload as ExactEvmPayloadV2; + const isPermit2 = isPermit2Payload(rawPayload); - if (isPermit2Payload(rawPayload)) { + if (isPermit2) { return settlePermit2(this.signer, payload, requirements, rawPayload, context); } diff --git a/typescript/packages/mechanisms/evm/src/signer.ts b/typescript/packages/mechanisms/evm/src/signer.ts index 3e6f79bdfd..66ec3de62d 100644 --- a/typescript/packages/mechanisms/evm/src/signer.ts +++ b/typescript/packages/mechanisms/evm/src/signer.ts @@ -20,7 +20,11 @@ export type ClientEvmSigner = { primaryType: string; message: Record; }): Promise<`0x${string}`>; - readContract(args: { + /** + * Optional on-chain reads. + * Required only for extension enrichment (EIP-2612 / ERC-20 approval). + */ + readContract?(args: { address: `0x${string}`; abi: readonly unknown[]; functionName: string; @@ -84,6 +88,8 @@ export type FacilitatorEvmSigner = { abi: readonly unknown[]; functionName: string; args: readonly unknown[]; + /** Optional gas limit. When provided, skips eth_estimateGas simulation. */ + gas?: bigint; }): Promise<`0x${string}`>; sendTransaction(args: { to: `0x${string}`; data: `0x${string}` }): Promise<`0x${string}`>; waitForTransactionReceipt(args: { hash: `0x${string}` }): Promise<{ status: string }>; @@ -106,11 +112,11 @@ export type FacilitatorEvmSigner = { * ``` * * @param signer - A signer with `address` and `signTypedData` (and optionally `readContract`) - * @param publicClient - A client with `readContract` (required if signer lacks it) + * @param publicClient - A client with optional read/nonce/fee helpers * @param publicClient.readContract - The readContract method from the public client * @param publicClient.getTransactionCount - Optional getTransactionCount for ERC-20 approval * @param publicClient.estimateFeesPerGas - Optional estimateFeesPerGas for ERC-20 approval - * @returns A complete ClientEvmSigner + * @returns A ClientEvmSigner with any available optional capabilities * * @example * ```typescript @@ -136,19 +142,15 @@ export function toClientEvmSigner( ): ClientEvmSigner { const readContract = signer.readContract ?? publicClient?.readContract.bind(publicClient); - if (!readContract) { - throw new Error( - "toClientEvmSigner requires either a signer with readContract or a publicClient. " + - "Use createWalletClient(...).extend(publicActions) or pass a publicClient.", - ); - } - const result: ClientEvmSigner = { address: signer.address, signTypedData: msg => signer.signTypedData(msg), - readContract, }; + if (readContract) { + result.readContract = readContract; + } + // Forward optional capabilities from signer or publicClient const signTransaction = signer.signTransaction; if (signTransaction) { diff --git a/typescript/packages/mechanisms/evm/test/unit/exact/client.rpc.test.ts b/typescript/packages/mechanisms/evm/test/unit/exact/client.rpc.test.ts new file mode 100644 index 0000000000..5143713e20 --- /dev/null +++ b/typescript/packages/mechanisms/evm/test/unit/exact/client.rpc.test.ts @@ -0,0 +1,123 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import type { ClientEvmSigner } from "../../../src/signer"; + +const { + mockReadContract, + mockGetTransactionCount, + mockEstimateFeesPerGas, + mockCreatePublicClient, + mockHttp, +} = vi.hoisted(() => { + const readContract = vi.fn(); + const getTransactionCount = vi.fn(); + const estimateFeesPerGas = vi.fn(); + return { + mockReadContract: readContract, + mockGetTransactionCount: getTransactionCount, + mockEstimateFeesPerGas: estimateFeesPerGas, + mockCreatePublicClient: vi.fn(() => ({ + readContract, + getTransactionCount, + estimateFeesPerGas, + })), + mockHttp: vi.fn((url: string) => ({ url })), + }; +}); + +vi.mock("viem", () => ({ + createPublicClient: mockCreatePublicClient, + http: mockHttp, +})); + +import { + resolveRpcUrl, + resolveExtensionRpcCapabilities, + type ExactEvmSchemeOptions, +} from "../../../src/exact/client/rpc"; + +describe("Exact EVM RPC resolver", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("resolves rpc url from single config", () => { + const options: ExactEvmSchemeOptions = { rpcUrl: "https://base.example" }; + expect(resolveRpcUrl("eip155:8453", options)).toBe("https://base.example"); + }); + + it("resolves rpc url from chain map", () => { + const options: ExactEvmSchemeOptions = { + 137: { rpcUrl: "https://polygon.example" }, + 8453: { rpcUrl: "https://base.example" }, + }; + expect(resolveRpcUrl("eip155:8453", options)).toBe("https://base.example"); + expect(resolveRpcUrl("eip155:137", options)).toBe("https://polygon.example"); + }); + + it("keeps signer capabilities as highest precedence", async () => { + const signerRead = vi.fn().mockResolvedValue(1n); + const signerGetTx = vi.fn().mockResolvedValue(7); + const signerFees = vi.fn().mockResolvedValue({ + maxFeePerGas: 100n, + maxPriorityFeePerGas: 10n, + }); + + const signer: ClientEvmSigner = { + address: "0x1234567890123456789012345678901234567890", + signTypedData: vi.fn().mockResolvedValue("0xabc"), + readContract: signerRead, + getTransactionCount: signerGetTx, + estimateFeesPerGas: signerFees, + }; + + const capabilities = resolveExtensionRpcCapabilities("eip155:8453", signer, { + rpcUrl: "https://base.example", + }); + await capabilities.readContract?.({ + address: "0x1234567890123456789012345678901234567890", + abi: [], + functionName: "allowance", + args: [], + }); + + expect(capabilities.readContract).toBe(signerRead); + expect(capabilities.getTransactionCount).toBe(signerGetTx); + expect(capabilities.estimateFeesPerGas).toBe(signerFees); + expect(mockCreatePublicClient).not.toHaveBeenCalled(); + }); + + it("backfills missing read and fee capabilities from rpc", async () => { + mockReadContract.mockResolvedValue(0n); + mockGetTransactionCount.mockResolvedValue(3); + mockEstimateFeesPerGas.mockResolvedValue({ + maxFeePerGas: 111n, + maxPriorityFeePerGas: 22n, + }); + + const signer: ClientEvmSigner = { + address: "0x1234567890123456789012345678901234567890", + signTypedData: vi.fn().mockResolvedValue("0xabc"), + }; + + const capabilities = resolveExtensionRpcCapabilities("eip155:8453", signer, { + rpcUrl: "https://base.example", + }); + + const allowance = await capabilities.readContract?.({ + address: "0x1234567890123456789012345678901234567890", + abi: [], + functionName: "allowance", + args: [], + }); + const nonce = await capabilities.getTransactionCount?.({ + address: "0x1234567890123456789012345678901234567890", + }); + const fees = await capabilities.estimateFeesPerGas?.(); + + expect(mockCreatePublicClient).toHaveBeenCalledTimes(1); + expect(mockHttp).toHaveBeenCalledWith("https://base.example"); + expect(allowance).toBe(0n); + expect(nonce).toBe(3); + expect(fees).toEqual({ maxFeePerGas: 111n, maxPriorityFeePerGas: 22n }); + }); +}); diff --git a/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts b/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts index 39efa7fda6..853be2a4a9 100644 --- a/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts +++ b/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts @@ -4,7 +4,7 @@ import { ExactEvmScheme as ClientExactEvmScheme } from "../../../src/exact/clien import type { ClientEvmSigner, FacilitatorEvmSigner } from "../../../src/signer"; import { PaymentRequirements, PaymentPayload } from "@x402/core/types"; import { x402ExactPermit2ProxyAddress, PERMIT2_ADDRESS } from "../../../src/constants"; -import { ERC20_APPROVAL_GAS_SPONSORING } from "@x402/extensions"; +import { ERC20_APPROVAL_GAS_SPONSORING_KEY } from "../../../src/exact/extensions"; // Mock viem's transaction parsing utilities for ERC-20 approval tests // Uses importOriginal to preserve all other viem exports (getAddress, etc.) @@ -1006,8 +1006,8 @@ describe("ExactEvmScheme (Facilitator)", () => { function makeErc20Context() { return { getExtension: vi.fn().mockImplementation((key: string) => { - if (key === ERC20_APPROVAL_GAS_SPONSORING.key) { - return { key: ERC20_APPROVAL_GAS_SPONSORING.key }; + if (key === ERC20_APPROVAL_GAS_SPONSORING_KEY) { + return { key: ERC20_APPROVAL_GAS_SPONSORING_KEY }; } return undefined; }), @@ -1164,7 +1164,6 @@ describe("ExactEvmScheme (Facilitator)", () => { const PAYER = "0x1234567890123456789012345678901234567890" as `0x${string}`; const TOKEN_ADDRESS = "0xeED520980fC7C7B4eB379B96d61CEdea2423005a" as `0x${string}`; const MOCK_SIGNED_TX = "0x02f8ab0102030405060708" as `0x${string}`; - const APPROVAL_TX_HASH = "0xapproval_tx_hash_mock" as `0x${string}`; const APPROVE_CALLDATA = `0x095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3` + @@ -1242,25 +1241,24 @@ describe("ExactEvmScheme (Facilitator)", () => { }); const SETTLE_TX_HASH = "0xsettle_tx_hash_mock" as `0x${string}`; - const mockExtSendRawTx = vi.fn().mockResolvedValue(APPROVAL_TX_HASH); - const mockExtWriteContract = vi.fn().mockResolvedValue(SETTLE_TX_HASH); + const mockSendTransactions = vi.fn().mockResolvedValue([SETTLE_TX_HASH]); const mockExtWaitForReceipt = vi.fn().mockResolvedValue({ status: "success" }); - // Extension signer has all FacilitatorEvmSigner methods + sendRawTransaction + // Extension signer has all FacilitatorEvmSigner methods + sendTransactions const mockContext = { getExtension: vi.fn().mockImplementation((key: string) => { - if (key === ERC20_APPROVAL_GAS_SPONSORING.key) { + if (key === ERC20_APPROVAL_GAS_SPONSORING_KEY) { return { - key: ERC20_APPROVAL_GAS_SPONSORING.key, + key: ERC20_APPROVAL_GAS_SPONSORING_KEY, signer: { getAddresses: vi.fn().mockReturnValue([PAYER]), readContract: mockFacilitatorSigner.readContract, verifyTypedData: mockFacilitatorSigner.verifyTypedData, - writeContract: mockExtWriteContract, + writeContract: vi.fn(), sendTransaction: vi.fn(), waitForTransactionReceipt: mockExtWaitForReceipt, getCode: vi.fn().mockResolvedValue("0x"), - sendRawTransaction: mockExtSendRawTx, + sendTransactions: mockSendTransactions, }, }; } @@ -1271,18 +1269,78 @@ describe("ExactEvmScheme (Facilitator)", () => { const payload = makeErc20Permit2Payload(makeValidErc20Extension()); const result = await facilitator.settle(payload, erc20Requirements, mockContext); - // Extension signer broadcast the approval tx - expect(mockExtSendRawTx).toHaveBeenCalledWith({ serializedTransaction: MOCK_SIGNED_TX }); - - // Extension signer called settle (not the base signer) - expect(mockExtWriteContract).toHaveBeenCalled(); - const writeCall = mockExtWriteContract.mock.calls[0][0]; - expect(writeCall.functionName).toBe("settle"); + // Extension signer called sendTransactions with [approvalTx, settleCall] + expect(mockSendTransactions).toHaveBeenCalled(); + const transactions = mockSendTransactions.mock.calls[0][0]; + expect(transactions[0]).toBe(MOCK_SIGNED_TX); + expect(transactions[1]).toHaveProperty("to"); + expect(transactions[1]).toHaveProperty("data"); // Base signer's writeContract should NOT have been called expect(mockFacilitatorSigner.writeContract).not.toHaveBeenCalled(); expect(result.success).toBe(true); }); + + it("should resolve extension signer by network when signerForNetwork is present", async () => { + const { parseTransaction, recoverTransactionAddress } = await import("viem"); + vi.mocked(parseTransaction).mockReturnValue({ + to: TOKEN_ADDRESS, + data: APPROVE_CALLDATA as `0x${string}`, + } as any); + vi.mocked(recoverTransactionAddress).mockResolvedValue(PAYER); + + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ functionName }: { functionName: string }) => { + if (functionName === "allowance") return Promise.resolve(0n); + if (functionName === "balanceOf") return Promise.resolve(BigInt("10000000")); + return Promise.resolve(0n); + }); + + const selectedSignerSendTransactions = vi + .fn() + .mockResolvedValue(["0xsettle_hash" as `0x${string}`]); + const selectedSignerWait = vi.fn().mockResolvedValue({ status: "success" }); + const fallbackSignerSendTransactions = vi.fn(); + + const mockContext = { + getExtension: vi.fn().mockImplementation((key: string) => { + if (key !== ERC20_APPROVAL_GAS_SPONSORING_KEY) return undefined; + return { + key: ERC20_APPROVAL_GAS_SPONSORING_KEY, + signer: { + getAddresses: vi.fn().mockReturnValue([PAYER]), + readContract: mockFacilitatorSigner.readContract, + verifyTypedData: mockFacilitatorSigner.verifyTypedData, + writeContract: vi.fn(), + sendTransaction: vi.fn(), + waitForTransactionReceipt: selectedSignerWait, + getCode: vi.fn().mockResolvedValue("0x"), + sendTransactions: fallbackSignerSendTransactions, + }, + signerForNetwork: (network: string) => { + if (network !== "eip155:84532") return undefined; + return { + getAddresses: vi.fn().mockReturnValue([PAYER]), + readContract: mockFacilitatorSigner.readContract, + verifyTypedData: mockFacilitatorSigner.verifyTypedData, + writeContract: vi.fn(), + sendTransaction: vi.fn(), + waitForTransactionReceipt: selectedSignerWait, + getCode: vi.fn().mockResolvedValue("0x"), + sendTransactions: selectedSignerSendTransactions, + }; + }, + }; + }), + }; + + const payload = makeErc20Permit2Payload(makeValidErc20Extension()); + await facilitator.settle(payload, erc20Requirements, mockContext); + + expect(selectedSignerSendTransactions).toHaveBeenCalled(); + expect(fallbackSignerSendTransactions).not.toHaveBeenCalled(); + }); }); }); diff --git a/typescript/packages/mechanisms/evm/test/unit/signer.test.ts b/typescript/packages/mechanisms/evm/test/unit/signer.test.ts index ed2faf15fa..2eaf5737e5 100644 --- a/typescript/packages/mechanisms/evm/test/unit/signer.test.ts +++ b/typescript/packages/mechanisms/evm/test/unit/signer.test.ts @@ -31,15 +31,15 @@ describe("EVM Signer Converters", () => { expect(result.readContract).toBeDefined(); }); - it("should throw when neither signer nor publicClient has readContract", () => { + it("should return minimal signer when no readContract exists", () => { const mockAccount = { address: "0x1234567890123456789012345678901234567890" as `0x${string}`, signTypedData: async () => "0xsignature" as `0x${string}`, }; - expect(() => toClientEvmSigner(mockAccount)).toThrow( - "toClientEvmSigner requires either a signer with readContract or a publicClient", - ); + const result = toClientEvmSigner(mockAccount); + expect(result.address).toBe(mockAccount.address); + expect(result.readContract).toBeUndefined(); }); }); diff --git a/typescript/pnpm-lock.yaml b/typescript/pnpm-lock.yaml index 6d8623cc6a..9b3e47ec27 100644 --- a/typescript/pnpm-lock.yaml +++ b/typescript/pnpm-lock.yaml @@ -1158,9 +1158,6 @@ importers: '@x402/core': specifier: workspace:~ version: link:../../core - '@x402/extensions': - specifier: workspace:~ - version: link:../../extensions viem: specifier: ^2.39.3 version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) diff --git a/typescript/site/app/facilitator/index.ts b/typescript/site/app/facilitator/index.ts index a8cb83ecfc..82f039d85d 100644 --- a/typescript/site/app/facilitator/index.ts +++ b/typescript/site/app/facilitator/index.ts @@ -133,10 +133,35 @@ async function createFacilitator(): Promise { ); } + // Build ERC-20 approval signer with sendTransactions for Permit2 gas sponsoring + const erc20ApprovalSigner = { + ...evmSigner, + sendTransactions: async ( + transactions: (`0x${string}` | { to: `0x${string}`; data: `0x${string}`; gas?: bigint })[], + ): Promise<`0x${string}`[]> => { + const hashes: `0x${string}`[] = []; + for (const tx of transactions) { + let hash: `0x${string}`; + if (typeof tx === "string") { + hash = await viemClient.sendRawTransaction({ serializedTransaction: tx }); + } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + hash = await viemClient.sendTransaction(tx as any); + } + const receipt = await viemClient.waitForTransactionReceipt({ hash }); + if (receipt.status !== "success") { + throw new Error(`transaction_failed: ${hash}`); + } + hashes.push(hash); + } + return hashes; + }, + }; + // Register gas sponsorship extensions for Permit2 support facilitator .registerExtension(EIP2612_GAS_SPONSORING) - .registerExtension(createErc20ApprovalGasSponsoringExtension(evmSigner, viemClient)); + .registerExtension(createErc20ApprovalGasSponsoringExtension(erc20ApprovalSigner)); return facilitator; } From 516f55f66a7ad379fd5aaae0908e36e03c01f234 Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:17:19 +0900 Subject: [PATCH 044/129] Add Stellar blockchain support documentation (#1451) * Update docs/sdk-features.md Generated-By: mintlify-agent * Update docs/getting-started/quickstart-for-buyers.mdx Generated-By: mintlify-agent * Update docs/getting-started/quickstart-for-buyers.mdx Generated-By: mintlify-agent * Update docs/getting-started/quickstart-for-buyers.mdx Generated-By: mintlify-agent * Update docs/core-concepts/network-and-token-support.mdx Generated-By: mintlify-agent * Update docs/core-concepts/network-and-token-support.mdx Generated-By: mintlify-agent * Update docs/core-concepts/network-and-token-support.mdx Generated-By: mintlify-agent * Update docs/core-concepts/network-and-token-support.mdx Generated-By: mintlify-agent --------- Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- .../network-and-token-support.mdx | 12 +++++++-- .../getting-started/quickstart-for-buyers.mdx | 26 +++++++++++++++++++ docs/sdk-features.md | 2 ++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/docs/core-concepts/network-and-token-support.mdx b/docs/core-concepts/network-and-token-support.mdx index da14a7d96e..aaa7e9afc5 100644 --- a/docs/core-concepts/network-and-token-support.mdx +++ b/docs/core-concepts/network-and-token-support.mdx @@ -17,6 +17,8 @@ x402 V2 uses [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) standard network i | `solana-devnet` | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | - | Solana Devnet | | - | `aptos:1` | 1 | Aptos Mainnet | | - | `aptos:2` | 2 | Aptos Testnet | +| - | `stellar:pubnet` | - | Stellar Mainnet | +| - | `stellar:testnet` | - | Stellar Testnet | | `avalanche` | `eip155:43114` | 43114 | Avalanche C-Chain mainnet | | `avalanche-fuji` | `eip155:43113` | 43113 | Avalanche Fuji testnet | | `polygon` | `eip155:137` | 137 | Polygon mainnet | @@ -29,6 +31,7 @@ x402 V2 uses [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) standard network i ### Format Explanation - **EVM networks**: `eip155:` where chainId is the numeric chain identifier - **Solana**: `solana:` where genesisHash is the first 32 bytes of the genesis block hash +- **Stellar**: `stellar:` where network is `pubnet` (mainnet) or `testnet` - **Aptos**: `aptos:` where chainId is the numeric chain identifier ## Overview @@ -50,13 +53,14 @@ Multiple production-ready facilitators are available supporting various networks ### Token Support -x402 supports tokens on EVM, Solana, and Aptos networks: +x402 supports tokens on EVM, Solana, Stellar, and Aptos networks: * **EVM**: Any ERC-20 token that implements the EIP-3009 standard * **Solana**: Any SPL or token-2022 token +* **Stellar**: Any Soroban token implementing SEP-41 * **Aptos**: Any fungible asset using Aptos's native fungible asset framework -**Important**: Facilitators support networks, not specific tokens β€” any EIP-3009 compatible token works on EVM networks, any SPL/token-2022 token works on Solana, and any fungible asset works on Aptos, for the facilitators that support those networks. +**Important**: Facilitators support networks, not specific tokens β€” any EIP-3009 compatible token works on EVM networks, any SPL/token-2022 token works on Solana, any SEP-41 token works on Stellar, and any fungible asset works on Aptos, for the facilitators that support those networks. #### EVM: EIP-3009 Requirement @@ -103,6 +107,10 @@ These values are used in the `eip712` nested object when configuring TokenAmount On Solana, x402 supports all SPL tokens and Token 2022 tokens. When using facilitators that support Solana or Solana Devnet, payments can be made in any SPL/token-2022 token, including USDC (SPL). No EIP-712 configuration is required on Solana. +#### Stellar: Soroban Tokens + +On Stellar, x402 supports all Soroban tokens implementing [SEP-41](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0041.md). Payments use the `transfer(from, to, amount)` function. The TypeScript SDK supports sponsored transactions where facilitators pay gas fees on behalf of clients. Stellar uses ledger-based expiration (default ~12 ledgers β‰ˆ 60 seconds) instead of timestamps. + #### Aptos: Fungible Assets On Aptos, x402 supports all fungible assets using Aptos's native fungible asset framework. Payments use the `primary_fungible_store::transfer` function for automatic store creation and management. The TypeScript SDK supports sponsored transactions where facilitators pay gas fees on behalf of clients. diff --git a/docs/getting-started/quickstart-for-buyers.mdx b/docs/getting-started/quickstart-for-buyers.mdx index b95796ab83..003524dc8a 100644 --- a/docs/getting-started/quickstart-for-buyers.mdx +++ b/docs/getting-started/quickstart-for-buyers.mdx @@ -32,6 +32,9 @@ There are pre-configured [examples available in the x402 repo](https://github.co # For Aptos support, also add: npm install @x402/aptos + + # For Stellar support, also add: + npm install @x402/stellar ``` @@ -135,6 +138,20 @@ const privateKey = new Ed25519PrivateKey(process.env.APTOS_PRIVATE_KEY!); const aptosSigner = Account.fromPrivateKey({ privateKey }); ``` +#### Stellar + +Use the Stellar SDK to instantiate a signer: + +```typescript +import { createEd25519Signer } from "@x402/stellar"; + +// Create signer from private key (S... format) +const stellarSigner = createEd25519Signer( + process.env.STELLAR_PRIVATE_KEY!, + "stellar:testnet" +); +``` + ### 3. Make Paid Requests Automatically @@ -387,6 +404,15 @@ You can register multiple payment schemes to handle different networks: const aptosPrivateKey = new Ed25519PrivateKey(process.env.APTOS_PRIVATE_KEY!); const aptosSigner = Account.fromPrivateKey({ privateKey: aptosPrivateKey }); client.register("aptos:*", new ExactAptosScheme(aptosSigner)); + + // For Stellar support, also add: + import { ExactStellarScheme, createEd25519Signer } from "@x402/stellar"; + + const stellarSigner = createEd25519Signer( + process.env.STELLAR_PRIVATE_KEY!, + "stellar:testnet" + ); + client.register("stellar:*", new ExactStellarScheme(stellarSigner)); ``` diff --git a/docs/sdk-features.md b/docs/sdk-features.md index d876b2e76b..326a5bd6da 100644 --- a/docs/sdk-features.md +++ b/docs/sdk-features.md @@ -28,6 +28,7 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt |---------|------------|-----|--------| | evm (EIP-155) | βœ… | βœ… | βœ… | | svm (Solana) | βœ… | βœ… | βœ… | +| stellar | βœ… | ❌ | ❌ | | aptos | βœ… | ❌ | ❌ | ## Mechanisms @@ -36,6 +37,7 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt |-----------|------------|-----|--------| | exact/evm (EIP-3009) | βœ… | βœ… | βœ… | | exact/svm (SPL) | βœ… | βœ… | βœ… | +| exact/stellar (Soroban) | βœ… | ❌ | ❌ | | exact/aptos (Fungible Assets) | βœ… | ❌ | ❌ | ## Extensions From 60108c905e441b301953bdde36b405bcf1ed1008 Mon Sep 17 00:00:00 2001 From: Plag Date: Tue, 10 Mar 2026 00:15:20 -0700 Subject: [PATCH 045/129] Update metadata.json (#1546) --- .../ecosystem/partners-data/spraay-x402-gateway/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json b/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json index ceb0646ca2..da1d0a5249 100644 --- a/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json +++ b/typescript/site/app/ecosystem/partners-data/spraay-x402-gateway/metadata.json @@ -1,7 +1,7 @@ { "name": "Spraay x402 Gateway", - "description": "Full-stack x402 infrastructure platform with 62 paid endpoints across 8 categories. AI chat (200+ models), batch payments (200 recipients/tx), token swaps (Uniswap V3), price oracle, cross-chain bridge (11 chains), payroll, invoicing, escrow, wallet analytics, AI inference, GPU/Compute (image/video/LLM/audio via Replicate), web search & RAG (Tavily), email/SMS, webhooks, XMTP messaging, multi-chain RPC, IPFS storage, cron scheduling, logging, KYC/KYB, auth/SSO, audit trails, and crypto tax. 63-tool MCP server on Smithery. USDC on Base. No API keys, no accounts.", + "description": "Full-stack x402 infrastructure platform with 62 paid endpoints across 11 categories. AI chat (200+ models), batch payments (200 recipients/tx), token swaps (Uniswap V3), price oracle, cross-chain bridge (11 chains), payroll, invoicing, escrow, wallet analytics, AI inference, GPU/Compute (image/video/LLM/audio via Replicate), web search & RAG (Tavily), email/SMS, webhooks, XMTP messaging, multi-chain RPC, IPFS storage, cron scheduling, logging, KYC/KYB, auth/SSO, audit trails, and crypto tax. 63-tool MCP server on Smithery. USDC on Base. No API keys, no accounts.", "logoUrl": "/logos/spraay.png", - "websiteUrl": "https://gateway.spraay.app", + "websiteUrl": "https://docs.spraay.app", "category": "Services/Endpoints" } From 0f74fb46506d642a947cbcd4743377126027090b Mon Sep 17 00:00:00 2001 From: Sannie Kwan Date: Tue, 10 Mar 2026 00:56:52 -0700 Subject: [PATCH 046/129] Add solana-pay-x402 to ecosystem (Infrastructure & Tooling) (#1543) --- .../partners-data/solana-pay-x402/metadata.json | 7 +++++++ typescript/site/public/logos/solana-pay-x402.png | Bin 0 -> 7740 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/solana-pay-x402/metadata.json create mode 100644 typescript/site/public/logos/solana-pay-x402.png diff --git a/typescript/site/app/ecosystem/partners-data/solana-pay-x402/metadata.json b/typescript/site/app/ecosystem/partners-data/solana-pay-x402/metadata.json new file mode 100644 index 0000000000..9e21b81696 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/solana-pay-x402/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "solana-pay-x402", + "category": "Infrastructure & Tooling", + "logoUrl": "/logos/solana-pay-x402.png", + "description": "HTTP 402 payment middleware for Solana (Express + Next.js). Supports x402 v2 programmatic flows and Solana Pay QR code transactions from a single integration.", + "websiteUrl": "https://www.npmjs.com/package/solana-pay-x402" +} \ No newline at end of file diff --git a/typescript/site/public/logos/solana-pay-x402.png b/typescript/site/public/logos/solana-pay-x402.png new file mode 100644 index 0000000000000000000000000000000000000000..5a10002716323070fd6e4aedb00a5524ac3ba13a GIT binary patch literal 7740 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 Ilz$iYKk@=4y#N3J literal 0 HcmV?d00001 From f43339a4f3d056e6b7760d944ad8a9d7a1b3cf43 Mon Sep 17 00:00:00 2001 From: phdargen Date: Wed, 11 Mar 2026 02:03:22 +0900 Subject: [PATCH 047/129] Fixed paywall config injection (#1550) --- go/.changes/unreleased/fixed-20260310-221203.yaml | 3 +++ go/http/paywall_test.go | 2 +- go/http/server.go | 4 ++-- python/x402/changelog.d/1550.bugfix.md | 1 + python/x402/http/paywall/__init__.py | 4 ++-- python/x402/http/x402_http_server_base.py | 2 +- 6 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 go/.changes/unreleased/fixed-20260310-221203.yaml create mode 100644 python/x402/changelog.d/1550.bugfix.md diff --git a/go/.changes/unreleased/fixed-20260310-221203.yaml b/go/.changes/unreleased/fixed-20260310-221203.yaml new file mode 100644 index 0000000000..75dd360069 --- /dev/null +++ b/go/.changes/unreleased/fixed-20260310-221203.yaml @@ -0,0 +1,3 @@ +kind: fixed +body: Fixed paywall config injection targeting `` causing SVG parse errors in the browser +time: 2026-03-10T22:12:03.806859+09:00 diff --git a/go/http/paywall_test.go b/go/http/paywall_test.go index 96ea50891d..ae1684bdd5 100644 --- a/go/http/paywall_test.go +++ b/go/http/paywall_test.go @@ -277,7 +277,7 @@ func TestRegisterPaywallProvider(t *testing.T) { // --- injectPaywallConfig tests --- func TestInjectPaywallConfig(t *testing.T) { - template := "" + template := "" paymentReq := makePaymentRequired("eip155:8453") t.Run("injects window.x402 config", func(t *testing.T) { diff --git a/go/http/server.go b/go/http/server.go index ecc9660857..a8c1dd3f7c 100644 --- a/go/http/server.go +++ b/go/http/server.go @@ -939,7 +939,7 @@ func (s *x402HTTPResourceServer) generatePaywallHTML(paymentRequired x402.Paymen // Select template based on network template := s.selectPaywallTemplate(paymentRequired) - return strings.Replace(template, "", configScript+"", 1) + return strings.Replace(template, "", configScript+"\n", 1) } // selectPaywallTemplate chooses the appropriate paywall template based on the network @@ -1023,7 +1023,7 @@ func injectPaywallConfig(template string, paymentRequired types.PaymentRequired, html.EscapeString(currentURL), ) - return strings.Replace(template, "", configScript+"", 1) + return strings.Replace(template, "", configScript+"\n", 1) } // ============================================================================ diff --git a/python/x402/changelog.d/1550.bugfix.md b/python/x402/changelog.d/1550.bugfix.md new file mode 100644 index 0000000000..4dfa4b1a09 --- /dev/null +++ b/python/x402/changelog.d/1550.bugfix.md @@ -0,0 +1 @@ +Fixed paywall config injection targeting causing SVG parse errors in the browser diff --git a/python/x402/http/paywall/__init__.py b/python/x402/http/paywall/__init__.py index 1d02a3f5f1..26147ba100 100644 --- a/python/x402/http/paywall/__init__.py +++ b/python/x402/http/paywall/__init__.py @@ -166,7 +166,7 @@ def generate_html( window.x402 = {htmlsafe_json_dumps(x402_config)}; """ - return template.replace("", f"{config_script}\n") + return template.replace("", f"{config_script}\n", 1) def _fallback_html( self, @@ -243,7 +243,7 @@ def generate_html( window.x402 = {htmlsafe_json_dumps(x402_config)}; """ - return template.replace("", f"{config_script}\n") + return template.replace("", f"{config_script}\n", 1) def _fallback_html( self, diff --git a/python/x402/http/x402_http_server_base.py b/python/x402/http/x402_http_server_base.py index afb5afc575..1fc2228796 100644 --- a/python/x402/http/x402_http_server_base.py +++ b/python/x402/http/x402_http_server_base.py @@ -749,7 +749,7 @@ def _inject_paywall_config( f"" ) - return template.replace("", config_script + "") + return template.replace("", config_script + "\n", 1) def _generate_fallback_html( self, From 1a6e08b291e70d951df86d39e132e6288f16ba79 Mon Sep 17 00:00:00 2001 From: phdargen Date: Wed, 11 Mar 2026 02:04:52 +0900 Subject: [PATCH 048/129] EVM verify simulation and improved smart account handling (#1474) * fix evm sim * fix EIP-6492 deployment info check * fix implementation-dependent verifyTypedData * same for v1 * update multicall * update errors * refactor * minor fixes * add go equivalent * add py equivalent * fix #1388 for go/py * fix #1139 for py/go * fix go signer --- e2e/facilitators/go/main.go | 25 +- examples/go/facilitator/advanced/signer.go | 22 +- examples/go/facilitator/basic/signer.go | 25 +- examples/typescript/pnpm-lock.yaml | 589 ++++---------- .../unreleased/changed-20260310-170850.yaml | 3 + go/http/server.go | 1 + go/http/server_test.go | 61 ++ go/mechanisms/evm/constants.go | 57 ++ .../evm/exact/facilitator/eip3009.go | 214 +++++ .../evm/exact/facilitator/eip3009_helpers.go | 448 +++++++++++ go/mechanisms/evm/exact/facilitator/errors.go | 42 +- go/mechanisms/evm/exact/facilitator/scheme.go | 416 +--------- .../evm/exact/v1/facilitator/errors.go | 2 +- .../evm/exact/v1/facilitator/scheme.go | 188 ++--- go/mechanisms/evm/multicall.go | 202 +++++ go/mechanisms/evm/verify_universal.go | 29 +- go/mechanisms/evm/verify_universal_test.go | 8 +- go/server.go | 18 +- go/server_test.go | 13 + go/test/integration/evm_test.go | 121 ++- go/test/unit/evm_client_facilitator_test.go | 432 ++++++++++ go/types.go | 11 +- python/x402/changelog.d/1474.feature.md | 1 + python/x402/http/x402_http_server.py | 2 + python/x402/mechanisms/evm/__init__.py | 4 +- python/x402/mechanisms/evm/constants.py | 61 +- .../mechanisms/evm/exact/eip3009_utils.py | 315 ++++++++ .../x402/mechanisms/evm/exact/facilitator.py | 202 +++-- python/x402/mechanisms/evm/exact/register.py | 12 +- .../mechanisms/evm/exact/v1/facilitator.py | 165 ++-- python/x402/mechanisms/evm/multicall.py | 172 ++++ .../x402/mechanisms/svm/exact/facilitator.py | 2 +- python/x402/schemas/config.py | 1 + python/x402/server_base.py | 5 +- .../integrations/test_http_integration.py | 40 + python/x402/tests/unit/core/test_server.py | 59 ++ .../unit/mechanisms/evm/test_facilitator.py | 757 ++++++++++-------- .../tests/unit/mechanisms/evm/test_verify.py | 93 +++ typescript/.changeset/slimy-baths-marry.md | 5 + typescript/package.json | 4 +- .../packages/mechanisms/evm/src/constants.ts | 17 + .../src/exact/facilitator/eip3009-utils.ts | 240 ++++++ .../evm/src/exact/facilitator/eip3009.ts | 223 +++--- .../evm/src/exact/facilitator/errors.ts | 17 +- .../evm/src/exact/facilitator/register.ts | 9 + .../evm/src/exact/facilitator/scheme.ts | 7 + .../evm/src/exact/v1/facilitator/scheme.ts | 436 +++++----- .../packages/mechanisms/evm/src/multicall.ts | 140 ++++ .../evm/test/unit/exact/facilitator.test.ts | 243 +++++- .../evm/test/unit/v1/facilitator.test.ts | 18 +- 50 files changed, 4204 insertions(+), 1973 deletions(-) create mode 100644 go/.changes/unreleased/changed-20260310-170850.yaml create mode 100644 go/mechanisms/evm/exact/facilitator/eip3009.go create mode 100644 go/mechanisms/evm/exact/facilitator/eip3009_helpers.go create mode 100644 go/mechanisms/evm/multicall.go create mode 100644 python/x402/changelog.d/1474.feature.md create mode 100644 python/x402/mechanisms/evm/exact/eip3009_utils.py create mode 100644 python/x402/mechanisms/evm/multicall.py create mode 100644 python/x402/tests/unit/mechanisms/evm/test_verify.py create mode 100644 typescript/.changeset/slimy-baths-marry.md create mode 100644 typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009-utils.ts create mode 100644 typescript/packages/mechanisms/evm/src/multicall.ts diff --git a/e2e/facilitators/go/main.go b/e2e/facilitators/go/main.go index ff55ada83d..6c857260ef 100644 --- a/e2e/facilitators/go/main.go +++ b/e2e/facilitators/go/main.go @@ -212,6 +212,11 @@ func (s *realFacilitatorEvmSigner) ReadContract( return nil, fmt.Errorf("failed to parse ABI: %w", err) } + methodObj, exists := contractABI.Methods[method] + if !exists { + return nil, fmt.Errorf("method %s not found in ABI", method) + } + // Pack the method call data, err := contractABI.Pack(method, args...) if err != nil { @@ -230,26 +235,12 @@ func (s *realFacilitatorEvmSigner) ReadContract( return nil, fmt.Errorf("failed to call contract: %w", err) } - // 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") + if len(methodObj.Outputs) == 0 { + return nil, nil } // 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) + output, err := methodObj.Outputs.Unpack(result) if err != nil { return nil, fmt.Errorf("failed to unpack result: %w", err) } diff --git a/examples/go/facilitator/advanced/signer.go b/examples/go/facilitator/advanced/signer.go index 19f57d0857..eac33b0a58 100644 --- a/examples/go/facilitator/advanced/signer.go +++ b/examples/go/facilitator/advanced/signer.go @@ -190,6 +190,11 @@ func (s *facilitatorEvmSigner) ReadContract( return nil, fmt.Errorf("failed to parse ABI: %w", err) } + methodObj, exists := contractABI.Methods[method] + if !exists { + return nil, fmt.Errorf("method %s not found in ABI", method) + } + // Pack the method call data, err := contractABI.Pack(method, args...) if err != nil { @@ -209,23 +214,11 @@ func (s *facilitatorEvmSigner) ReadContract( 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") + if len(methodObj.Outputs) == 0 { + return nil, nil } // 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) @@ -606,4 +599,3 @@ func getBigIntFromInterface(v interface{}) *big.Int { } return big.NewInt(0) } - diff --git a/examples/go/facilitator/basic/signer.go b/examples/go/facilitator/basic/signer.go index 19f57d0857..442da10515 100644 --- a/examples/go/facilitator/basic/signer.go +++ b/examples/go/facilitator/basic/signer.go @@ -184,12 +184,18 @@ func (s *facilitatorEvmSigner) ReadContract( 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) } + methodObj, exists := contractABI.Methods[method] + if !exists { + return nil, fmt.Errorf("method %s not found in ABI", method) + } + // Pack the method call data, err := contractABI.Pack(method, args...) if err != nil { @@ -208,24 +214,12 @@ func (s *facilitatorEvmSigner) ReadContract( 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") + + if len(methodObj.Outputs) == 0 { + return nil, nil } // 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) @@ -606,4 +600,3 @@ func getBigIntFromInterface(v interface{}) *big.Int { } return big.NewInt(0) } - diff --git a/examples/typescript/pnpm-lock.yaml b/examples/typescript/pnpm-lock.yaml index 16ac03175f..3a80de4c92 100644 --- a/examples/typescript/pnpm-lock.yaml +++ b/examples/typescript/pnpm-lock.yaml @@ -1624,7 +1624,7 @@ importers: version: 16.6.1 openai: specifier: ^4.77.3 - version: 4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + version: 4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) viem: specifier: ^2.39.0 version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -1914,10 +1914,10 @@ importers: dependencies: '@coinbase/onchainkit': specifier: 1.1.2 - version: 1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(zod@4.1.13) + version: 1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76))(zod@3.25.76) '@farcaster/miniapp-sdk': specifier: 0.2.1 - version: 0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + version: 0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@tanstack/react-query': specifier: ^5 version: 5.90.11(react@19.2.3) @@ -1944,10 +1944,10 @@ importers: version: 19.2.3(react@19.2.3) viem: specifier: ^2.27.2 - version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) wagmi: specifier: ^2.14.11 - version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) devDependencies: '@eslint/js': specifier: ^9.24.0 @@ -3349,6 +3349,70 @@ importers: specifier: ^5.3.0 version: 5.9.2 + servers/receipt-attestation: + 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.4.7 + version: 16.6.1 + express: + specifier: ^4.18.2 + version: 4.21.2 + viem: + specifier: ^2.39.0 + version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.33.0 + '@types/express': + specifier: ^5.0.1 + version: 5.0.3 + '@types/node': + specifier: ^20.0.0 + version: 20.19.11 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.24.0 + version: 9.33.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.4 + typescript: + specifier: ^5.3.0 + version: 5.9.2 + servers/sign-in-with-x: dependencies: '@x402/core': @@ -14381,16 +14445,16 @@ snapshots: - ws - zod - '@base-org/account@2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': + '@base-org/account@2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)': dependencies: '@coinbase/cdp-sdk': 1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@noble/hashes': 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 - ox: 0.6.9(typescript@5.9.2)(zod@4.1.13) + ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) preact: 10.24.2 - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zustand: 5.0.3(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) transitivePeerDependencies: - '@types/react' @@ -14735,10 +14799,10 @@ snapshots: - ws - zod - '@coinbase/onchainkit@1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(zod@4.1.13)': + '@coinbase/onchainkit@1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76))(zod@3.25.76)': dependencies: - '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@farcaster/miniapp-wagmi-connector': 1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@farcaster/miniapp-wagmi-connector': 1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) '@floating-ui/react': 0.27.16(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -14746,7 +14810,7 @@ snapshots: '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-toast': 1.2.15(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) clsx: 2.1.1 graphql: 16.11.0 graphql-request: 6.1.0(encoding@0.1.13)(graphql@16.11.0) @@ -14755,8 +14819,8 @@ snapshots: react-dom: 19.2.3(react@19.2.3) tailwind-merge: 3.4.0 usehooks-ts: 3.1.1(react@19.2.3) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) transitivePeerDependencies: - '@tanstack/query-core' - '@types/react' @@ -14883,15 +14947,15 @@ snapshots: - utf-8-validate - zod - '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13)': + '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76)': 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.9.2)(zod@4.1.13) + ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) preact: 10.24.2 - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zustand: 5.0.3(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) transitivePeerDependencies: - '@types/react' @@ -15080,7 +15144,7 @@ snapshots: '@es-joy/jsdoccomment@0.50.2': dependencies: '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.40.0 + '@typescript-eslint/types': 8.48.0 comment-parser: 1.4.1 esquery: 1.6.0 jsdoc-type-pratt-parser: 4.1.0 @@ -15454,11 +15518,11 @@ snapshots: - utf-8-validate - zod - '@farcaster/miniapp-wagmi-connector@1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))': + '@farcaster/miniapp-wagmi-connector@1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: - '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@farcaster/miniapp-wagmi-connector@1.0.0(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.1))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: @@ -17544,7 +17608,7 @@ snapshots: dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -17574,13 +17638,13 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + '@reown/appkit-controllers@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -17748,12 +17812,12 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + '@reown/appkit-pay@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) lit: 3.3.0 valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) transitivePeerDependencies: @@ -17931,12 +17995,12 @@ snapshots: - valtio - zod - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13)': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 transitivePeerDependencies: @@ -18103,10 +18167,10 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + '@reown/appkit-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 qrcode: 1.5.3 @@ -18255,7 +18319,7 @@ snapshots: '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -18285,16 +18349,16 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13)': + '@reown/appkit-utils@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -18470,7 +18534,7 @@ snapshots: '@reown/appkit-utils': 1.7.8(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.10)(react@19.2.3))(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) @@ -18501,21 +18565,21 @@ snapshots: - utf-8-validate - zod - '@reown/appkit@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + '@reown/appkit@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-pay': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-pay': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -19143,7 +19207,7 @@ snapshots: '@solana/errors@2.3.0(typescript@5.9.2)': dependencies: chalk: 5.6.2 - commander: 14.0.2 + commander: 14.0.3 typescript: 5.9.2 '@solana/errors@3.0.3(typescript@5.9.2)': @@ -20178,7 +20242,7 @@ snapshots: '@solana/rpc-spec': 3.0.3(typescript@5.9.2) '@solana/rpc-spec-types': 3.0.3(typescript@5.9.2) typescript: 5.9.2 - undici-types: 7.16.0 + undici-types: 7.22.0 '@solana/rpc-transport-http@5.0.0(typescript@5.9.2)': dependencies: @@ -21704,18 +21768,18 @@ snapshots: - utf-8-validate - zod - '@wagmi/connectors@6.2.0(1aee367860625464d156864b651beb8c)': + '@wagmi/connectors@6.2.0(26b6de6e2b894d3d8ec3de3fd9d7a34e)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 @@ -21757,19 +21821,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(26b6de6e2b894d3d8ec3de3fd9d7a34e)': + '@wagmi/connectors@6.2.0(696284975690661567148e5458660a80)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) - '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@base-org/account': 2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -22278,11 +22342,11 @@ snapshots: - react - use-sync-external-store - '@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))': + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.9.2) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zustand: 5.0.0(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) optionalDependencies: '@tanstack/query-core': 5.90.11 @@ -22389,49 +22453,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/core@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-provider': 1.0.14 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/logger': 2.1.2 - '@walletconnect/relay-api': 1.0.11 - '@walletconnect/relay-auth': 1.1.0 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/window-getters': 1.0.1 - es-toolkit: 1.33.0 - events: 3.3.0 - uint8arrays: 3.1.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/core@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/heartbeat': 1.2.2 @@ -22518,49 +22539,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/core@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-provider': 1.0.14 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/logger': 2.1.2 - '@walletconnect/relay-api': 1.0.11 - '@walletconnect/relay-auth': 1.1.0 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/window-getters': 1.0.1 - es-toolkit: 1.33.0 - events: 3.3.0 - uint8arrays: 3.1.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/environment@1.0.1': dependencies: tslib: 1.14.1 @@ -22693,10 +22671,10 @@ snapshots: '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/utils': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -22725,18 +22703,18 @@ snapshots: - utf-8-validate - zod - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: - '@reown/appkit': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/utils': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -22927,41 +22905,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/sign-client@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@walletconnect/core': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/logger': 2.1.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - events: 3.3.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/sign-client@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/core': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -23032,41 +22975,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/sign-client@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@walletconnect/core': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/events': 1.0.1 - '@walletconnect/heartbeat': 1.2.2 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/logger': 2.1.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - events: 3.3.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/time@1.0.2': dependencies: tslib: 1.14.1 @@ -23205,45 +23113,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@walletconnect/events': 1.0.1 - '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) - '@walletconnect/jsonrpc-provider': 1.0.14 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - es-toolkit: 1.33.0 - events: 3.3.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - encoding - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/universal-provider@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/events': 1.0.1 @@ -23322,45 +23191,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/universal-provider@2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@walletconnect/events': 1.0.1 - '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) - '@walletconnect/jsonrpc-provider': 1.0.14 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/logger': 2.1.2 - '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - es-toolkit: 1.33.0 - events: 3.3.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - encoding - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/utils@2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 @@ -23447,49 +23277,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@noble/ciphers': 1.2.1 - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/relay-api': 1.0.11 - '@walletconnect/relay-auth': 1.1.0 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 - bs58: 6.0.0 - detect-browser: 5.3.0 - query-string: 7.1.3 - uint8arrays: 3.1.0 - viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - 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/kv' - - aws4fetch - - bufferutil - - db0 - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/utils@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 @@ -23576,49 +23363,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/utils@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': - dependencies: - '@noble/ciphers': 1.2.1 - '@noble/curves': 1.8.1 - '@noble/hashes': 1.7.1 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/relay-api': 1.0.11 - '@walletconnect/relay-auth': 1.1.0 - '@walletconnect/safe-json': 1.0.2 - '@walletconnect/time': 1.0.2 - '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/window-getters': 1.0.1 - '@walletconnect/window-metadata': 1.0.1 - bs58: 6.0.0 - detect-browser: 5.3.0 - query-string: 7.1.3 - uint8arrays: 3.1.0 - viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - 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/kv' - - aws4fetch - - bufferutil - - db0 - - ioredis - - typescript - - uploadthing - - utf-8-validate - - zod - '@walletconnect/window-getters@1.0.1': dependencies: tslib: 1.14.1 @@ -25318,7 +25062,7 @@ snapshots: 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 @@ -26562,7 +26306,7 @@ snapshots: whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil @@ -27199,21 +26943,6 @@ snapshots: dependencies: mimic-fn: 2.1.0 - openai@4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): - dependencies: - '@types/node': 18.19.123 - '@types/node-fetch': 2.6.13 - abort-controller: 3.0.0 - agentkeepalive: 4.6.0 - form-data-encoder: 1.7.2 - formdata-node: 4.4.1 - node-fetch: 2.7.0(encoding@0.1.13) - optionalDependencies: - ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) - zod: 3.25.76 - transitivePeerDependencies: - - encoding - openai@4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): dependencies: '@types/node': 18.19.123 @@ -27764,21 +27493,21 @@ snapshots: - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)): dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) hono: 4.10.7 idb-keyval: 6.2.2 mipd: 0.0.7(typescript@5.9.2) ox: 0.9.17(typescript@5.9.2)(zod@4.1.13) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) zod: 4.1.13 zustand: 5.0.8(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) optionalDependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) react: 19.2.3 typescript: 5.9.2 - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) transitivePeerDependencies: - '@types/react' - immer @@ -28318,7 +28047,7 @@ snapshots: buffer: 6.0.3 eventemitter3: 5.0.1 uuid: 8.3.2 - ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: bufferutil: 4.0.9 utf-8-validate: 5.0.10 @@ -29989,14 +29718,14 @@ snapshots: - ws - zod - wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): dependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/connectors': 6.2.0(1aee367860625464d156864b651beb8c) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@wagmi/connectors': 6.2.0(696284975690661567148e5458660a80) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: diff --git a/go/.changes/unreleased/changed-20260310-170850.yaml b/go/.changes/unreleased/changed-20260310-170850.yaml new file mode 100644 index 0000000000..1dd67b4d45 --- /dev/null +++ b/go/.changes/unreleased/changed-20260310-170850.yaml @@ -0,0 +1,3 @@ +kind: changed +body: Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling +time: 2026-03-10T17:08:50.404017+09:00 diff --git a/go/http/server.go b/go/http/server.go index a8c1dd3f7c..af76c8d777 100644 --- a/go/http/server.go +++ b/go/http/server.go @@ -392,6 +392,7 @@ func (s *x402HTTPResourceServer) BuildPaymentRequirementsFromOptions(ctx context Price: resolvedPrice, Network: option.Network, MaxTimeoutSeconds: option.MaxTimeoutSeconds, + Extra: option.Extra, } // Use existing BuildPaymentRequirementsFromConfig for each option diff --git a/go/http/server_test.go b/go/http/server_test.go index e93c79e545..1aa760fd2d 100644 --- a/go/http/server_test.go +++ b/go/http/server_test.go @@ -189,6 +189,67 @@ func TestProcessHTTPRequestPaymentRequired(t *testing.T) { } } +func TestBuildPaymentRequirementsFromOptionsPreservesOptionExtra(t *testing.T) { + ctx := context.Background() + + routes := RoutesConfig{ + "GET /api": { + Accepts: PaymentOptions{ + { + Scheme: "exact", + PayTo: "0xtest", + Price: "$1.00", + Network: "eip155:1", + Extra: map[string]interface{}{ + "assetTransferMethod": "permit2", + "merchantNote": "route-level-extra", + }, + }, + }, + }, + } + + mockServer := &mockSchemeServer{scheme: "exact"} + mockClient := &mockFacilitatorClient{ + supported: func(ctx context.Context) (x402.SupportedResponse, error) { + return x402.SupportedResponse{ + Kinds: []x402.SupportedKind{{X402Version: 2, Scheme: "exact", Network: "eip155:1"}}, + Extensions: []string{}, + Signers: make(map[string][]string), + }, nil + }, + } + + server := Newx402HTTPResourceServer( + routes, + x402.WithFacilitatorClient(mockClient), + x402.WithSchemeServer("eip155:1", mockServer), + ) + if err := server.Initialize(ctx); err != nil { + t.Fatalf("Failed to initialize server: %v", err) + } + + reqCtx := HTTPRequestContext{ + Adapter: &mockHTTPAdapter{method: "GET", path: "/api", url: "http://example.com/api"}, + Path: "/api", + Method: "GET", + } + + requirements, err := server.BuildPaymentRequirementsFromOptions(ctx, routes["GET /api"].Accepts, reqCtx) + if err != nil { + t.Fatalf("Failed to build payment requirements: %v", err) + } + if len(requirements) != 1 { + t.Fatalf("Expected 1 requirement, got %d", len(requirements)) + } + if requirements[0].Extra["assetTransferMethod"] != "permit2" { + t.Fatalf("Expected assetTransferMethod passthrough, got %v", requirements[0].Extra["assetTransferMethod"]) + } + if requirements[0].Extra["merchantNote"] != "route-level-extra" { + t.Fatalf("Expected merchant extra passthrough, got %v", requirements[0].Extra["merchantNote"]) + } +} + func TestProcessHTTPRequestWithBrowser(t *testing.T) { ctx := context.Background() diff --git a/go/mechanisms/evm/constants.go b/go/mechanisms/evm/constants.go index 768a1cfa53..005bbd9b09 100644 --- a/go/mechanisms/evm/constants.go +++ b/go/mechanisms/evm/constants.go @@ -15,6 +15,7 @@ const ( FunctionTransferWithAuthorization = "transferWithAuthorization" FunctionReceiveWithAuthorization = "receiveWithAuthorization" FunctionAuthorizationState = "authorizationState" + FunctionTryAggregate = "tryAggregate" // Permit2 function names FunctionSettle = "settle" @@ -41,6 +42,10 @@ const ( // Same address on all EVM chains via CREATE2 deployment. PERMIT2Address = "0x000000000022D473030F116dDEE9F6B43aC78BA3" + // MULTICALL3Address is the canonical Multicall3 deployment address. + // Same address on all EVM chains via CREATE2 deployment. + MULTICALL3Address = "0xcA11bde05977b3631167028862bE2a173976CA11" + // X402ExactPermit2ProxyAddress is the x402 exact payment proxy. // Vanity address: 0x4020...0001 for easy recognition. X402ExactPermit2ProxyAddress = "0x402085c248EeA27D92E8b30b2C58ed07f9E20001" @@ -176,6 +181,36 @@ var ( } ]`) + // Multicall3TryAggregateABI batches arbitrary eth_call requests. + Multicall3TryAggregateABI = []byte(`[ + { + "inputs": [ + {"name": "requireSuccess", "type": "bool"}, + { + "name": "calls", + "type": "tuple[]", + "components": [ + {"name": "target", "type": "address"}, + {"name": "callData", "type": "bytes"} + ] + } + ], + "name": "tryAggregate", + "outputs": [ + { + "name": "returnData", + "type": "tuple[]", + "components": [ + {"name": "success", "type": "bool"}, + {"name": "returnData", "type": "bytes"} + ] + } + ], + "stateMutability": "payable", + "type": "function" + } + ]`) + // ERC20AllowanceABI for checking Permit2 approval ERC20AllowanceABI = []byte(`[ { @@ -217,6 +252,28 @@ var ( } ]`) + // ERC20NameABI for checking EIP-712 domain name diagnostics. + ERC20NameABI = []byte(`[ + { + "inputs": [], + "name": "name", + "outputs": [{"name": "", "type": "string"}], + "stateMutability": "view", + "type": "function" + } + ]`) + + // ERC20VersionABI for checking EIP-712 domain version diagnostics. + ERC20VersionABI = []byte(`[ + { + "inputs": [], + "name": "version", + "outputs": [{"name": "", "type": "string"}], + "stateMutability": "view", + "type": "function" + } + ]`) + // X402ExactPermit2ProxySettleABI for calling settle on x402ExactPermit2Proxy X402ExactPermit2ProxySettleABI = []byte(`[ { diff --git a/go/mechanisms/evm/exact/facilitator/eip3009.go b/go/mechanisms/evm/exact/facilitator/eip3009.go new file mode 100644 index 0000000000..dd749e6f02 --- /dev/null +++ b/go/mechanisms/evm/exact/facilitator/eip3009.go @@ -0,0 +1,214 @@ +package facilitator + +import ( + "context" + "errors" + "fmt" + "math/big" + "strings" + "time" + + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/mechanisms/evm" + "github.com/coinbase/x402/go/types" +) + +// verifyEIP3009 verifies an EIP-3009 payment payload. +func (f *ExactEvmScheme) verifyEIP3009( + ctx context.Context, + payload types.PaymentPayload, + requirements types.PaymentRequirements, + simulate bool, +) (*x402.VerifyResponse, error) { + if payload.Accepted.Scheme != evm.SchemeExact { + return nil, x402.NewVerifyError(ErrInvalidScheme, "", fmt.Sprintf("invalid scheme: %s", payload.Accepted.Scheme)) + } + + if payload.Accepted.Network != requirements.Network { + return nil, x402.NewVerifyError(ErrNetworkMismatch, "", fmt.Sprintf("network mismatch: %s != %s", payload.Accepted.Network, requirements.Network)) + } + + evmPayload, err := evm.PayloadFromMap(payload.Payload) + if err != nil { + return nil, x402.NewVerifyError(ErrInvalidPayload, "", fmt.Sprintf("failed to parse EVM payload: %s", err.Error())) + } + + if evmPayload.Signature == "" { + return nil, x402.NewVerifyError(ErrMissingSignature, "", "missing signature") + } + + chainID, err := evm.GetEvmChainId(string(requirements.Network)) + if err != nil { + return nil, x402.NewVerifyError(ErrFailedToGetNetworkConfig, "", err.Error()) + } + + tokenAddress := evm.NormalizeAddress(requirements.Asset) + + if !strings.EqualFold(evmPayload.Authorization.To, requirements.PayTo) { + return nil, x402.NewVerifyError(ErrRecipientMismatch, "", fmt.Sprintf("recipient mismatch: %s != %s", evmPayload.Authorization.To, requirements.PayTo)) + } + + parsedAuthorization, err := ParseEIP3009Authorization(evmPayload.Authorization) + if err != nil { + return nil, x402.NewVerifyError(ErrInvalidPayload, evmPayload.Authorization.From, err.Error()) + } + + requiredValue, ok := new(big.Int).SetString(requirements.Amount, 10) + if !ok { + return nil, x402.NewVerifyError(ErrInvalidRequiredAmount, "", fmt.Sprintf("invalid required amount: %s", requirements.Amount)) + } + + if parsedAuthorization.Value.Cmp(requiredValue) != 0 { + return nil, x402.NewVerifyError(ErrAuthorizationValueMismatch, evmPayload.Authorization.From, fmt.Sprintf("authorization value mismatch: %s != %s", parsedAuthorization.Value.String(), requiredValue.String())) + } + + now := time.Now().Unix() + if parsedAuthorization.ValidBefore.Cmp(big.NewInt(now+6)) < 0 { + return nil, x402.NewVerifyError(ErrValidBeforeExpired, evmPayload.Authorization.From, fmt.Sprintf("valid before expired: %s", parsedAuthorization.ValidBefore.String())) + } + + if parsedAuthorization.ValidAfter.Cmp(big.NewInt(now)) > 0 { + return nil, x402.NewVerifyError(ErrValidAfterInFuture, evmPayload.Authorization.From, fmt.Sprintf("valid after in future: %s", parsedAuthorization.ValidAfter.String())) + } + + tokenName, _ := requirements.Extra["name"].(string) + tokenVersion, _ := requirements.Extra["version"].(string) + if tokenName == "" || tokenVersion == "" { + return nil, x402.NewVerifyError(ErrMissingEip712Domain, evmPayload.Authorization.From, "missing EIP-712 domain name/version in requirements.extra") + } + + signatureBytes, err := evm.HexToBytes(evmPayload.Signature) + if err != nil { + return nil, x402.NewVerifyError(ErrInvalidSignatureFormat, evmPayload.Authorization.From, err.Error()) + } + + classification, err := ClassifyEIP3009Signature( + ctx, + f.signer, + evmPayload.Authorization, + signatureBytes, + chainID, + tokenAddress, + tokenName, + tokenVersion, + ) + if err != nil { + return nil, x402.NewVerifyError(ErrFailedToVerifySignature, evmPayload.Authorization.From, err.Error()) + } + + if !classification.Valid && classification.IsUndeployed && !HasEIP6492Deployment(classification.SigData) { + return nil, x402.NewVerifyError(ErrUndeployedSmartWallet, evmPayload.Authorization.From, "") + } + + if !classification.Valid && !classification.IsSmartWallet { + return nil, x402.NewVerifyError(ErrInvalidSignature, evmPayload.Authorization.From, fmt.Sprintf("invalid signature: %s", evmPayload.Signature)) + } + + if simulate { + simulationSucceeded, err := SimulateEIP3009Transfer( + ctx, + f.signer, + tokenAddress, + parsedAuthorization, + classification.SigData, + ) + if err != nil { + return nil, x402.NewVerifyError(ErrInvalidPayload, evmPayload.Authorization.From, err.Error()) + } + if !simulationSucceeded { + reason := DiagnoseEIP3009SimulationFailure( + ctx, + f.signer, + tokenAddress, + evmPayload.Authorization, + requiredValue, + tokenName, + tokenVersion, + ) + return nil, x402.NewVerifyError(reason, evmPayload.Authorization.From, "") + } + } + + return &x402.VerifyResponse{ + IsValid: true, + Payer: evmPayload.Authorization.From, + }, nil +} + +// settleEIP3009 settles an EIP-3009 payment on-chain. +func (f *ExactEvmScheme) settleEIP3009( + ctx context.Context, + payload types.PaymentPayload, + requirements types.PaymentRequirements, +) (*x402.SettleResponse, error) { + network := x402.Network(payload.Accepted.Network) + + verifyResp, err := f.verifyEIP3009(ctx, payload, requirements, f.config.SimulateInSettle) + if err != nil { + ve := &x402.VerifyError{} + if errors.As(err, &ve) { + return nil, x402.NewSettleError(ve.InvalidReason, ve.Payer, network, "", ve.InvalidMessage) + } + return nil, x402.NewSettleError(ErrVerificationFailed, "", network, "", err.Error()) + } + + evmPayload, err := evm.PayloadFromMap(payload.Payload) + if err != nil { + return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", err.Error()) + } + + tokenAddress := evm.NormalizeAddress(requirements.Asset) + + signatureBytes, err := evm.HexToBytes(evmPayload.Signature) + if err != nil { + return nil, x402.NewSettleError(ErrInvalidSignatureFormat, verifyResp.Payer, network, "", err.Error()) + } + + sigData, err := evm.ParseERC6492Signature(signatureBytes) + if err != nil { + return nil, x402.NewSettleError(ErrFailedToParseSignature, verifyResp.Payer, network, "", err.Error()) + } + + if HasEIP6492Deployment(sigData) { + code, err := f.signer.GetCode(ctx, evmPayload.Authorization.From) + if err != nil { + return nil, x402.NewSettleError(ErrFailedToCheckDeployment, verifyResp.Payer, network, "", err.Error()) + } + + if len(code) == 0 { + if !f.config.DeployERC4337WithEIP6492 { + return nil, x402.NewSettleError(ErrUndeployedSmartWallet, verifyResp.Payer, network, "", "") + } + + if err := DeploySmartWallet(ctx, f.signer, sigData); err != nil { + return nil, x402.NewSettleError(ErrSmartWalletDeploymentFailed, verifyResp.Payer, network, "", err.Error()) + } + } + } + + parsedAuthorization, err := ParseEIP3009Authorization(evmPayload.Authorization) + if err != nil { + return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", err.Error()) + } + + txHash, err := ExecuteTransferWithAuthorization(ctx, f.signer, tokenAddress, parsedAuthorization, sigData) + if err != nil { + return nil, x402.NewSettleError(ErrFailedToExecuteTransfer, verifyResp.Payer, network, "", err.Error()) + } + + receipt, err := f.signer.WaitForTransactionReceipt(ctx, txHash) + if err != nil { + return nil, x402.NewSettleError(ErrFailedToGetReceipt, verifyResp.Payer, network, txHash, err.Error()) + } + + if receipt.Status != evm.TxStatusSuccess { + return nil, x402.NewSettleError(ErrTransactionFailed, verifyResp.Payer, network, txHash, "") + } + + return &x402.SettleResponse{ + Success: true, + Transaction: txHash, + Network: network, + Payer: verifyResp.Payer, + }, nil +} diff --git a/go/mechanisms/evm/exact/facilitator/eip3009_helpers.go b/go/mechanisms/evm/exact/facilitator/eip3009_helpers.go new file mode 100644 index 0000000000..5f072035ad --- /dev/null +++ b/go/mechanisms/evm/exact/facilitator/eip3009_helpers.go @@ -0,0 +1,448 @@ +package facilitator + +import ( + "context" + "fmt" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/coinbase/x402/go/mechanisms/evm" +) + +// ParsedEIP3009Authorization contains the parsed transfer arguments used by verify and settle. +type ParsedEIP3009Authorization struct { + From common.Address + To common.Address + Value *big.Int + ValidAfter *big.Int + ValidBefore *big.Int + Nonce [32]byte +} + +// EIP3009SignatureClassification captures how the signature should be treated. +type EIP3009SignatureClassification struct { + Valid bool + IsSmartWallet bool + IsUndeployed bool + SigData *evm.ERC6492SignatureData +} + +// ParseEIP3009Authorization parses authorization fields into contract-call arguments. +func ParseEIP3009Authorization( + authorization evm.ExactEIP3009Authorization, +) (*ParsedEIP3009Authorization, error) { + value, ok := new(big.Int).SetString(authorization.Value, 10) + if !ok { + return nil, fmt.Errorf("invalid authorization value: %s", authorization.Value) + } + + validAfter, ok := new(big.Int).SetString(authorization.ValidAfter, 10) + if !ok { + return nil, fmt.Errorf("invalid validAfter: %s", authorization.ValidAfter) + } + + validBefore, ok := new(big.Int).SetString(authorization.ValidBefore, 10) + if !ok { + return nil, fmt.Errorf("invalid validBefore: %s", authorization.ValidBefore) + } + + nonceBytes, err := evm.HexToBytes(authorization.Nonce) + if err != nil { + return nil, fmt.Errorf("invalid nonce: %w", err) + } + if len(nonceBytes) != 32 { + return nil, fmt.Errorf("invalid nonce length: got %d bytes, want 32", len(nonceBytes)) + } + + var nonce [32]byte + copy(nonce[:], nonceBytes) + + return &ParsedEIP3009Authorization{ + From: common.HexToAddress(authorization.From), + To: common.HexToAddress(authorization.To), + Value: value, + ValidAfter: validAfter, + ValidBefore: validBefore, + Nonce: nonce, + }, nil +} + +// ClassifyEIP3009Signature checks the signature directly when possible, while preserving +// smart-wallet signatures for simulation-first verification. +func ClassifyEIP3009Signature( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + authorization evm.ExactEIP3009Authorization, + signature []byte, + chainID *big.Int, + tokenAddress string, + tokenName string, + tokenVersion string, +) (*EIP3009SignatureClassification, error) { + hash, err := evm.HashEIP3009Authorization( + authorization, + chainID, + tokenAddress, + tokenName, + tokenVersion, + ) + if err != nil { + return nil, err + } + + var hash32 [32]byte + copy(hash32[:], hash) + + valid, sigData, err := evm.VerifyUniversalSignature( + ctx, + signer, + authorization.From, + hash32, + signature, + true, + ) + if err != nil { + return nil, err + } + if sigData == nil { + sigData = &evm.ERC6492SignatureData{InnerSignature: signature} + } + + classification := &EIP3009SignatureClassification{ + Valid: valid, + SigData: sigData, + } + + if HasEIP6492Deployment(sigData) || len(sigData.InnerSignature) != 65 { + classification.IsSmartWallet = true + } + if valid { + return classification, nil + } + + code, err := signer.GetCode(ctx, authorization.From) + if err != nil { + return nil, err + } + if len(code) > 0 { + classification.IsSmartWallet = true + return classification, nil + } + + if HasEIP6492Deployment(sigData) { + classification.IsSmartWallet = true + classification.IsUndeployed = true + return classification, nil + } + + if len(sigData.InnerSignature) != 65 { + classification.IsSmartWallet = true + classification.IsUndeployed = true + } + + return classification, nil +} + +// SimulateEIP3009Transfer runs the transfer via eth_call. +func SimulateEIP3009Transfer( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + tokenAddress string, + parsed *ParsedEIP3009Authorization, + sigData *evm.ERC6492SignatureData, +) (bool, error) { + if sigData == nil { + return false, fmt.Errorf("missing signature data") + } + + if HasEIP6492Deployment(sigData) { + transferCalldata, err := buildTransferWithAuthorizationBytesCalldata(parsed, sigData.InnerSignature) + if err != nil { + return false, err + } + + results, err := evm.Multicall(ctx, signer, []evm.MulticallCall{ + { + Address: common.BytesToAddress(sigData.Factory[:]).Hex(), + CallData: sigData.FactoryCalldata, + }, + { + Address: tokenAddress, + CallData: transferCalldata, + }, + }) + if err != nil { + return false, err + } + if len(results) < 2 { + return false, nil + } + + return results[1].Success(), nil + } + + if len(sigData.InnerSignature) == 65 { + v, r, s := splitSignatureParts(sigData.InnerSignature) + _, err := signer.ReadContract( + ctx, + tokenAddress, + evm.TransferWithAuthorizationVRSABI, + evm.FunctionTransferWithAuthorization, + parsed.From, + parsed.To, + parsed.Value, + parsed.ValidAfter, + parsed.ValidBefore, + parsed.Nonce, + v, + r, + s, + ) + if err != nil { + return false, err + } + + return true, nil + } + + _, err := signer.ReadContract( + ctx, + tokenAddress, + evm.TransferWithAuthorizationBytesABI, + evm.FunctionTransferWithAuthorization, + parsed.From, + parsed.To, + parsed.Value, + parsed.ValidAfter, + parsed.ValidBefore, + parsed.Nonce, + sigData.InnerSignature, + ) + if err != nil { + return false, err + } + + return true, nil +} + +// DiagnoseEIP3009SimulationFailure resolves a failed simulation into the most specific error. +func DiagnoseEIP3009SimulationFailure( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + tokenAddress string, + authorization evm.ExactEIP3009Authorization, + requiredAmount *big.Int, + tokenName string, + tokenVersion string, +) string { + results, err := evm.Multicall(ctx, signer, []evm.MulticallCall{ + { + Address: tokenAddress, + ABI: evm.ERC20BalanceOfABI, + FunctionName: "balanceOf", + Args: []interface{}{common.HexToAddress(authorization.From)}, + }, + { + Address: tokenAddress, + ABI: evm.ERC20NameABI, + FunctionName: "name", + }, + { + Address: tokenAddress, + ABI: evm.ERC20VersionABI, + FunctionName: "version", + }, + { + Address: tokenAddress, + ABI: evm.AuthorizationStateABI, + FunctionName: evm.FunctionAuthorizationState, + Args: []interface{}{common.HexToAddress(authorization.From), mustNonce(authorization.Nonce)}, + }, + }) + if err != nil || len(results) < 4 { + return ErrEip3009SimulationFailed + } + + authStateResult := results[3] + if !authStateResult.Success() { + return ErrEip3009NotSupported + } + + if nonceUsed, ok := authStateResult.Result.(bool); ok && nonceUsed { + return ErrNonceAlreadyUsed + } + + nameResult := results[1] + if tokenName != "" && nameResult.Success() { + if actualName, ok := nameResult.Result.(string); ok && actualName != tokenName { + return ErrEip3009TokenNameMismatch + } + } + + versionResult := results[2] + if tokenVersion != "" && versionResult.Success() { + if actualVersion, ok := versionResult.Result.(string); ok && actualVersion != tokenVersion { + return ErrEip3009TokenVersionMismatch + } + } + + balanceResult := results[0] + if balanceResult.Success() { + if balance := asBigInt(balanceResult.Result); balance != nil && balance.Cmp(requiredAmount) < 0 { + return ErrInsufficientBalance + } + } + + return ErrEip3009SimulationFailed +} + +// ExecuteTransferWithAuthorization executes the actual transfer onchain. +func ExecuteTransferWithAuthorization( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + tokenAddress string, + parsed *ParsedEIP3009Authorization, + sigData *evm.ERC6492SignatureData, +) (string, error) { + if sigData == nil { + return "", fmt.Errorf("missing signature data") + } + + if len(sigData.InnerSignature) == 65 { + v, r, s := splitSignatureParts(sigData.InnerSignature) + return signer.WriteContract( + ctx, + tokenAddress, + evm.TransferWithAuthorizationVRSABI, + evm.FunctionTransferWithAuthorization, + parsed.From, + parsed.To, + parsed.Value, + parsed.ValidAfter, + parsed.ValidBefore, + parsed.Nonce, + v, + r, + s, + ) + } + + return signer.WriteContract( + ctx, + tokenAddress, + evm.TransferWithAuthorizationBytesABI, + evm.FunctionTransferWithAuthorization, + parsed.From, + parsed.To, + parsed.Value, + parsed.ValidAfter, + parsed.ValidBefore, + parsed.Nonce, + sigData.InnerSignature, + ) +} + +// DeploySmartWallet sends the ERC-6492 factory deployment transaction when enabled. +func DeploySmartWallet( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + sigData *evm.ERC6492SignatureData, +) error { + if !HasEIP6492Deployment(sigData) { + return nil + } + + txHash, err := signer.SendTransaction( + ctx, + common.BytesToAddress(sigData.Factory[:]).Hex(), + sigData.FactoryCalldata, + ) + if err != nil { + return fmt.Errorf("factory deployment transaction failed: %w", err) + } + + receipt, err := signer.WaitForTransactionReceipt(ctx, txHash) + if err != nil { + return fmt.Errorf("failed to wait for deployment: %w", err) + } + if receipt.Status != evm.TxStatusSuccess { + return fmt.Errorf("deployment transaction reverted") + } + + return nil +} + +func buildTransferWithAuthorizationBytesCalldata( + parsed *ParsedEIP3009Authorization, + signature []byte, +) ([]byte, error) { + return packCallData( + evm.TransferWithAuthorizationBytesABI, + evm.FunctionTransferWithAuthorization, + parsed.From, + parsed.To, + parsed.Value, + parsed.ValidAfter, + parsed.ValidBefore, + parsed.Nonce, + signature, + ) +} + +func packCallData(abiBytes []byte, functionName string, args ...interface{}) ([]byte, error) { + contractABI, err := abi.JSON(strings.NewReader(string(abiBytes))) + if err != nil { + return nil, err + } + + data, err := contractABI.Pack(functionName, args...) + if err != nil { + return nil, err + } + + return data, nil +} + +func splitSignatureParts(signature []byte) (uint8, [32]byte, [32]byte) { + var r [32]byte + var s [32]byte + copy(r[:], signature[0:32]) + copy(s[:], signature[32:64]) + + v := signature[64] + if v == 0 || v == 1 { + v += 27 + } + + return v, r, s +} + +func HasEIP6492Deployment(sigData *evm.ERC6492SignatureData) bool { + if sigData == nil { + return false + } + + var zeroFactory [20]byte + return sigData.Factory != zeroFactory && len(sigData.FactoryCalldata) > 0 +} + +func mustNonce(nonce string) [32]byte { + nonceBytes, _ := evm.HexToBytes(nonce) + var nonceArray [32]byte + copy(nonceArray[:], nonceBytes) + return nonceArray +} + +func asBigInt(value interface{}) *big.Int { + switch v := value.(type) { + case *big.Int: + return v + case big.Int: + return &v + default: + return nil + } +} diff --git a/go/mechanisms/evm/exact/facilitator/errors.go b/go/mechanisms/evm/exact/facilitator/errors.go index 0c4d276633..a22119ac5a 100644 --- a/go/mechanisms/evm/exact/facilitator/errors.go +++ b/go/mechanisms/evm/exact/facilitator/errors.go @@ -3,25 +3,29 @@ package facilitator // Facilitator error constants for the exact EVM scheme const ( // EIP-3009 Verify errors - ErrInvalidScheme = "invalid_exact_evm_scheme" - ErrNetworkMismatch = "invalid_exact_evm_network_mismatch" - ErrInvalidPayload = "invalid_exact_evm_payload" - ErrMissingSignature = "invalid_exact_evm_payload_missing_signature" - ErrFailedToGetNetworkConfig = "invalid_exact_evm_failed_to_get_network_config" - ErrMissingEip712Domain = "invalid_exact_evm_missing_eip712_domain" - ErrRecipientMismatch = "invalid_exact_evm_recipient_mismatch" - ErrInvalidAuthorizationValue = "invalid_exact_evm_authorization_value" - ErrInvalidRequiredAmount = "invalid_exact_evm_required_amount" - ErrInsufficientAmount = "invalid_exact_evm_insufficient_amount" - ErrFailedToCheckNonce = "invalid_exact_evm_failed_to_check_nonce" - ErrNonceAlreadyUsed = "invalid_exact_evm_nonce_already_used" - ErrFailedToGetBalance = "invalid_exact_evm_failed_to_get_balance" - ErrInsufficientBalance = "invalid_exact_evm_insufficient_balance" - ErrInvalidSignatureFormat = "invalid_exact_evm_signature_format" - ErrFailedToVerifySignature = "invalid_exact_evm_failed_to_verify_signature" - ErrInvalidSignature = "invalid_exact_evm_signature" - ErrValidBeforeExpired = "invalid_exact_evm_payload_authorization_valid_before" - ErrValidAfterInFuture = "invalid_exact_evm_payload_authorization_valid_after" + ErrInvalidScheme = "invalid_exact_evm_scheme" + ErrNetworkMismatch = "invalid_exact_evm_network_mismatch" + ErrInvalidPayload = "invalid_exact_evm_payload" + ErrMissingSignature = "invalid_exact_evm_payload_missing_signature" + ErrFailedToGetNetworkConfig = "invalid_exact_evm_failed_to_get_network_config" + ErrMissingEip712Domain = "invalid_exact_evm_missing_eip712_domain" + ErrRecipientMismatch = "invalid_exact_evm_recipient_mismatch" + ErrInvalidAuthorizationValue = "invalid_exact_evm_authorization_value" + ErrInvalidRequiredAmount = "invalid_exact_evm_required_amount" + ErrAuthorizationValueMismatch = "invalid_exact_evm_payload_authorization_value_mismatch" + ErrFailedToCheckNonce = "invalid_exact_evm_failed_to_check_nonce" + ErrNonceAlreadyUsed = "invalid_exact_evm_nonce_already_used" + ErrFailedToGetBalance = "invalid_exact_evm_failed_to_get_balance" + ErrInsufficientBalance = "invalid_exact_evm_insufficient_balance" + ErrInvalidSignatureFormat = "invalid_exact_evm_signature_format" + ErrFailedToVerifySignature = "invalid_exact_evm_failed_to_verify_signature" + ErrInvalidSignature = "invalid_exact_evm_signature" + ErrValidBeforeExpired = "invalid_exact_evm_payload_authorization_valid_before" + ErrValidAfterInFuture = "invalid_exact_evm_payload_authorization_valid_after" + ErrEip3009TokenNameMismatch = "invalid_exact_evm_token_name_mismatch" + ErrEip3009TokenVersionMismatch = "invalid_exact_evm_token_version_mismatch" + ErrEip3009NotSupported = "invalid_exact_evm_eip3009_not_supported" + ErrEip3009SimulationFailed = "invalid_exact_evm_transaction_simulation_failed" // EIP-3009 Settle errors ErrVerificationFailed = "invalid_exact_evm_verification_failed" diff --git a/go/mechanisms/evm/exact/facilitator/scheme.go b/go/mechanisms/evm/exact/facilitator/scheme.go index ca3e240ade..ce6750b364 100644 --- a/go/mechanisms/evm/exact/facilitator/scheme.go +++ b/go/mechanisms/evm/exact/facilitator/scheme.go @@ -2,13 +2,7 @@ package facilitator import ( "context" - "errors" "fmt" - "math/big" - "strings" - "time" - - "github.com/ethereum/go-ethereum/common" x402 "github.com/coinbase/x402/go" "github.com/coinbase/x402/go/mechanisms/evm" @@ -20,6 +14,8 @@ type ExactEvmSchemeConfig struct { // DeployERC4337WithEIP6492 enables automatic deployment of ERC-4337 smart wallets // via EIP-6492 when encountering undeployed contract signatures during settlement DeployERC4337WithEIP6492 bool + // SimulateInSettle reruns transfer simulation during settle. Verify always simulates. + SimulateInSettle bool } // ExactEvmScheme implements the SchemeNetworkFacilitator interface for EVM exact payments (V2) @@ -88,138 +84,7 @@ func (f *ExactEvmScheme) Verify( return VerifyPermit2(ctx, f.signer, payload, requirements, permit2Payload, fctx) } - return f.verifyEIP3009(ctx, payload, requirements) -} - -// verifyEIP3009 verifies an EIP-3009 payment payload. -func (f *ExactEvmScheme) verifyEIP3009( - ctx context.Context, - payload types.PaymentPayload, - requirements types.PaymentRequirements, -) (*x402.VerifyResponse, error) { - // Validate scheme (v2 has scheme in Accepted field) - if payload.Accepted.Scheme != evm.SchemeExact { - return nil, x402.NewVerifyError(ErrInvalidScheme, "", fmt.Sprintf("invalid scheme: %s", payload.Accepted.Scheme)) - } - - // Validate network (v2 has network in Accepted field) - if payload.Accepted.Network != requirements.Network { - return nil, x402.NewVerifyError(ErrNetworkMismatch, "", fmt.Sprintf("network mismatch: %s != %s", payload.Accepted.Network, requirements.Network)) - } - - // Parse EVM payload - evmPayload, err := evm.PayloadFromMap(payload.Payload) - if err != nil { - return nil, x402.NewVerifyError(ErrInvalidPayload, "", fmt.Sprintf("failed to parse EVM payload: %s", err.Error())) - } - - // Validate signature exists - if evmPayload.Signature == "" { - return nil, x402.NewVerifyError(ErrMissingSignature, "", "missing signature") - } - - // Parse chain ID from network identifier - chainID, err := evm.GetEvmChainId(string(requirements.Network)) - if err != nil { - return nil, x402.NewVerifyError(ErrFailedToGetNetworkConfig, "", err.Error()) - } - - tokenAddress := evm.NormalizeAddress(requirements.Asset) - - // Validate authorization matches requirements - if !strings.EqualFold(evmPayload.Authorization.To, requirements.PayTo) { - return nil, x402.NewVerifyError(ErrRecipientMismatch, "", fmt.Sprintf("recipient mismatch: %s != %s", evmPayload.Authorization.To, requirements.PayTo)) - } - - // Parse and validate amount - authValue, ok := new(big.Int).SetString(evmPayload.Authorization.Value, 10) - if !ok { - return nil, x402.NewVerifyError(ErrInvalidAuthorizationValue, "", fmt.Sprintf("invalid authorization value: %s", evmPayload.Authorization.Value)) - } - - // Requirements.Amount is already in the smallest unit - requiredValue, ok := new(big.Int).SetString(requirements.Amount, 10) - if !ok { - return nil, x402.NewVerifyError(ErrInvalidRequiredAmount, "", fmt.Sprintf("invalid required amount: %s", requirements.Amount)) - } - - if authValue.Cmp(requiredValue) < 0 { - return nil, x402.NewVerifyError(ErrInsufficientAmount, evmPayload.Authorization.From, fmt.Sprintf("insufficient amount: %s < %s", authValue.String(), requiredValue.String())) - } - - // Check validBefore is in the future (with 6 second buffer for block time) - now := time.Now().Unix() - validBefore, ok := new(big.Int).SetString(evmPayload.Authorization.ValidBefore, 10) - if !ok { - return nil, x402.NewVerifyError(ErrInvalidPayload, evmPayload.Authorization.From, "invalid validBefore format") - } - if validBefore.Cmp(big.NewInt(now+6)) < 0 { - return nil, x402.NewVerifyError(ErrValidBeforeExpired, evmPayload.Authorization.From, - fmt.Sprintf("valid before expired: %s", validBefore.String())) - } - - // Check validAfter is not in the future - validAfter, ok := new(big.Int).SetString(evmPayload.Authorization.ValidAfter, 10) - if !ok { - return nil, x402.NewVerifyError(ErrInvalidPayload, evmPayload.Authorization.From, "invalid validAfter format") - } - if validAfter.Cmp(big.NewInt(now)) > 0 { - return nil, x402.NewVerifyError(ErrValidAfterInFuture, evmPayload.Authorization.From, - fmt.Sprintf("valid after in future: %s", validAfter.String())) - } - - // Check if nonce has been used - nonceUsed, err := f.checkNonceUsed(ctx, evmPayload.Authorization.From, evmPayload.Authorization.Nonce, tokenAddress) - if err != nil { - return nil, x402.NewVerifyError(ErrFailedToCheckNonce, evmPayload.Authorization.From, err.Error()) - } - if nonceUsed { - return nil, x402.NewVerifyError(ErrNonceAlreadyUsed, evmPayload.Authorization.From, fmt.Sprintf("nonce already used: %s", evmPayload.Authorization.Nonce)) - } - - // Check balance - balance, err := f.signer.GetBalance(ctx, evmPayload.Authorization.From, tokenAddress) - if err != nil { - return nil, x402.NewVerifyError(ErrFailedToGetBalance, evmPayload.Authorization.From, err.Error()) - } - if balance.Cmp(authValue) < 0 { - return nil, x402.NewVerifyError(ErrInsufficientBalance, evmPayload.Authorization.From, fmt.Sprintf("insufficient balance: %s < %s", balance.String(), authValue.String())) - } - - // Extract EIP-712 domain parameters from requirements - tokenName, _ := requirements.Extra["name"].(string) - tokenVersion, _ := requirements.Extra["version"].(string) - if tokenName == "" || tokenVersion == "" { - return nil, x402.NewVerifyError(ErrMissingEip712Domain, evmPayload.Authorization.From, "missing EIP-712 domain name/version in requirements.extra") - } - - // Verify signature - signatureBytes, err := evm.HexToBytes(evmPayload.Signature) - if err != nil { - return nil, x402.NewVerifyError(ErrInvalidSignatureFormat, evmPayload.Authorization.From, err.Error()) - } - - valid, err := f.verifySignature( - ctx, - evmPayload.Authorization, - signatureBytes, - chainID, - tokenAddress, - tokenName, - tokenVersion, - ) - if err != nil { - return nil, x402.NewVerifyError(ErrFailedToVerifySignature, evmPayload.Authorization.From, err.Error()) - } - - if !valid { - return nil, x402.NewVerifyError(ErrInvalidSignature, evmPayload.Authorization.From, fmt.Sprintf("invalid signature: %s", evmPayload.Signature)) - } - - return &x402.VerifyResponse{ - IsValid: true, - Payer: evmPayload.Authorization.From, - }, nil + return f.verifyEIP3009(ctx, payload, requirements, true) } // Settle settles a V2 payment on-chain. @@ -243,278 +108,3 @@ func (f *ExactEvmScheme) Settle( return f.settleEIP3009(ctx, payload, requirements) } - -// settleEIP3009 settles an EIP-3009 payment on-chain. -func (f *ExactEvmScheme) settleEIP3009( - ctx context.Context, - payload types.PaymentPayload, - requirements types.PaymentRequirements, -) (*x402.SettleResponse, error) { - network := x402.Network(payload.Accepted.Network) - - // First verify the payment - verifyResp, err := f.verifyEIP3009(ctx, payload, requirements) - if err != nil { - // Convert VerifyError to SettleError - ve := &x402.VerifyError{} - if errors.As(err, &ve) { - return nil, x402.NewSettleError(ve.InvalidReason, ve.Payer, network, "", ve.InvalidMessage) - } - return nil, x402.NewSettleError(ErrVerificationFailed, "", network, "", err.Error()) - } - - // Parse EVM payload - evmPayload, err := evm.PayloadFromMap(payload.Payload) - if err != nil { - return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", err.Error()) - } - - tokenAddress := evm.NormalizeAddress(requirements.Asset) - - // Parse signature - signatureBytes, err := evm.HexToBytes(evmPayload.Signature) - if err != nil { - return nil, x402.NewSettleError(ErrInvalidSignatureFormat, verifyResp.Payer, network, "", err.Error()) - } - - // Parse ERC-6492 signature to extract inner signature if needed - sigData, err := evm.ParseERC6492Signature(signatureBytes) - if err != nil { - return nil, x402.NewSettleError(ErrFailedToParseSignature, verifyResp.Payer, network, "", err.Error()) - } - - // Check if wallet needs deployment (undeployed smart wallet with ERC-6492) - zeroFactory := [20]byte{} - if sigData.Factory != zeroFactory && len(sigData.FactoryCalldata) > 0 { - code, err := f.signer.GetCode(ctx, evmPayload.Authorization.From) - if err != nil { - return nil, x402.NewSettleError(ErrFailedToCheckDeployment, verifyResp.Payer, network, "", err.Error()) - } - - if len(code) == 0 { - // Wallet not deployed - if f.config.DeployERC4337WithEIP6492 { - // Deploy wallet - err := f.deploySmartWallet(ctx, sigData) - if err != nil { - return nil, x402.NewSettleError(ErrSmartWalletDeploymentFailed, verifyResp.Payer, network, "", err.Error()) - } - } else { - // Deployment not enabled - fail settlement - return nil, x402.NewSettleError(ErrUndeployedSmartWallet, verifyResp.Payer, network, "", "") - } - } - } - - // Use inner signature for settlement - signatureBytes = sigData.InnerSignature - - // Parse values (validated during verify, but check again for safety) - value, ok := new(big.Int).SetString(evmPayload.Authorization.Value, 10) - if !ok { - return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", "invalid authorization value") - } - validAfter, ok := new(big.Int).SetString(evmPayload.Authorization.ValidAfter, 10) - if !ok { - return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", "invalid validAfter") - } - validBefore, ok := new(big.Int).SetString(evmPayload.Authorization.ValidBefore, 10) - if !ok { - return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", "invalid validBefore") - } - nonceBytes, err := evm.HexToBytes(evmPayload.Authorization.Nonce) - if err != nil { - return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", "invalid nonce format") - } - - // Determine signature type: ECDSA (65 bytes) or smart wallet (longer) - isECDSA := len(signatureBytes) == 65 - - var txHash string - if isECDSA { - // For EOA wallets, use v,r,s overload - r := signatureBytes[0:32] - s := signatureBytes[32:64] - v := signatureBytes[64] - if v == 0 || v == 1 { - v += 27 - } - - txHash, err = f.signer.WriteContract( - ctx, - tokenAddress, - evm.TransferWithAuthorizationVRSABI, - evm.FunctionTransferWithAuthorization, - common.HexToAddress(evmPayload.Authorization.From), - common.HexToAddress(evmPayload.Authorization.To), - value, - validAfter, - validBefore, - [32]byte(nonceBytes), - v, - [32]byte(r), - [32]byte(s), - ) - } else { - // For smart wallets, use bytes signature overload - txHash, err = f.signer.WriteContract( - ctx, - tokenAddress, - evm.TransferWithAuthorizationBytesABI, - evm.FunctionTransferWithAuthorization, - common.HexToAddress(evmPayload.Authorization.From), - common.HexToAddress(evmPayload.Authorization.To), - value, - validAfter, - validBefore, - [32]byte(nonceBytes), - signatureBytes, - ) - } - - if err != nil { - return nil, x402.NewSettleError(ErrFailedToExecuteTransfer, verifyResp.Payer, network, "", err.Error()) - } - - // Wait for transaction confirmation - receipt, err := f.signer.WaitForTransactionReceipt(ctx, txHash) - if err != nil { - return nil, x402.NewSettleError(ErrFailedToGetReceipt, verifyResp.Payer, network, txHash, err.Error()) - } - - if receipt.Status != evm.TxStatusSuccess { - return nil, x402.NewSettleError(ErrTransactionFailed, verifyResp.Payer, network, txHash, "") - } - - return &x402.SettleResponse{ - Success: true, - Transaction: txHash, - Network: network, - Payer: verifyResp.Payer, - }, nil -} - -// deploySmartWallet deploys an ERC-4337 smart wallet using the ERC-6492 factory -// -// This function sends the pre-encoded factory calldata directly as a transaction. -// The factoryCalldata already contains the complete encoded function call with selector. -// -// Args: -// -// ctx: Context for cancellation -// sigData: Parsed ERC-6492 signature containing factory address and calldata -// -// Returns: -// -// error if deployment fails -func (f *ExactEvmScheme) deploySmartWallet( - ctx context.Context, - sigData *evm.ERC6492SignatureData, -) error { - factoryAddr := common.BytesToAddress(sigData.Factory[:]) - - // Send the factory calldata directly - it already contains the encoded function call - txHash, err := f.signer.SendTransaction( - ctx, - factoryAddr.Hex(), - sigData.FactoryCalldata, - ) - if err != nil { - return fmt.Errorf("factory deployment transaction failed: %w", err) - } - - // Wait for deployment transaction - receipt, err := f.signer.WaitForTransactionReceipt(ctx, txHash) - if err != nil { - return fmt.Errorf("failed to wait for deployment: %w", err) - } - - if receipt.Status != evm.TxStatusSuccess { - return fmt.Errorf("deployment transaction reverted") - } - - return nil -} - -// checkNonceUsed checks if a nonce has already been used -func (f *ExactEvmScheme) checkNonceUsed(ctx context.Context, from string, nonce string, tokenAddress string) (bool, error) { - nonceBytes, err := evm.HexToBytes(nonce) - if err != nil { - return false, err - } - - result, err := f.signer.ReadContract( - ctx, - tokenAddress, - evm.AuthorizationStateABI, - evm.FunctionAuthorizationState, - common.HexToAddress(from), - [32]byte(nonceBytes), - ) - if err != nil { - return false, err - } - - used, ok := result.(bool) - if !ok { - return false, fmt.Errorf("unexpected result type from authorizationState") - } - - return used, nil -} - -// verifySignature verifies the EIP-712 signature -func (f *ExactEvmScheme) verifySignature( - ctx context.Context, - authorization evm.ExactEIP3009Authorization, - signature []byte, - chainID *big.Int, - verifyingContract string, - tokenName string, - tokenVersion string, -) (bool, error) { - // Hash the EIP-712 typed data - hash, err := evm.HashEIP3009Authorization( - authorization, - chainID, - verifyingContract, - tokenName, - tokenVersion, - ) - if err != nil { - return false, err - } - - // Convert hash to [32]byte - var hash32 [32]byte - copy(hash32[:], hash) - - // Use universal verification (supports EOA, EIP-1271, and ERC-6492) - valid, sigData, err := evm.VerifyUniversalSignature( - ctx, - f.signer, - authorization.From, - hash32, - signature, - true, // allowUndeployed in verify() - ) - - if err != nil { - return false, err - } - - // If undeployed wallet with deployment info, it will be deployed in settle() - if sigData != nil { - zeroFactory := [20]byte{} - if sigData.Factory != zeroFactory { - _, err := f.signer.GetCode(ctx, authorization.From) - if err != nil { - return false, err - } - // Wallet may not be deployed - this is OK in verify() if has deployment info - // Actual deployment happens in settle() if configured - } - } - - return valid, nil -} diff --git a/go/mechanisms/evm/exact/v1/facilitator/errors.go b/go/mechanisms/evm/exact/v1/facilitator/errors.go index 628666a585..2c2297b4a7 100644 --- a/go/mechanisms/evm/exact/v1/facilitator/errors.go +++ b/go/mechanisms/evm/exact/v1/facilitator/errors.go @@ -13,7 +13,7 @@ const ( ErrRecipientMismatch = "invalid_exact_evm_payload_recipient_mismatch" ErrInvalidAuthorizationValue = "invalid_exact_evm_payload_authorization_value" ErrInvalidRequiredAmount = "invalid_exact_evm_required_amount" - ErrAuthorizationValueInsufficient = "invalid_exact_evm_payload_authorization_value_insufficient" + ErrAuthorizationValueMismatch = "invalid_exact_evm_payload_authorization_value_mismatch" ErrAuthorizationValidBeforeExpired = "invalid_exact_evm_payload_authorization_valid_before" ErrAuthorizationValidAfterInFuture = "invalid_exact_evm_payload_authorization_valid_after" ErrInsufficientFunds = "invalid_exact_evm_insufficient_funds" diff --git a/go/mechanisms/evm/exact/v1/facilitator/scheme.go b/go/mechanisms/evm/exact/v1/facilitator/scheme.go index 825f4a273f..ebd1c7d2d1 100644 --- a/go/mechanisms/evm/exact/v1/facilitator/scheme.go +++ b/go/mechanisms/evm/exact/v1/facilitator/scheme.go @@ -13,6 +13,7 @@ import ( x402 "github.com/coinbase/x402/go" "github.com/coinbase/x402/go/mechanisms/evm" + exactfacilitator "github.com/coinbase/x402/go/mechanisms/evm/exact/facilitator" evmv1 "github.com/coinbase/x402/go/mechanisms/evm/v1" "github.com/coinbase/x402/go/types" ) @@ -22,6 +23,8 @@ type ExactEvmSchemeV1Config struct { // DeployERC4337WithEIP6492 enables automatic deployment of ERC-4337 smart wallets // via EIP-6492 when encountering undeployed contract signatures during settlement DeployERC4337WithEIP6492 bool + // SimulateInSettle reruns transfer simulation during settle. Verify always simulates. + SimulateInSettle bool } // ExactEvmSchemeV1 implements the SchemeNetworkFacilitatorV1 interface for EVM exact payments (V1) @@ -74,10 +77,20 @@ func (f *ExactEvmSchemeV1) GetSigners(_ x402.Network) []string { // Verify verifies a V1 payment payload against requirements func (f *ExactEvmSchemeV1) Verify( + ctx context.Context, + payload types.PaymentPayloadV1, + requirements types.PaymentRequirementsV1, + fctx *x402.FacilitatorContext, +) (*x402.VerifyResponse, error) { + return f.verify(ctx, payload, requirements, fctx, true) +} + +func (f *ExactEvmSchemeV1) verify( ctx context.Context, payload types.PaymentPayloadV1, requirements types.PaymentRequirementsV1, _ *x402.FacilitatorContext, + simulate bool, ) (*x402.VerifyResponse, error) { // Validate scheme (v1 has scheme at top level) if payload.Scheme != evm.SchemeExact || requirements.Scheme != evm.SchemeExact { @@ -133,10 +146,9 @@ func (f *ExactEvmSchemeV1) Verify( return nil, x402.NewVerifyError(ErrRecipientMismatch, evmPayload.Authorization.From, fmt.Sprintf("recipient mismatch: %s != %s", evmPayload.Authorization.To, requirements.PayTo)) } - // Parse and validate amount - authValue, ok := new(big.Int).SetString(evmPayload.Authorization.Value, 10) - if !ok || evmPayload.Authorization.Value == "" { - return nil, x402.NewVerifyError(ErrInvalidAuthorizationValue, evmPayload.Authorization.From, fmt.Sprintf("invalid value: %s", evmPayload.Authorization.Value)) + parsedAuthorization, err := exactfacilitator.ParseEIP3009Authorization(evmPayload.Authorization) + if err != nil { + return nil, x402.NewVerifyError(ErrInvalidPayload, evmPayload.Authorization.From, err.Error()) } // V1: Use MaxAmountRequired field @@ -147,27 +159,19 @@ func (f *ExactEvmSchemeV1) Verify( return nil, x402.NewVerifyError(ErrInvalidRequiredAmount, evmPayload.Authorization.From, fmt.Sprintf("invalid required amount: %s", amountStr)) } - if authValue.Cmp(requiredValue) < 0 { - return nil, x402.NewVerifyError(ErrAuthorizationValueInsufficient, evmPayload.Authorization.From, fmt.Sprintf("authorization value insufficient: %s < %s", authValue.String(), requiredValue.String())) + if parsedAuthorization.Value.Cmp(requiredValue) != 0 { + return nil, x402.NewVerifyError(ErrAuthorizationValueMismatch, evmPayload.Authorization.From, fmt.Sprintf("authorization value mismatch: %s != %s", parsedAuthorization.Value.String(), requiredValue.String())) } // V1 specific: Check validBefore is in the future (with 6 second buffer for block time) now := time.Now().Unix() - validBefore, _ := new(big.Int).SetString(evmPayload.Authorization.ValidBefore, 10) - if validBefore.Cmp(big.NewInt(now+6)) < 0 { - return nil, x402.NewVerifyError(ErrAuthorizationValidBeforeExpired, evmPayload.Authorization.From, fmt.Sprintf("valid before expired: %s < %s", validBefore.String(), big.NewInt(now+6).String())) + if parsedAuthorization.ValidBefore.Cmp(big.NewInt(now+6)) < 0 { + return nil, x402.NewVerifyError(ErrAuthorizationValidBeforeExpired, evmPayload.Authorization.From, fmt.Sprintf("valid before expired: %s < %s", parsedAuthorization.ValidBefore.String(), big.NewInt(now+6).String())) } // V1 specific: Check validAfter is not in the future - validAfter, _ := new(big.Int).SetString(evmPayload.Authorization.ValidAfter, 10) - if validAfter.Cmp(big.NewInt(now)) > 0 { - return nil, x402.NewVerifyError(ErrAuthorizationValidAfterInFuture, evmPayload.Authorization.From, fmt.Sprintf("valid after in future: %s > %s", validAfter.String(), big.NewInt(now).String())) - } - - // Check balance - balance, err := f.signer.GetBalance(ctx, evmPayload.Authorization.From, tokenAddress) - if err == nil && balance.Cmp(requiredValue) < 0 { - return nil, x402.NewVerifyError(ErrInsufficientFunds, evmPayload.Authorization.From, fmt.Sprintf("insufficient funds: wallet balance %s < %s", balance.String(), requiredValue.String())) + if parsedAuthorization.ValidAfter.Cmp(big.NewInt(now)) > 0 { + return nil, x402.NewVerifyError(ErrAuthorizationValidAfterInFuture, evmPayload.Authorization.From, fmt.Sprintf("valid after in future: %s > %s", parsedAuthorization.ValidAfter.String(), big.NewInt(now).String())) } // Extract token info from requirements (already unmarshaled earlier) @@ -180,8 +184,9 @@ func (f *ExactEvmSchemeV1) Verify( return nil, x402.NewVerifyError(ErrInvalidSignatureFormat, evmPayload.Authorization.From, err.Error()) } - valid, err := f.verifySignature( + classification, err := exactfacilitator.ClassifyEIP3009Signature( ctx, + f.signer, evmPayload.Authorization, signatureBytes, chainID, @@ -193,10 +198,39 @@ func (f *ExactEvmSchemeV1) Verify( return nil, x402.NewVerifyError(ErrFailedToVerifySignature, evmPayload.Authorization.From, err.Error()) } - if !valid { + if !classification.Valid && classification.IsUndeployed && !exactfacilitator.HasEIP6492Deployment(classification.SigData) { + return nil, x402.NewVerifyError(ErrUndeployedSmartWallet, evmPayload.Authorization.From, "") + } + + if !classification.Valid && !classification.IsSmartWallet { return nil, x402.NewVerifyError(ErrInvalidSignature, evmPayload.Authorization.From, "invalid signature") } + if simulate { + simulationSucceeded, err := exactfacilitator.SimulateEIP3009Transfer( + ctx, + f.signer, + tokenAddress, + parsedAuthorization, + classification.SigData, + ) + if err != nil { + return nil, x402.NewVerifyError(ErrInvalidPayload, evmPayload.Authorization.From, err.Error()) + } + if !simulationSucceeded { + reason := exactfacilitator.DiagnoseEIP3009SimulationFailure( + ctx, + f.signer, + tokenAddress, + evmPayload.Authorization, + requiredValue, + tokenName, + tokenVersion, + ) + return nil, x402.NewVerifyError(reason, evmPayload.Authorization.From, reason) + } + } + return &x402.VerifyResponse{ IsValid: true, Payer: evmPayload.Authorization.From, @@ -213,7 +247,7 @@ func (f *ExactEvmSchemeV1) Settle( network := x402.Network(payload.Network) // First verify the payment - verifyResp, err := f.Verify(ctx, payload, requirements, fctx) + verifyResp, err := f.verify(ctx, payload, requirements, fctx, f.config.SimulateInSettle) if err != nil { // Convert VerifyError to SettleError ve := &x402.VerifyError{} @@ -266,60 +300,12 @@ func (f *ExactEvmSchemeV1) Settle( } } - // Use inner signature for settlement - signatureBytes = sigData.InnerSignature - - // Parse values - value, _ := new(big.Int).SetString(evmPayload.Authorization.Value, 10) - validAfter, _ := new(big.Int).SetString(evmPayload.Authorization.ValidAfter, 10) - validBefore, _ := new(big.Int).SetString(evmPayload.Authorization.ValidBefore, 10) - nonceBytes, _ := evm.HexToBytes(evmPayload.Authorization.Nonce) - - // Determine signature type: ECDSA (65 bytes) or smart wallet (longer) - isECDSA := len(signatureBytes) == 65 - - var txHash string - if isECDSA { - // For EOA wallets, use v,r,s overload - r := signatureBytes[0:32] - s := signatureBytes[32:64] - v := signatureBytes[64] - if v == 0 || v == 1 { - v += 27 - } - - txHash, err = f.signer.WriteContract( - ctx, - tokenAddress, - evm.TransferWithAuthorizationVRSABI, - evm.FunctionTransferWithAuthorization, - common.HexToAddress(evmPayload.Authorization.From), - common.HexToAddress(evmPayload.Authorization.To), - value, - validAfter, - validBefore, - [32]byte(nonceBytes), - v, - [32]byte(r), - [32]byte(s), - ) - } else { - // For smart wallets, use bytes signature overload - txHash, err = f.signer.WriteContract( - ctx, - tokenAddress, - evm.TransferWithAuthorizationBytesABI, - evm.FunctionTransferWithAuthorization, - common.HexToAddress(evmPayload.Authorization.From), - common.HexToAddress(evmPayload.Authorization.To), - value, - validAfter, - validBefore, - [32]byte(nonceBytes), - signatureBytes, - ) + parsedAuthorization, err := exactfacilitator.ParseEIP3009Authorization(evmPayload.Authorization) + if err != nil { + return nil, x402.NewSettleError(ErrInvalidPayload, verifyResp.Payer, network, "", err.Error()) } + txHash, err := exactfacilitator.ExecuteTransferWithAuthorization(ctx, f.signer, tokenAddress, parsedAuthorization, sigData) if err != nil { return nil, x402.NewSettleError(ErrTransactionFailed, verifyResp.Payer, network, "", err.Error()) } @@ -342,62 +328,6 @@ func (f *ExactEvmSchemeV1) Settle( }, nil } -// verifySignature verifies the EIP-712 signature -func (f *ExactEvmSchemeV1) verifySignature( - ctx context.Context, - authorization evm.ExactEIP3009Authorization, - signature []byte, - chainID *big.Int, - verifyingContract string, - tokenName string, - tokenVersion string, -) (bool, error) { - // Hash the EIP-712 typed data - hash, err := evm.HashEIP3009Authorization( - authorization, - chainID, - verifyingContract, - tokenName, - tokenVersion, - ) - if err != nil { - return false, err - } - - // Convert hash to [32]byte - var hash32 [32]byte - copy(hash32[:], hash) - - // Use universal verification (supports EOA, EIP-1271, and ERC-6492) - valid, sigData, err := evm.VerifyUniversalSignature( - ctx, - f.signer, - authorization.From, - hash32, - signature, - true, // allowUndeployed in verify() - ) - - if err != nil { - return false, err - } - - // If undeployed wallet with deployment info, it will be deployed in settle() - if sigData != nil { - zeroFactory := [20]byte{} - if sigData.Factory != zeroFactory { - _, err := f.signer.GetCode(ctx, authorization.From) - if err != nil { - return false, err - } - // Wallet may not be deployed - this is OK in verify() if has deployment info - // Actual deployment happens in settle() if configured - } - } - - return valid, nil -} - // deploySmartWallet deploys an ERC-4337 smart wallet using the ERC-6492 factory // // This function sends the pre-encoded factory calldata directly as a transaction. diff --git a/go/mechanisms/evm/multicall.go b/go/mechanisms/evm/multicall.go new file mode 100644 index 0000000000..c22141204b --- /dev/null +++ b/go/mechanisms/evm/multicall.go @@ -0,0 +1,202 @@ +package evm + +import ( + "context" + "fmt" + "reflect" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" +) + +// MulticallCall describes one batched call. +// Use CallData for pre-encoded raw calls, or ABI/FunctionName/Args for typed calls. +type MulticallCall struct { + Address string + ABI []byte + FunctionName string + Args []interface{} + CallData []byte +} + +// MulticallResult is the decoded outcome of one batched call. +type MulticallResult struct { + Status string + Result interface{} + Error error +} + +type multicallTryAggregateCall struct { + Target common.Address + CallData []byte +} + +type multicallTryAggregateResult struct { + Success bool + ReturnData []byte +} + +// Success reports whether the call completed successfully. +func (r MulticallResult) Success() bool { + return r.Status == "success" +} + +// Multicall batches typed and raw eth_call requests via Multicall3. +func Multicall( + ctx context.Context, + signer FacilitatorEvmSigner, + calls []MulticallCall, +) ([]MulticallResult, error) { + if len(calls) == 0 { + return nil, nil + } + + aggregateCalls := make([]multicallTryAggregateCall, 0, len(calls)) + for _, call := range calls { + callData, err := multicallCallData(call) + if err != nil { + return nil, err + } + + aggregateCalls = append(aggregateCalls, multicallTryAggregateCall{ + Target: common.HexToAddress(call.Address), + CallData: callData, + }) + } + + rawResults, err := signer.ReadContract( + ctx, + MULTICALL3Address, + Multicall3TryAggregateABI, + FunctionTryAggregate, + false, + aggregateCalls, + ) + if err != nil { + return nil, err + } + + decodedResults, err := normalizeMulticallResults(rawResults) + if err != nil { + return nil, err + } + if len(decodedResults) != len(calls) { + return nil, fmt.Errorf("multicall result length mismatch: got %d, want %d", len(decodedResults), len(calls)) + } + + results := make([]MulticallResult, 0, len(calls)) + for i, raw := range decodedResults { + if !raw.Success { + results = append(results, MulticallResult{ + Status: "failure", + Error: fmt.Errorf("multicall: call reverted"), + }) + continue + } + + call := calls[i] + if len(call.CallData) > 0 { + results = append(results, MulticallResult{Status: "success"}) + continue + } + + decoded, err := decodeMulticallResult(call, raw.ReturnData) + if err != nil { + results = append(results, MulticallResult{ + Status: "failure", + Error: err, + }) + continue + } + + results = append(results, MulticallResult{ + Status: "success", + Result: decoded, + }) + } + + return results, nil +} + +func multicallCallData(call MulticallCall) ([]byte, error) { + if len(call.CallData) > 0 { + return call.CallData, nil + } + + if len(call.ABI) == 0 || call.FunctionName == "" { + return nil, fmt.Errorf("multicall typed call requires ABI and function name") + } + + contractABI, err := abi.JSON(strings.NewReader(string(call.ABI))) + if err != nil { + return nil, fmt.Errorf("failed to parse ABI for multicall: %w", err) + } + + data, err := contractABI.Pack(call.FunctionName, call.Args...) + if err != nil { + return nil, fmt.Errorf("failed to pack multicall input for %s: %w", call.FunctionName, err) + } + + return data, nil +} + +func decodeMulticallResult(call MulticallCall, returnData []byte) (interface{}, error) { + contractABI, err := abi.JSON(strings.NewReader(string(call.ABI))) + if err != nil { + return nil, fmt.Errorf("failed to parse ABI for multicall decode: %w", err) + } + + outputs, err := contractABI.Unpack(call.FunctionName, returnData) + if err != nil { + return nil, fmt.Errorf("failed to decode multicall result for %s: %w", call.FunctionName, err) + } + + if len(outputs) == 0 { + return nil, nil + } + if len(outputs) == 1 { + return outputs[0], nil + } + + return outputs, nil +} + +func normalizeMulticallResults(raw interface{}) ([]multicallTryAggregateResult, error) { + value := reflect.ValueOf(raw) + if !value.IsValid() { + return nil, fmt.Errorf("multicall returned nil results") + } + if value.Kind() != reflect.Slice { + return nil, fmt.Errorf("multicall returned %T, want slice", raw) + } + + results := make([]multicallTryAggregateResult, 0, value.Len()) + for i := 0; i < value.Len(); i++ { + entry := value.Index(i) + if entry.Kind() == reflect.Interface || entry.Kind() == reflect.Pointer { + entry = entry.Elem() + } + if !entry.IsValid() || entry.Kind() != reflect.Struct { + return nil, fmt.Errorf("multicall entry %d has unexpected type %s", i, entry.Kind()) + } + + successField := entry.FieldByName("Success") + returnDataField := entry.FieldByName("ReturnData") + if !successField.IsValid() || !returnDataField.IsValid() { + return nil, fmt.Errorf("multicall entry %d missing expected fields", i) + } + + returnData, ok := returnDataField.Interface().([]byte) + if !ok { + return nil, fmt.Errorf("multicall entry %d returnData has unexpected type %T", i, returnDataField.Interface()) + } + + results = append(results, multicallTryAggregateResult{ + Success: successField.Bool(), + ReturnData: returnData, + }) + } + + return results, nil +} diff --git a/go/mechanisms/evm/verify_universal.go b/go/mechanisms/evm/verify_universal.go index 2119f6bf12..5c38f22dc0 100644 --- a/go/mechanisms/evm/verify_universal.go +++ b/go/mechanisms/evm/verify_universal.go @@ -16,12 +16,13 @@ import ( // - ERC-6492: Counterfactual signatures (undeployed contracts with deployment info) // // The verification flow: -// 1. Parse ERC-6492 wrapper if present to extract inner signature -// 2. If inner signature is exactly 65 bytes AND no factory: EOA path (optimization - skips GetCode) -// 3. Otherwise: check if contract is deployed (GetCode) -// 4. If undeployed + has deployment info + allowUndeployed: accept (deploy in settle) -// 5. If undeployed without deployment info: fallback to EOA verification -// 6. If deployed: use EIP-1271 verification +// 1. Parse ERC-6492 wrapper if present to extract inner signature +// 2. If inner signature is exactly 65 bytes AND no factory: EOA path (optimization - skips GetCode) +// 3. Otherwise: check if contract is deployed (GetCode) +// 4. If undeployed + has deployment info + allowUndeployed: classify as counterfactual, +// but do not treat it as valid until a later onchain simulation succeeds +// 5. If undeployed without deployment info: fallback to EOA verification +// 6. If deployed: use EIP-1271 verification // // Args: // @@ -62,7 +63,10 @@ func VerifyUniversalSignature( // EOA signature - use ECDSA recovery directly (avoids GetCode call) signerAddr := common.HexToAddress(signerAddress) valid, err := VerifyEOASignature(hash[:], sigData.InnerSignature, signerAddr) - return valid, sigData, err + if err == nil { + return valid, sigData, nil + } + // EOA verification failed - could be smart wallet with 65-byte sig, fall through to check GetCode } // Step 4: Potential smart wallet signature - check if contract is deployed @@ -84,16 +88,19 @@ func VerifyUniversalSignature( if !allowUndeployed { return false, nil, errors.New(ErrUndeployedSmartWallet + ": undeployed not allowed") } - // Valid ERC-6492 signature - allow it through - // Actual deployment happens in settle() if configured - return true, sigData, nil + // Preserve deployment info for callers, but require a later simulation + // to prove the inner signature would succeed onchain. + return false, sigData, nil } // No deployment info - try EOA verification as fallback // This handles the case where someone sends a non-65-byte signature from an EOA signerAddr := common.HexToAddress(signerAddress) valid, err := VerifyEOASignature(hash[:], sigData.InnerSignature, signerAddr) - return valid, sigData, err + if err != nil { + return false, sigData, err + } + return valid, sigData, nil } // Step 6: Deployed smart contract - use EIP-1271 verification diff --git a/go/mechanisms/evm/verify_universal_test.go b/go/mechanisms/evm/verify_universal_test.go index 0fd6ac4b71..09d93224d4 100644 --- a/go/mechanisms/evm/verify_universal_test.go +++ b/go/mechanisms/evm/verify_universal_test.go @@ -171,8 +171,8 @@ func TestVerifyUniversalSignature_ERC6492(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - if !valid { - t.Error("expected valid ERC-6492 signature") + if valid { + t.Error("expected ERC-6492 signature to require later simulation") } if sigData == nil { t.Fatal("expected sigData to be non-nil") @@ -223,7 +223,7 @@ func TestVerifyUniversalSignature_ERC6492(t *testing.T) { ) if err == nil { - t.Error("expected error for undeployed wallet without deployment info") + t.Error("expected error for invalid EOA signature length when used as fallback") } if valid { t.Error("expected invalid result") @@ -245,7 +245,7 @@ func TestVerifyUniversalSignature_EdgeCases(t *testing.T) { mock, "0x1234", testHash, - make([]byte, 65), + make([]byte, 100), true, ) diff --git a/go/server.go b/go/server.go index 13f0fce154..b112dea737 100644 --- a/go/server.go +++ b/go/server.go @@ -246,6 +246,22 @@ func (s *x402ResourceServer) OnSettleFailure(hook OnSettleFailureHook) *x402Reso // Core Payment Methods (V2 Only) // ============================================================================ +func mergeExtraFields(parsedExtra map[string]interface{}, configExtra map[string]interface{}) map[string]interface{} { + if len(parsedExtra) == 0 && len(configExtra) == 0 { + return nil + } + + merged := make(map[string]interface{}, len(parsedExtra)+len(configExtra)) + for key, value := range parsedExtra { + merged[key] = value + } + for key, value := range configExtra { + merged[key] = value + } + + return merged +} + // BuildPaymentRequirements creates payment requirements for a resource func (s *x402ResourceServer) BuildPaymentRequirements( ctx context.Context, @@ -288,7 +304,7 @@ func (s *x402ResourceServer) BuildPaymentRequirements( Amount: assetAmount.Amount, PayTo: config.PayTo, MaxTimeoutSeconds: maxTimeout, - Extra: assetAmount.Extra, + Extra: mergeExtraFields(assetAmount.Extra, config.Extra), } // Enhance with scheme-specific details diff --git a/go/server_test.go b/go/server_test.go index b9b70b030a..4aa6ea26bc 100644 --- a/go/server_test.go +++ b/go/server_test.go @@ -232,6 +232,10 @@ func TestServerBuildPaymentRequirements(t *testing.T) { Price: "$5.00", Network: "eip155:1", MaxTimeoutSeconds: 600, + Extra: map[string]interface{}{ + "assetTransferMethod": "permit2", + "merchantNote": "custom-scheme-data", + }, } // BuildPaymentRequirements now requires supportedKind @@ -260,6 +264,15 @@ func TestServerBuildPaymentRequirements(t *testing.T) { if requirements.Extra["enhanced"] != true { t.Fatal("Expected requirements to be enhanced") } + if requirements.Extra["decimals"] != 6 { + t.Fatalf("Expected parsed extra to be preserved, got %v", requirements.Extra["decimals"]) + } + if requirements.Extra["assetTransferMethod"] != "permit2" { + t.Fatalf("Expected config extra to be merged, got %v", requirements.Extra["assetTransferMethod"]) + } + if requirements.Extra["merchantNote"] != "custom-scheme-data" { + t.Fatalf("Expected merchant extra to be merged, got %v", requirements.Extra["merchantNote"]) + } } func TestServerBuildPaymentRequirementsNoScheme(t *testing.T) { diff --git a/go/test/integration/evm_test.go b/go/test/integration/evm_test.go index c1bc176dfb..812037aed4 100644 --- a/go/test/integration/evm_test.go +++ b/go/test/integration/evm_test.go @@ -36,6 +36,49 @@ func newRealClientEvmSigner(privateKeyHex string) (evm.ClientEvmSigner, error) { return evmsigners.NewClientSignerFromPrivateKey(privateKeyHex) } +// callContractAndDecode performs a generic eth_call and returns the decoded result. +// Used by integration test signers to support any contract read (tryAggregate, transferWithAuthorization, etc.). +func callContractAndDecode( + ctx context.Context, + ethClient *ethclient.Client, + contractAddress string, + abiBytes []byte, + functionName string, + args ...interface{}, +) (interface{}, error) { + contractABI, err := abi.JSON(strings.NewReader(string(abiBytes))) + if err != nil { + return nil, fmt.Errorf("failed to parse ABI: %w", err) + } + + callData, err := contractABI.Pack(functionName, args...) + if err != nil { + return nil, fmt.Errorf("failed to pack %s: %w", functionName, err) + } + + addr := common.HexToAddress(contractAddress) + result, err := ethClient.CallContract(ctx, ethereum.CallMsg{ + To: &addr, + Data: callData, + }, nil) + if err != nil { + return nil, fmt.Errorf("eth_call failed: %w", err) + } + + outputs, err := contractABI.Unpack(functionName, result) + if err != nil { + return nil, fmt.Errorf("failed to unpack %s result: %w", functionName, err) + } + + if len(outputs) == 0 { + return nil, nil + } + if len(outputs) == 1 { + return outputs[0], nil + } + return outputs, nil +} + // Real EVM facilitator signer type realFacilitatorEvmSigner struct { privateKey *ecdsa.PrivateKey @@ -100,15 +143,11 @@ func (s *realFacilitatorEvmSigner) GetCode(ctx context.Context, address string) func (s *realFacilitatorEvmSigner) ReadContract( ctx context.Context, contractAddress string, - abi []byte, + abiBytes []byte, functionName string, args ...interface{}, ) (interface{}, error) { - // For integration tests with authorizationState, assume nonce not used - if functionName == "authorizationState" { - return false, nil - } - return nil, fmt.Errorf("read contract not fully implemented for integration tests") + return callContractAndDecode(ctx, s.ethClient, contractAddress, abiBytes, functionName, args...) } func (s *realFacilitatorEvmSigner) WriteContract( @@ -550,6 +589,21 @@ func TestEVMIntegrationV2Permit2(t *testing.T) { // Setup resource server with EVM v2 evmServer := evmserver.NewExactEvmScheme() + evmServer.RegisterMoneyParser(func(amount float64, network x402.Network) (*x402.AssetAmount, error) { + if string(network) != "eip155:84532" { + return nil, nil + } + + return &x402.AssetAmount{ + Asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // USDC on Base Sepolia + Amount: fmt.Sprintf("%.0f", amount*1e6), + Extra: map[string]interface{}{ + "assetTransferMethod": "permit2", + "name": "USDC", + "version": "2", + }, + }, nil + }) server := x402.Newx402ResourceServer( x402.WithFacilitatorClient(facilitatorClient), ) @@ -561,21 +615,19 @@ func TestEVMIntegrationV2Permit2(t *testing.T) { t.Fatalf("Failed to initialize server: %v", err) } - // Server - builds PaymentRequired response with Permit2 method - accepts := []types.PaymentRequirements{ - { - Scheme: evm.SchemeExact, - Network: "eip155:84532", - Asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // USDC on Base Sepolia - Amount: "1000", // 0.001 USDC - PayTo: resourceServerAddress, - MaxTimeoutSeconds: 300, - Extra: map[string]interface{}{ - "assetTransferMethod": "permit2", // Request Permit2 flow - "name": "USDC", - "version": "2", - }, - }, + // Server - builds PaymentRequired response with Permit2 method via money parser + accepts, err := server.BuildPaymentRequirementsFromConfig(ctx, x402.ResourceConfig{ + Scheme: evm.SchemeExact, + Network: "eip155:84532", + PayTo: resourceServerAddress, + Price: "$0.001", + MaxTimeoutSeconds: 300, + }) + if err != nil { + t.Fatalf("Failed to build payment requirements: %v", err) + } + if accepts[0].Extra["assetTransferMethod"] != "permit2" { + t.Fatalf("Expected Permit2 payment requirements, got extra=%v", accepts[0].Extra) } resource := &types.ResourceInfo{ URL: "https://api.example.com/permit2", @@ -742,33 +794,16 @@ func (s *permit2FacilitatorEvmSigner) ReadContract( functionName string, args ...interface{}, ) (interface{}, error) { - // For authorizationState, assume nonce not used (random nonces are unique) - if functionName == "authorizationState" { - return false, nil - } - - // For allowance, read real on-chain value (fall back to MaxUint256 on any error) + // For allowance, fall back to MaxUint256 on any error (Permit2 integration test convenience) if functionName == "allowance" { - contractABI, parseErr := abi.JSON(strings.NewReader(string(abiBytes))) - if parseErr != nil { - return evm.MaxUint256(), nil //nolint:nilerr // fallback to assume approved - } - callData, packErr := contractABI.Pack(functionName, args...) - if packErr != nil { - return evm.MaxUint256(), nil //nolint:nilerr // fallback to assume approved - } - addr := common.HexToAddress(contractAddress) - result, callErr := s.ethClient.CallContract(ctx, ethereum.CallMsg{ - To: &addr, - Data: callData, - }, nil) - if callErr != nil { + result, err := callContractAndDecode(ctx, s.ethClient, contractAddress, abiBytes, functionName, args...) + if err != nil { return evm.MaxUint256(), nil //nolint:nilerr // fallback to assume approved } - return new(big.Int).SetBytes(result), nil + return result, nil } - return nil, fmt.Errorf("read contract not fully implemented for integration tests") + return callContractAndDecode(ctx, s.ethClient, contractAddress, abiBytes, functionName, args...) } func (s *permit2FacilitatorEvmSigner) WriteContract( diff --git a/go/test/unit/evm_client_facilitator_test.go b/go/test/unit/evm_client_facilitator_test.go index 5b6970d300..f6d865a531 100644 --- a/go/test/unit/evm_client_facilitator_test.go +++ b/go/test/unit/evm_client_facilitator_test.go @@ -2,16 +2,20 @@ package unit_test import ( "context" + "encoding/json" "fmt" "math/big" "strings" "testing" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/coinbase/x402/go/mechanisms/evm" evmclient "github.com/coinbase/x402/go/mechanisms/evm/exact/client" evmfacilitator "github.com/coinbase/x402/go/mechanisms/evm/exact/facilitator" + evmv1facilitator "github.com/coinbase/x402/go/mechanisms/evm/exact/v1/facilitator" "github.com/coinbase/x402/go/types" ) @@ -72,12 +76,15 @@ type mockFacilitatorSigner struct { chainID *big.Int writeContractTxHash string writeContractError error + sendTransactionError error receiptStatus uint64 receiptError error readContractError error + readContractFn func(contractAddress string, abi []byte, functionName string, args ...interface{}) (interface{}, error) verifyTypedDataResult bool verifyTypedDataError error code []byte + getCodeError error authorizationStateUsed bool lastWriteFunctionName string } @@ -101,6 +108,9 @@ func (m *mockFacilitatorSigner) GetChainID(ctx context.Context) (*big.Int, error } func (m *mockFacilitatorSigner) GetCode(ctx context.Context, address string) ([]byte, error) { + if m.getCodeError != nil { + return nil, m.getCodeError + } return m.code, nil } @@ -111,6 +121,9 @@ func (m *mockFacilitatorSigner) ReadContract( functionName string, args ...interface{}, ) (interface{}, error) { + if m.readContractFn != nil { + return m.readContractFn(contractAddress, abi, functionName, args...) + } if m.readContractError != nil { return nil, m.readContractError } @@ -150,6 +163,9 @@ func (m *mockFacilitatorSigner) WriteContract( } func (m *mockFacilitatorSigner) SendTransaction(ctx context.Context, to string, data []byte) (string, error) { + if m.sendTransactionError != nil { + return "", m.sendTransactionError + } return "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", nil } @@ -486,6 +502,119 @@ func mockSignature65Bytes() string { return "0x" + strings.Repeat("00", 65) } +type mockMulticallResult struct { + Success bool + ReturnData []byte +} + +func defaultEIP3009Requirements() types.PaymentRequirements { + return types.PaymentRequirements{ + Scheme: evm.SchemeExact, + Network: "eip155:84532", + Asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + Amount: "1000000", + PayTo: "0x9876543210987654321098765432109876543210", + Extra: map[string]interface{}{ + "name": "USDC", + "version": "2", + }, + } +} + +func defaultEIP3009Payload(signature string) types.PaymentPayload { + return types.PaymentPayload{ + X402Version: 2, + Accepted: types.PaymentRequirements{ + Scheme: evm.SchemeExact, + Network: "eip155:84532", + }, + Payload: map[string]interface{}{ + "signature": signature, + "authorization": map[string]interface{}{ + "from": "0x1234567890123456789012345678901234567890", + "to": "0x9876543210987654321098765432109876543210", + "value": "1000000", + "validAfter": "0", + "validBefore": "99999999999", + "nonce": "0x0000000000000000000000000000000000000000000000000000000000000001", + }, + }, + } +} + +func defaultEIP3009RequirementsV1(t *testing.T) types.PaymentRequirementsV1 { + t.Helper() + + extra, err := json.Marshal(map[string]interface{}{ + "name": "USDC", + "version": "2", + }) + if err != nil { + t.Fatalf("failed to marshal v1 extra: %v", err) + } + + raw := json.RawMessage(extra) + return types.PaymentRequirementsV1{ + Scheme: evm.SchemeExact, + Network: "base-sepolia", + MaxAmountRequired: "1000000", + PayTo: "0x9876543210987654321098765432109876543210", + Asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + Extra: &raw, + } +} + +func defaultEIP3009PayloadV1(signature string) types.PaymentPayloadV1 { + return types.PaymentPayloadV1{ + X402Version: 1, + Scheme: evm.SchemeExact, + Network: "base-sepolia", + Payload: defaultEIP3009Payload(signature).Payload, + } +} + +func packABIOutput(t *testing.T, abiBytes []byte, functionName string, values ...interface{}) []byte { + t.Helper() + + contractABI, err := abi.JSON(strings.NewReader(string(abiBytes))) + if err != nil { + t.Fatalf("failed to parse ABI for %s: %v", functionName, err) + } + + data, err := contractABI.Methods[functionName].Outputs.Pack(values...) + if err != nil { + t.Fatalf("failed to pack output for %s: %v", functionName, err) + } + + return data +} + +func wrapERC6492SignatureForTest(t *testing.T, factory common.Address, factoryData []byte, originalSig []byte) string { + t.Helper() + + addressTy, err := abi.NewType("address", "", nil) + if err != nil { + t.Fatalf("failed to create address ABI type: %v", err) + } + bytesTy, err := abi.NewType("bytes", "", nil) + if err != nil { + t.Fatalf("failed to create bytes ABI type: %v", err) + } + + arguments := abi.Arguments{ + {Type: addressTy}, + {Type: bytesTy}, + {Type: bytesTy}, + } + + packed, err := arguments.Pack(factory, factoryData, originalSig) + if err != nil { + t.Fatalf("failed to pack ERC-6492 signature: %v", err) + } + + return "0x" + fmt.Sprintf("%x%x", packed, common.Hex2Bytes(evm.ERC6492MagicValue[2:])) +} + // TestVerifyPermit2InvalidInputs tests validation in VerifyPermit2 func TestVerifyPermit2InvalidInputs(t *testing.T) { ctx := context.Background() @@ -804,6 +933,309 @@ func TestVerifyEIP3009TimingValidation(t *testing.T) { }) } +func TestVerifyEIP3009RejectsOverpayment(t *testing.T) { + ctx := context.Background() + requirements := defaultEIP3009Requirements() + payload := defaultEIP3009Payload(mockSignature65Bytes()) + payload.Payload["authorization"].(map[string]interface{})["value"] = "1000001" + + signer := &mockFacilitatorSigner{ + verifyTypedDataResult: true, + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + if functionName == evm.FunctionTransferWithAuthorization { + return nil, nil + } + return nil, fmt.Errorf("unsupported function: %s", functionName) + }, + } + scheme := evmfacilitator.NewExactEvmScheme(signer, nil) + + _, err := scheme.Verify(ctx, payload, requirements, nil) + if err == nil { + t.Fatal("expected overpayment mismatch error") + } + if !strings.Contains(err.Error(), evmfacilitator.ErrAuthorizationValueMismatch) { + t.Fatalf("expected %q, got %v", evmfacilitator.ErrAuthorizationValueMismatch, err) + } +} + +func TestVerifyEIP3009V1RejectsOverpayment(t *testing.T) { + ctx := context.Background() + requirements := defaultEIP3009RequirementsV1(t) + payload := defaultEIP3009PayloadV1(mockSignature65Bytes()) + payload.Payload["authorization"].(map[string]interface{})["value"] = "1000001" + + signer := &mockFacilitatorSigner{ + verifyTypedDataResult: true, + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + if functionName == evm.FunctionTransferWithAuthorization { + return nil, nil + } + return nil, fmt.Errorf("unsupported function: %s", functionName) + }, + } + scheme := evmv1facilitator.NewExactEvmSchemeV1(signer, nil) + + _, err := scheme.Verify(ctx, payload, requirements, nil) + if err == nil { + t.Fatal("expected overpayment mismatch error") + } + if !strings.Contains(err.Error(), evmv1facilitator.ErrAuthorizationValueMismatch) { + t.Fatalf("expected %q, got %v", evmv1facilitator.ErrAuthorizationValueMismatch, err) + } +} + +func TestVerifyEIP3009SimulationParity(t *testing.T) { + ctx := context.Background() + requirements := defaultEIP3009Requirements() + + t.Run("Rejects wrong token name from simulation diagnostics", func(t *testing.T) { + factory := common.HexToAddress("0x1111111111111111111111111111111111111111") + payload := defaultEIP3009Payload("0x") + payload.Payload["signature"] = wrapERC6492SignatureForTest(t, factory, []byte{0xde, 0xad}, make([]byte, 65)) + + multicallCount := 0 + signer := &mockFacilitatorSigner{ + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + if functionName != evm.FunctionTryAggregate { + return nil, fmt.Errorf("unsupported function: %s", functionName) + } + multicallCount++ + if multicallCount == 1 { + return []mockMulticallResult{ + {Success: true, ReturnData: []byte{}}, + {Success: false, ReturnData: []byte{}}, + }, nil + } + return []mockMulticallResult{ + {Success: true, ReturnData: packABIOutput(t, evm.ERC20BalanceOfABI, "balanceOf", big.NewInt(1_000_000))}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20NameABI, "name", "Wrong Name")}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20VersionABI, "version", "2")}, + {Success: true, ReturnData: packABIOutput(t, evm.AuthorizationStateABI, evm.FunctionAuthorizationState, false)}, + }, nil + }, + } + scheme := evmfacilitator.NewExactEvmScheme(signer, nil) + + _, err := scheme.Verify(ctx, payload, requirements, nil) + if err == nil { + t.Fatal("expected token name mismatch") + } + if !strings.Contains(err.Error(), evmfacilitator.ErrEip3009TokenNameMismatch) { + t.Fatalf("expected %q, got %v", evmfacilitator.ErrEip3009TokenNameMismatch, err) + } + }) + + t.Run("Rejects wrong token version from simulation diagnostics", func(t *testing.T) { + factory := common.HexToAddress("0x1111111111111111111111111111111111111111") + payload := defaultEIP3009Payload("0x") + payload.Payload["signature"] = wrapERC6492SignatureForTest(t, factory, []byte{0xde, 0xad}, make([]byte, 65)) + + multicallCount := 0 + signer := &mockFacilitatorSigner{ + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + if functionName != evm.FunctionTryAggregate { + return nil, fmt.Errorf("unsupported function: %s", functionName) + } + multicallCount++ + if multicallCount == 1 { + return []mockMulticallResult{ + {Success: true, ReturnData: []byte{}}, + {Success: false, ReturnData: []byte{}}, + }, nil + } + return []mockMulticallResult{ + {Success: true, ReturnData: packABIOutput(t, evm.ERC20BalanceOfABI, "balanceOf", big.NewInt(1_000_000))}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20NameABI, "name", "USDC")}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20VersionABI, "version", "999")}, + {Success: true, ReturnData: packABIOutput(t, evm.AuthorizationStateABI, evm.FunctionAuthorizationState, false)}, + }, nil + }, + } + scheme := evmfacilitator.NewExactEvmScheme(signer, nil) + + _, err := scheme.Verify(ctx, payload, requirements, nil) + if err == nil { + t.Fatal("expected token version mismatch") + } + if !strings.Contains(err.Error(), evmfacilitator.ErrEip3009TokenVersionMismatch) { + t.Fatalf("expected %q, got %v", evmfacilitator.ErrEip3009TokenVersionMismatch, err) + } + }) + + t.Run("Accepts deployed smart wallet when simulation succeeds", func(t *testing.T) { + signer := &mockFacilitatorSigner{ + code: []byte{0x60, 0x80}, + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + switch functionName { + case "isValidSignature": + return []byte{0x16, 0x26, 0xba, 0x7e}, nil + case evm.FunctionTransferWithAuthorization: + return nil, nil + default: + return nil, fmt.Errorf("unsupported function: %s", functionName) + } + }, + } + scheme := evmfacilitator.NewExactEvmScheme(signer, nil) + + verifyResp, err := scheme.Verify(ctx, defaultEIP3009Payload(mockSignature65Bytes()), requirements, nil) + if err != nil { + t.Fatalf("expected verification success, got %v", err) + } + if !verifyResp.IsValid { + t.Fatal("expected valid verification response") + } + }) + + t.Run("Rejects undeployed ERC-6492 when deploy+transfer simulation fails", func(t *testing.T) { + factory := common.HexToAddress("0x1111111111111111111111111111111111111111") + payload := defaultEIP3009Payload("0x") + payload.Payload["signature"] = wrapERC6492SignatureForTest(t, factory, []byte{0xde, 0xad}, make([]byte, 65)) + + multicallCount := 0 + signer := &mockFacilitatorSigner{ + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + if functionName != evm.FunctionTryAggregate { + return nil, fmt.Errorf("unsupported function: %s", functionName) + } + multicallCount++ + if multicallCount == 1 { + return []mockMulticallResult{ + {Success: true, ReturnData: []byte{}}, + {Success: false, ReturnData: []byte{}}, + }, nil + } + return []mockMulticallResult{ + {Success: true, ReturnData: packABIOutput(t, evm.ERC20BalanceOfABI, "balanceOf", big.NewInt(1_000_000))}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20NameABI, "name", "USDC")}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20VersionABI, "version", "2")}, + {Success: true, ReturnData: packABIOutput(t, evm.AuthorizationStateABI, evm.FunctionAuthorizationState, false)}, + }, nil + }, + } + scheme := evmfacilitator.NewExactEvmScheme(signer, nil) + + _, err := scheme.Verify(ctx, payload, requirements, nil) + if err == nil { + t.Fatal("expected simulation failure") + } + if !strings.Contains(err.Error(), evmfacilitator.ErrEip3009SimulationFailed) { + t.Fatalf("expected %q, got %v", evmfacilitator.ErrEip3009SimulationFailed, err) + } + }) + + t.Run("Accepts undeployed ERC-6492 when deploy+transfer simulation succeeds", func(t *testing.T) { + factory := common.HexToAddress("0x2222222222222222222222222222222222222222") + payload := defaultEIP3009Payload("0x") + payload.Payload["signature"] = wrapERC6492SignatureForTest(t, factory, []byte{0xbe, 0xef}, make([]byte, 65)) + + signer := &mockFacilitatorSigner{ + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + if functionName != evm.FunctionTryAggregate { + return nil, fmt.Errorf("unsupported function: %s", functionName) + } + return []mockMulticallResult{ + {Success: true, ReturnData: []byte{}}, + {Success: true, ReturnData: []byte{}}, + }, nil + }, + } + scheme := evmfacilitator.NewExactEvmScheme(signer, nil) + + verifyResp, err := scheme.Verify(ctx, payload, requirements, nil) + if err != nil { + t.Fatalf("expected verification success, got %v", err) + } + if !verifyResp.IsValid { + t.Fatal("expected valid verification response") + } + }) +} + +func TestSettleEIP3009SimulateInSettleToggle(t *testing.T) { + ctx := context.Background() + requirements := defaultEIP3009Requirements() + payload := defaultEIP3009Payload(mockSignature65Bytes()) + + runCase := func(simulateInSettle bool) int { + simulations := 0 + signer := &mockFacilitatorSigner{ + code: []byte{0x60, 0x80}, + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + switch functionName { + case "isValidSignature": + return []byte{0x16, 0x26, 0xba, 0x7e}, nil + case evm.FunctionTransferWithAuthorization: + simulations++ + return nil, nil + default: + return nil, fmt.Errorf("unsupported function: %s", functionName) + } + }, + } + scheme := evmfacilitator.NewExactEvmScheme(signer, &evmfacilitator.ExactEvmSchemeConfig{ + SimulateInSettle: simulateInSettle, + }) + + if _, err := scheme.Verify(ctx, payload, requirements, nil); err != nil { + t.Fatalf("verify failed: %v", err) + } + if _, err := scheme.Settle(ctx, payload, requirements, nil); err != nil { + t.Fatalf("settle failed: %v", err) + } + + return simulations + } + + if got := runCase(false); got != 1 { + t.Fatalf("expected 1 simulation when SimulateInSettle=false, got %d", got) + } + if got := runCase(true); got != 2 { + t.Fatalf("expected 2 simulations when SimulateInSettle=true, got %d", got) + } +} + +func TestVerifyEIP3009V1UsesSimulationDiagnostics(t *testing.T) { + ctx := context.Background() + requirements := defaultEIP3009RequirementsV1(t) + + factory := common.HexToAddress("0x1111111111111111111111111111111111111111") + payload := defaultEIP3009PayloadV1("0x") + payload.Payload["signature"] = wrapERC6492SignatureForTest(t, factory, []byte{0xde, 0xad}, make([]byte, 65)) + + multicallCount := 0 + signer := &mockFacilitatorSigner{ + readContractFn: func(contractAddress string, abiBytes []byte, functionName string, args ...interface{}) (interface{}, error) { + if functionName != evm.FunctionTryAggregate { + return nil, fmt.Errorf("unsupported function: %s", functionName) + } + multicallCount++ + if multicallCount == 1 { + return []mockMulticallResult{ + {Success: true, ReturnData: []byte{}}, + {Success: false, ReturnData: []byte{}}, + }, nil + } + return []mockMulticallResult{ + {Success: true, ReturnData: packABIOutput(t, evm.ERC20BalanceOfABI, "balanceOf", big.NewInt(1_000_000))}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20NameABI, "name", "Wrong Name")}, + {Success: true, ReturnData: packABIOutput(t, evm.ERC20VersionABI, "version", "2")}, + {Success: true, ReturnData: packABIOutput(t, evm.AuthorizationStateABI, evm.FunctionAuthorizationState, false)}, + }, nil + }, + } + scheme := evmv1facilitator.NewExactEvmSchemeV1(signer, nil) + + _, err := scheme.Verify(ctx, payload, requirements, nil) + if err == nil { + t.Fatal("expected token name mismatch") + } + if !strings.Contains(err.Error(), evmfacilitator.ErrEip3009TokenNameMismatch) { + t.Fatalf("expected %q, got %v", evmfacilitator.ErrEip3009TokenNameMismatch, err) + } +} + // TestExactEvmFacilitatorScheme tests the scheme initialization func TestExactEvmFacilitatorScheme(t *testing.T) { signer := &mockFacilitatorSigner{} diff --git a/go/types.go b/go/types.go index cec884ce98..4a7d5941db 100644 --- a/go/types.go +++ b/go/types.go @@ -100,11 +100,12 @@ type SettleResponse struct { // ResourceConfig defines payment configuration for a protected resource type ResourceConfig struct { - Scheme string `json:"scheme"` - PayTo string `json:"payTo"` - Price Price `json:"price"` - Network Network `json:"network"` - MaxTimeoutSeconds int `json:"maxTimeoutSeconds,omitempty"` + Scheme string `json:"scheme"` + PayTo string `json:"payTo"` + Price Price `json:"price"` + Network Network `json:"network"` + MaxTimeoutSeconds int `json:"maxTimeoutSeconds,omitempty"` + Extra map[string]interface{} `json:"extra,omitempty"` } // ============================================================================ diff --git a/python/x402/changelog.d/1474.feature.md b/python/x402/changelog.d/1474.feature.md new file mode 100644 index 0000000000..30f8d76e9c --- /dev/null +++ b/python/x402/changelog.d/1474.feature.md @@ -0,0 +1 @@ +Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling to prevent facilitator grieving and account for implementation dependent verifyTypedData; Enforce strict amount equality per spec in evm exact; Fix extra field passthrough in resource configs diff --git a/python/x402/http/x402_http_server.py b/python/x402/http/x402_http_server.py index cc6f3e852f..4799aed5a0 100644 --- a/python/x402/http/x402_http_server.py +++ b/python/x402/http/x402_http_server.py @@ -272,6 +272,7 @@ async def _build_payment_requirements_from_options( price=price, network=option.network, max_timeout_seconds=option.max_timeout_seconds, + extra=option.extra, ) requirements = self._server.build_payment_requirements(config) @@ -431,6 +432,7 @@ def _build_payment_requirements_from_options_sync( price=price, network=option.network, max_timeout_seconds=option.max_timeout_seconds, + extra=option.extra, ) requirements = self._server.build_payment_requirements(config) diff --git a/python/x402/mechanisms/evm/__init__.py b/python/x402/mechanisms/evm/__init__.py index 375436d273..a364df1775 100644 --- a/python/x402/mechanisms/evm/__init__.py +++ b/python/x402/mechanisms/evm/__init__.py @@ -8,10 +8,10 @@ DEFAULT_VALIDITY_PERIOD, EIP1271_MAGIC_VALUE, ERC6492_MAGIC_VALUE, + ERR_AUTHORIZATION_VALUE_MISMATCH, ERR_FAILED_TO_GET_ASSET_INFO, ERR_FAILED_TO_GET_NETWORK_CONFIG, ERR_FAILED_TO_VERIFY_SIGNATURE, - ERR_INSUFFICIENT_AMOUNT, ERR_INSUFFICIENT_BALANCE, ERR_INVALID_SIGNATURE, ERR_MISSING_EIP712_DOMAIN, @@ -118,7 +118,7 @@ "ERR_UNDEPLOYED_SMART_WALLET", "ERR_SMART_WALLET_DEPLOYMENT_FAILED", "ERR_RECIPIENT_MISMATCH", - "ERR_INSUFFICIENT_AMOUNT", + "ERR_AUTHORIZATION_VALUE_MISMATCH", "ERR_VALID_BEFORE_EXPIRED", "ERR_VALID_AFTER_FUTURE", "ERR_NONCE_ALREADY_USED", diff --git a/python/x402/mechanisms/evm/constants.py b/python/x402/mechanisms/evm/constants.py index 2531b26b4d..8ef6492576 100644 --- a/python/x402/mechanisms/evm/constants.py +++ b/python/x402/mechanisms/evm/constants.py @@ -36,11 +36,11 @@ ERR_UNDEPLOYED_SMART_WALLET = "invalid_exact_evm_payload_undeployed_smart_wallet" ERR_SMART_WALLET_DEPLOYMENT_FAILED = "smart_wallet_deployment_failed" ERR_RECIPIENT_MISMATCH = "invalid_exact_evm_payload_recipient_mismatch" -ERR_INSUFFICIENT_AMOUNT = "invalid_exact_evm_payload_authorization_value" +ERR_AUTHORIZATION_VALUE_MISMATCH = "invalid_exact_evm_payload_authorization_value_mismatch" ERR_VALID_BEFORE_EXPIRED = "invalid_exact_evm_payload_authorization_valid_before" ERR_VALID_AFTER_FUTURE = "invalid_exact_evm_payload_authorization_valid_after" -ERR_NONCE_ALREADY_USED = "nonce_already_used" -ERR_INSUFFICIENT_BALANCE = "insufficient_balance" +ERR_NONCE_ALREADY_USED = "invalid_exact_evm_nonce_already_used" +ERR_INSUFFICIENT_BALANCE = "invalid_exact_evm_insufficient_balance" ERR_MISSING_EIP712_DOMAIN = "missing_eip712_domain" ERR_NETWORK_MISMATCH = "network_mismatch" ERR_UNSUPPORTED_SCHEME = "unsupported_scheme" @@ -48,6 +48,10 @@ ERR_FAILED_TO_GET_ASSET_INFO = "invalid_exact_evm_failed_to_get_asset_info" ERR_FAILED_TO_VERIFY_SIGNATURE = "invalid_exact_evm_failed_to_verify_signature" ERR_TRANSACTION_FAILED = "transaction_failed" +ERR_TOKEN_NAME_MISMATCH = "invalid_exact_evm_token_name_mismatch" +ERR_TOKEN_VERSION_MISMATCH = "invalid_exact_evm_token_version_mismatch" +ERR_EIP3009_NOT_SUPPORTED = "invalid_exact_evm_eip3009_not_supported" +ERR_TRANSACTION_SIMULATION_FAILED = "invalid_exact_evm_transaction_simulation_failed" class _AssetInfoRequired(TypedDict): @@ -189,6 +193,26 @@ class NetworkConfig(_NetworkConfigRequired, total=False): } ] +NAME_ABI = [ + { + "inputs": [], + "name": "name", + "outputs": [{"name": "", "type": "string"}], + "stateMutability": "view", + "type": "function", + } +] + +VERSION_ABI = [ + { + "inputs": [], + "name": "version", + "outputs": [{"name": "", "type": "string"}], + "stateMutability": "view", + "type": "function", + } +] + IS_VALID_SIGNATURE_ABI = [ { "inputs": [ @@ -201,3 +225,34 @@ class NetworkConfig(_NetworkConfigRequired, total=False): "type": "function", } ] + +MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11" + +MULTICALL3_TRY_AGGREGATE_ABI = [ + { + "inputs": [ + {"name": "requireSuccess", "type": "bool"}, + { + "name": "calls", + "type": "tuple[]", + "components": [ + {"name": "target", "type": "address"}, + {"name": "callData", "type": "bytes"}, + ], + }, + ], + "name": "tryAggregate", + "outputs": [ + { + "name": "returnData", + "type": "tuple[]", + "components": [ + {"name": "success", "type": "bool"}, + {"name": "returnData", "type": "bytes"}, + ], + } + ], + "stateMutability": "payable", + "type": "function", + } +] diff --git a/python/x402/mechanisms/evm/exact/eip3009_utils.py b/python/x402/mechanisms/evm/exact/eip3009_utils.py new file mode 100644 index 0000000000..0b0885e461 --- /dev/null +++ b/python/x402/mechanisms/evm/exact/eip3009_utils.py @@ -0,0 +1,315 @@ +"""Shared EIP-3009 helpers for exact EVM facilitators.""" + +from __future__ import annotations + +from dataclasses import dataclass + +from ..constants import ( + AUTHORIZATION_STATE_ABI, + BALANCE_OF_ABI, + ERR_EIP3009_NOT_SUPPORTED, + ERR_INSUFFICIENT_BALANCE, + ERR_NONCE_ALREADY_USED, + ERR_TOKEN_NAME_MISMATCH, + ERR_TOKEN_VERSION_MISMATCH, + ERR_TRANSACTION_SIMULATION_FAILED, + FUNCTION_TRANSFER_WITH_AUTHORIZATION, + NAME_ABI, + TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, + TRANSFER_WITH_AUTHORIZATION_VRS_ABI, + VERSION_ABI, +) +from ..eip712 import build_typed_data_for_signing +from ..erc6492 import has_deployment_info, parse_erc6492_signature +from ..multicall import MulticallCall, encode_contract_call, multicall +from ..signer import FacilitatorEvmSigner +from ..types import ERC6492SignatureData, ExactEIP3009Authorization +from ..utils import bytes_to_hex, hex_to_bytes + + +@dataclass +class ParsedEIP3009Authorization: + """Parsed authorization values ready for contract calls.""" + + from_address: str + to: str + value: int + valid_after: int + valid_before: int + nonce: bytes + + +@dataclass +class EIP3009SignatureClassification: + """How the facilitator should treat a signature before simulation.""" + + valid: bool + is_smart_wallet: bool + is_undeployed: bool + sig_data: ERC6492SignatureData + + +def parse_eip3009_authorization( + authorization: ExactEIP3009Authorization, +) -> ParsedEIP3009Authorization: + """Parse string-encoded authorization fields into contract-call values.""" + nonce = hex_to_bytes(authorization.nonce) + if len(nonce) != 32: + raise ValueError(f"invalid nonce length: got {len(nonce)} bytes, want 32") + + return ParsedEIP3009Authorization( + from_address=authorization.from_address, + to=authorization.to, + value=int(authorization.value), + valid_after=int(authorization.valid_after), + valid_before=int(authorization.valid_before), + nonce=nonce, + ) + + +def classify_eip3009_signature( + signer: FacilitatorEvmSigner, + authorization: ExactEIP3009Authorization, + signature: bytes, + chain_id: int, + token_address: str, + token_name: str, + token_version: str, +) -> EIP3009SignatureClassification: + """Classify the signature before deciding whether simulation may rescue it.""" + sig_data = parse_erc6492_signature(signature) + domain, types, primary_type, message = build_typed_data_for_signing( + authorization, + chain_id, + token_address, + token_name, + token_version, + ) + + is_smart_wallet = has_deployment_info(sig_data) or len(sig_data.inner_signature) != 65 + valid = signer.verify_typed_data( + authorization.from_address, + domain, + types, + primary_type, + message, + sig_data.inner_signature, + ) + if valid: + return EIP3009SignatureClassification( + valid=True, + is_smart_wallet=is_smart_wallet, + is_undeployed=False, + sig_data=sig_data, + ) + + code = signer.get_code(authorization.from_address) + if len(code) > 0: + return EIP3009SignatureClassification( + valid=False, + is_smart_wallet=True, + is_undeployed=False, + sig_data=sig_data, + ) + + if has_deployment_info(sig_data): + return EIP3009SignatureClassification( + valid=False, + is_smart_wallet=True, + is_undeployed=True, + sig_data=sig_data, + ) + + return EIP3009SignatureClassification( + valid=False, + is_smart_wallet=is_smart_wallet, + is_undeployed=is_smart_wallet, + sig_data=sig_data, + ) + + +def simulate_eip3009_transfer( + signer: FacilitatorEvmSigner, + token_address: str, + parsed: ParsedEIP3009Authorization, + sig_data: ERC6492SignatureData, +) -> bool: + """Simulate `transferWithAuthorization` and return whether it succeeds.""" + if has_deployment_info(sig_data): + transfer_calldata = encode_contract_call( + TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, + FUNCTION_TRANSFER_WITH_AUTHORIZATION, + parsed.from_address, + parsed.to, + parsed.value, + parsed.valid_after, + parsed.valid_before, + parsed.nonce, + sig_data.inner_signature, + ) + try: + results = multicall( + signer, + [ + MulticallCall( + address=bytes_to_hex(sig_data.factory), + call_data=sig_data.factory_calldata, + ), + MulticallCall(address=token_address, call_data=transfer_calldata), + ], + ) + except Exception: + return False + return len(results) >= 2 and results[1].success + + if len(sig_data.inner_signature) == 65: + v, r, s = _split_signature_parts(sig_data.inner_signature) + try: + signer.read_contract( + token_address, + TRANSFER_WITH_AUTHORIZATION_VRS_ABI, + FUNCTION_TRANSFER_WITH_AUTHORIZATION, + parsed.from_address, + parsed.to, + parsed.value, + parsed.valid_after, + parsed.valid_before, + parsed.nonce, + v, + r, + s, + ) + except Exception: + return False + return True + + try: + signer.read_contract( + token_address, + TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, + FUNCTION_TRANSFER_WITH_AUTHORIZATION, + parsed.from_address, + parsed.to, + parsed.value, + parsed.valid_after, + parsed.valid_before, + parsed.nonce, + sig_data.inner_signature, + ) + except Exception: + return False + return True + + +def diagnose_eip3009_simulation_failure( + signer: FacilitatorEvmSigner, + token_address: str, + authorization: ExactEIP3009Authorization, + required_amount: int, + token_name: str, + token_version: str, +) -> str: + """Map a failed transfer simulation to the most specific invalid reason.""" + try: + results = multicall( + signer, + [ + MulticallCall( + address=token_address, + abi=BALANCE_OF_ABI, + function_name="balanceOf", + args=(authorization.from_address,), + ), + MulticallCall(address=token_address, abi=NAME_ABI, function_name="name"), + MulticallCall( + address=token_address, + abi=VERSION_ABI, + function_name="version", + ), + MulticallCall( + address=token_address, + abi=AUTHORIZATION_STATE_ABI, + function_name="authorizationState", + args=(authorization.from_address, hex_to_bytes(authorization.nonce)), + ), + ], + ) + except Exception: + return ERR_TRANSACTION_SIMULATION_FAILED + + if len(results) < 4: + return ERR_TRANSACTION_SIMULATION_FAILED + + authorization_state = results[3] + if not authorization_state.success: + return ERR_EIP3009_NOT_SUPPORTED + if bool(authorization_state.result): + return ERR_NONCE_ALREADY_USED + + name_result = results[1] + if token_name and name_result.success and isinstance(name_result.result, str): + if name_result.result != token_name: + return ERR_TOKEN_NAME_MISMATCH + + version_result = results[2] + if token_version and version_result.success and isinstance(version_result.result, str): + if version_result.result != token_version: + return ERR_TOKEN_VERSION_MISMATCH + + balance_result = results[0] + if balance_result.success: + try: + if int(balance_result.result) < required_amount: + return ERR_INSUFFICIENT_BALANCE + except (TypeError, ValueError): + pass + + return ERR_TRANSACTION_SIMULATION_FAILED + + +def execute_transfer_with_authorization( + signer: FacilitatorEvmSigner, + token_address: str, + parsed: ParsedEIP3009Authorization, + sig_data: ERC6492SignatureData, +) -> str: + """Execute `transferWithAuthorization` using the correct ABI overload.""" + if len(sig_data.inner_signature) == 65: + v, r, s = _split_signature_parts(sig_data.inner_signature) + return signer.write_contract( + token_address, + TRANSFER_WITH_AUTHORIZATION_VRS_ABI, + FUNCTION_TRANSFER_WITH_AUTHORIZATION, + parsed.from_address, + parsed.to, + parsed.value, + parsed.valid_after, + parsed.valid_before, + parsed.nonce, + v, + r, + s, + ) + + return signer.write_contract( + token_address, + TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, + FUNCTION_TRANSFER_WITH_AUTHORIZATION, + parsed.from_address, + parsed.to, + parsed.value, + parsed.valid_after, + parsed.valid_before, + parsed.nonce, + sig_data.inner_signature, + ) + + +def _split_signature_parts(signature: bytes) -> tuple[int, bytes, bytes]: + if len(signature) != 65: + raise ValueError(f"invalid ECDSA signature length: expected 65, got {len(signature)}") + + v = signature[64] + if v in (0, 1): + v += 27 + return (v, signature[:32], signature[32:64]) diff --git a/python/x402/mechanisms/evm/exact/facilitator.py b/python/x402/mechanisms/evm/exact/facilitator.py index ecf3b070c3..a80bacb6f7 100644 --- a/python/x402/mechanisms/evm/exact/facilitator.py +++ b/python/x402/mechanisms/evm/exact/facilitator.py @@ -12,15 +12,12 @@ VerifyResponse, ) from ..constants import ( - AUTHORIZATION_STATE_ABI, + ERR_AUTHORIZATION_VALUE_MISMATCH, ERR_FAILED_TO_GET_NETWORK_CONFIG, ERR_FAILED_TO_VERIFY_SIGNATURE, - ERR_INSUFFICIENT_AMOUNT, - ERR_INSUFFICIENT_BALANCE, ERR_INVALID_SIGNATURE, ERR_MISSING_EIP712_DOMAIN, ERR_NETWORK_MISMATCH, - ERR_NONCE_ALREADY_USED, ERR_RECIPIENT_MISMATCH, ERR_SMART_WALLET_DEPLOYMENT_FAILED, ERR_TRANSACTION_FAILED, @@ -29,16 +26,19 @@ ERR_VALID_AFTER_FUTURE, ERR_VALID_BEFORE_EXPIRED, SCHEME_EXACT, - TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, - TRANSFER_WITH_AUTHORIZATION_VRS_ABI, TX_STATUS_SUCCESS, ) -from ..eip712 import hash_eip3009_authorization from ..erc6492 import has_deployment_info, parse_erc6492_signature +from ..exact.eip3009_utils import ( + classify_eip3009_signature, + diagnose_eip3009_simulation_failure, + execute_transfer_with_authorization, + parse_eip3009_authorization, + simulate_eip3009_transfer, +) from ..signer import FacilitatorEvmSigner from ..types import ERC6492SignatureData, ExactEIP3009Payload from ..utils import bytes_to_hex, get_evm_chain_id, hex_to_bytes, normalize_address -from ..verify import verify_universal_signature @dataclass @@ -48,6 +48,9 @@ class ExactEvmSchemeConfig: deploy_erc4337_with_eip6492: bool = False """Enable automatic smart wallet deployment via EIP-6492.""" + simulate_in_settle: bool = False + """Rerun transfer simulation during settle.""" + class ExactEvmScheme: """EVM facilitator implementation for the Exact payment scheme (V2). @@ -103,6 +106,14 @@ def verify( payload: PaymentPayload, requirements: PaymentRequirements, context=None, + ) -> VerifyResponse: + return self._verify(payload, requirements, simulate=True) + + def _verify( + self, + payload: PaymentPayload, + requirements: PaymentRequirements, + simulate: bool, ) -> VerifyResponse: """Verify EIP-3009 payment payload. @@ -110,7 +121,7 @@ def verify( - Scheme and network match - Signature is valid (EOA, EIP-1271, or ERC-6492) - Recipient matches requirements.pay_to - - Amount >= requirements.amount + - Amount exactly matches requirements.amount - Validity window is correct - Nonce hasn't been used - Payer has sufficient balance @@ -163,9 +174,11 @@ def verify( ) # Validate amount - if int(evm_payload.authorization.value) < int(requirements.amount): + if int(evm_payload.authorization.value) != int(requirements.amount): return VerifyResponse( - is_valid=False, invalid_reason=ERR_INSUFFICIENT_AMOUNT, payer=payer + is_valid=False, + invalid_reason=ERR_AUTHORIZATION_VALUE_MISMATCH, + payer=payer, ) # Validate timing @@ -183,46 +196,30 @@ def verify( is_valid=False, invalid_reason=ERR_VALID_AFTER_FUTURE, payer=payer ) - # Check nonce - try: - nonce_used = self._check_nonce_used( - payer, evm_payload.authorization.nonce, token_address - ) - if nonce_used: - return VerifyResponse( - is_valid=False, invalid_reason=ERR_NONCE_ALREADY_USED, payer=payer - ) - except Exception: - pass # Continue if nonce check fails - - # Check balance - try: - balance = self._signer.get_balance(payer, token_address) - if balance < int(evm_payload.authorization.value): - return VerifyResponse( - is_valid=False, invalid_reason=ERR_INSUFFICIENT_BALANCE, payer=payer - ) - except Exception: - pass # Continue if balance check fails - # Verify signature if not evm_payload.signature: return VerifyResponse(is_valid=False, invalid_reason=ERR_INVALID_SIGNATURE, payer=payer) - signature = hex_to_bytes(evm_payload.signature) - hash_bytes = hash_eip3009_authorization( - evm_payload.authorization, - chain_id, - token_address, - extra["name"], - extra["version"], - ) - try: - valid, _ = verify_universal_signature( - self._signer, payer, hash_bytes, signature, allow_undeployed=True + signature = hex_to_bytes(evm_payload.signature) + classification = classify_eip3009_signature( + self._signer, + evm_payload.authorization, + signature, + chain_id, + token_address, + extra["name"], + extra["version"], ) - if not valid: + if not classification.valid and classification.is_undeployed: + if not has_deployment_info(classification.sig_data): + return VerifyResponse( + is_valid=False, + invalid_reason=ERR_UNDEPLOYED_SMART_WALLET, + payer=payer, + ) + + if not classification.valid and not classification.is_smart_wallet: return VerifyResponse( is_valid=False, invalid_reason=ERR_INVALID_SIGNATURE, payer=payer ) @@ -234,6 +231,38 @@ def verify( payer=payer, ) + if not simulate: + return VerifyResponse(is_valid=True, payer=payer) + + try: + parsed_authorization = parse_eip3009_authorization(evm_payload.authorization) + except Exception as e: + return VerifyResponse( + is_valid=False, + invalid_reason=ERR_FAILED_TO_VERIFY_SIGNATURE, + invalid_message=str(e), + payer=payer, + ) + + if not simulate_eip3009_transfer( + self._signer, + token_address, + parsed_authorization, + classification.sig_data, + ): + return VerifyResponse( + is_valid=False, + invalid_reason=diagnose_eip3009_simulation_failure( + self._signer, + token_address, + evm_payload.authorization, + int(requirements.amount), + extra["name"], + extra["version"], + ), + payer=payer, + ) + return VerifyResponse(is_valid=True, payer=payer) def settle( @@ -257,7 +286,11 @@ def settle( SettleResponse with success, transaction, and payer. """ # First verify - verify_result = self.verify(payload, requirements, context) + verify_result = self._verify( + payload, + requirements, + simulate=self._config.simulate_in_settle, + ) if not verify_result.is_valid: return SettleResponse( success=False, @@ -272,8 +305,19 @@ def settle( network = str(requirements.network) token_address = normalize_address(requirements.asset) - signature = hex_to_bytes(evm_payload.signature) - sig_data = parse_erc6492_signature(signature) + try: + signature = hex_to_bytes(evm_payload.signature or "") + sig_data = parse_erc6492_signature(signature) + parsed_authorization = parse_eip3009_authorization(evm_payload.authorization) + except Exception as e: + return SettleResponse( + success=False, + error_reason=ERR_TRANSACTION_FAILED, + error_message=str(e), + network=network, + payer=payer, + transaction="", + ) # Deploy smart wallet if needed if has_deployment_info(sig_data): @@ -300,43 +344,13 @@ def settle( transaction="", ) - # Use inner signature for settlement - inner_sig = sig_data.inner_signature - is_ecdsa = len(inner_sig) == 65 - try: - if is_ecdsa: - # EOA: v,r,s overload - r, s, v = inner_sig[:32], inner_sig[32:64], inner_sig[64] - tx_hash = self._signer.write_contract( - token_address, - TRANSFER_WITH_AUTHORIZATION_VRS_ABI, - "transferWithAuthorization", - payer, - evm_payload.authorization.to, - int(evm_payload.authorization.value), - int(evm_payload.authorization.valid_after), - int(evm_payload.authorization.valid_before), - hex_to_bytes(evm_payload.authorization.nonce), - v, - r, - s, - ) - else: - # Smart wallet: bytes overload - tx_hash = self._signer.write_contract( - token_address, - TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, - "transferWithAuthorization", - payer, - evm_payload.authorization.to, - int(evm_payload.authorization.value), - int(evm_payload.authorization.valid_after), - int(evm_payload.authorization.valid_before), - hex_to_bytes(evm_payload.authorization.nonce), - inner_sig, - ) - + tx_hash = execute_transfer_with_authorization( + self._signer, + token_address, + parsed_authorization, + sig_data, + ) receipt = self._signer.wait_for_transaction_receipt(tx_hash) if receipt.status != TX_STATUS_SUCCESS: return SettleResponse( @@ -364,26 +378,6 @@ def settle( transaction="", ) - def _check_nonce_used(self, from_addr: str, nonce: str, token: str) -> bool: - """Check if EIP-3009 nonce has been used. - - Args: - from_addr: Authorizer address. - nonce: Nonce hex string. - token: Token contract address. - - Returns: - True if nonce has been used. - """ - result = self._signer.read_contract( - token, - AUTHORIZATION_STATE_ABI, - "authorizationState", - from_addr, - hex_to_bytes(nonce), - ) - return bool(result) - def _deploy_smart_wallet(self, sig_data: ERC6492SignatureData) -> None: """Deploy ERC-4337 smart wallet via ERC-6492 factory. diff --git a/python/x402/mechanisms/evm/exact/register.py b/python/x402/mechanisms/evm/exact/register.py index 00656224f8..2d871980ee 100644 --- a/python/x402/mechanisms/evm/exact/register.py +++ b/python/x402/mechanisms/evm/exact/register.py @@ -105,6 +105,7 @@ def register_exact_evm_facilitator( signer: "FacilitatorEvmSigner", networks: str | list[str], deploy_erc4337_with_eip6492: bool = False, + simulate_in_settle: bool = False, ) -> FacilitatorT: """Register EVM exact payment schemes to x402Facilitator. @@ -117,6 +118,7 @@ def register_exact_evm_facilitator( signer: EVM signer for verification/settlement. networks: Network(s) to register. deploy_erc4337_with_eip6492: Enable smart wallet deployment. + simulate_in_settle: Rerun verify-time simulation inside settle. Returns: Facilitator for chaining. @@ -126,7 +128,10 @@ def register_exact_evm_facilitator( from .v1.facilitator import ExactEvmSchemeV1 as ExactEvmFacilitatorSchemeV1 from .v1.facilitator import ExactEvmSchemeV1Config - config = ExactEvmSchemeConfig(deploy_erc4337_with_eip6492=deploy_erc4337_with_eip6492) + config = ExactEvmSchemeConfig( + deploy_erc4337_with_eip6492=deploy_erc4337_with_eip6492, + simulate_in_settle=simulate_in_settle, + ) scheme = ExactEvmFacilitatorScheme(signer, config) if isinstance(networks, str): @@ -134,7 +139,10 @@ def register_exact_evm_facilitator( facilitator.register(networks, scheme) # Register V1 - v1_config = ExactEvmSchemeV1Config(deploy_erc4337_with_eip6492=deploy_erc4337_with_eip6492) + v1_config = ExactEvmSchemeV1Config( + deploy_erc4337_with_eip6492=deploy_erc4337_with_eip6492, + simulate_in_settle=simulate_in_settle, + ) v1_scheme = ExactEvmFacilitatorSchemeV1(signer, v1_config) facilitator.register_v1(V1_NETWORKS, v1_scheme) diff --git a/python/x402/mechanisms/evm/exact/v1/facilitator.py b/python/x402/mechanisms/evm/exact/v1/facilitator.py index 538d68c068..412bece471 100644 --- a/python/x402/mechanisms/evm/exact/v1/facilitator.py +++ b/python/x402/mechanisms/evm/exact/v1/facilitator.py @@ -8,10 +8,9 @@ from .....schemas import Network, SettleResponse, VerifyResponse from .....schemas.v1 import PaymentPayloadV1, PaymentRequirementsV1 from ...constants import ( + ERR_AUTHORIZATION_VALUE_MISMATCH, ERR_FAILED_TO_GET_NETWORK_CONFIG, ERR_FAILED_TO_VERIFY_SIGNATURE, - ERR_INSUFFICIENT_AMOUNT, - ERR_INSUFFICIENT_BALANCE, ERR_INVALID_SIGNATURE, ERR_MISSING_EIP712_DOMAIN, ERR_NETWORK_MISMATCH, @@ -23,17 +22,20 @@ ERR_VALID_AFTER_FUTURE, ERR_VALID_BEFORE_EXPIRED, SCHEME_EXACT, - TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, - TRANSFER_WITH_AUTHORIZATION_VRS_ABI, TX_STATUS_SUCCESS, ) -from ...eip712 import hash_eip3009_authorization from ...erc6492 import has_deployment_info, parse_erc6492_signature from ...signer import FacilitatorEvmSigner from ...types import ERC6492SignatureData, ExactEIP3009Payload from ...utils import bytes_to_hex, hex_to_bytes, normalize_address from ...v1.utils import get_evm_chain_id -from ...verify import verify_universal_signature +from ..eip3009_utils import ( + classify_eip3009_signature, + diagnose_eip3009_simulation_failure, + execute_transfer_with_authorization, + parse_eip3009_authorization, + simulate_eip3009_transfer, +) @dataclass @@ -43,6 +45,9 @@ class ExactEvmSchemeV1Config: deploy_erc4337_with_eip6492: bool = False """Enable automatic smart wallet deployment via EIP-6492.""" + simulate_in_settle: bool = False + """Rerun transfer simulation during settle.""" + class ExactEvmSchemeV1: """EVM facilitator implementation for Exact payment scheme (V1). @@ -102,12 +107,20 @@ def verify( payload: PaymentPayloadV1, requirements: PaymentRequirementsV1, context=None, + ) -> VerifyResponse: + return self._verify(payload, requirements, simulate=True) + + def _verify( + self, + payload: PaymentPayloadV1, + requirements: PaymentRequirementsV1, + simulate: bool, ) -> VerifyResponse: """Verify EIP-3009 payment payload (V1). V1 validation differences: - scheme/network at top level of payload - - Uses maxAmountRequired for amount check + - Uses maxAmountRequired for exact amount validation - extra is JSON-encoded Args: @@ -161,9 +174,11 @@ def verify( ) # V1: Use maxAmountRequired - if int(evm_payload.authorization.value) < int(requirements.max_amount_required): + if int(evm_payload.authorization.value) != int(requirements.max_amount_required): return VerifyResponse( - is_valid=False, invalid_reason=ERR_INSUFFICIENT_AMOUNT, payer=payer + is_valid=False, + invalid_reason=ERR_AUTHORIZATION_VALUE_MISMATCH, + payer=payer, ) # V1: Check validBefore is in future (6 second buffer) @@ -179,34 +194,30 @@ def verify( is_valid=False, invalid_reason=ERR_VALID_AFTER_FUTURE, payer=payer ) - # Check balance - try: - balance = self._signer.get_balance(payer, token_address) - if balance < int(requirements.max_amount_required): - return VerifyResponse( - is_valid=False, invalid_reason=ERR_INSUFFICIENT_BALANCE, payer=payer - ) - except Exception: - pass # Continue if balance check fails - # Verify signature if not evm_payload.signature: return VerifyResponse(is_valid=False, invalid_reason=ERR_INVALID_SIGNATURE, payer=payer) - signature = hex_to_bytes(evm_payload.signature) - hash_bytes = hash_eip3009_authorization( - evm_payload.authorization, - chain_id, - token_address, - extra["name"], - extra["version"], - ) - try: - valid, _ = verify_universal_signature( - self._signer, payer, hash_bytes, signature, allow_undeployed=True + signature = hex_to_bytes(evm_payload.signature) + classification = classify_eip3009_signature( + self._signer, + evm_payload.authorization, + signature, + chain_id, + token_address, + extra["name"], + extra["version"], ) - if not valid: + if not classification.valid and classification.is_undeployed: + if not has_deployment_info(classification.sig_data): + return VerifyResponse( + is_valid=False, + invalid_reason=ERR_UNDEPLOYED_SMART_WALLET, + payer=payer, + ) + + if not classification.valid and not classification.is_smart_wallet: return VerifyResponse( is_valid=False, invalid_reason=ERR_INVALID_SIGNATURE, payer=payer ) @@ -218,6 +229,38 @@ def verify( payer=payer, ) + if not simulate: + return VerifyResponse(is_valid=True, payer=payer) + + try: + parsed_authorization = parse_eip3009_authorization(evm_payload.authorization) + except Exception as e: + return VerifyResponse( + is_valid=False, + invalid_reason=ERR_FAILED_TO_VERIFY_SIGNATURE, + invalid_message=str(e), + payer=payer, + ) + + if not simulate_eip3009_transfer( + self._signer, + token_address, + parsed_authorization, + classification.sig_data, + ): + return VerifyResponse( + is_valid=False, + invalid_reason=diagnose_eip3009_simulation_failure( + self._signer, + token_address, + evm_payload.authorization, + int(requirements.max_amount_required), + extra["name"], + extra["version"], + ), + payer=payer, + ) + return VerifyResponse(is_valid=True, payer=payer) def settle( @@ -238,7 +281,11 @@ def settle( SettleResponse with success, transaction, and payer. """ # First verify - verify_result = self.verify(payload, requirements, context) + verify_result = self._verify( + payload, + requirements, + simulate=self._config.simulate_in_settle, + ) if not verify_result.is_valid: return SettleResponse( success=False, @@ -253,8 +300,19 @@ def settle( network = requirements.network token_address = normalize_address(requirements.asset) - signature = hex_to_bytes(evm_payload.signature) - sig_data = parse_erc6492_signature(signature) + try: + signature = hex_to_bytes(evm_payload.signature or "") + sig_data = parse_erc6492_signature(signature) + parsed_authorization = parse_eip3009_authorization(evm_payload.authorization) + except Exception as e: + return SettleResponse( + success=False, + error_reason=ERR_TRANSACTION_FAILED, + error_message=str(e), + network=network, + payer=payer, + transaction="", + ) # Deploy smart wallet if needed if has_deployment_info(sig_data): @@ -281,40 +339,13 @@ def settle( transaction="", ) - inner_sig = sig_data.inner_signature - is_ecdsa = len(inner_sig) == 65 - try: - if is_ecdsa: - r, s, v = inner_sig[:32], inner_sig[32:64], inner_sig[64] - tx_hash = self._signer.write_contract( - token_address, - TRANSFER_WITH_AUTHORIZATION_VRS_ABI, - "transferWithAuthorization", - payer, - evm_payload.authorization.to, - int(evm_payload.authorization.value), - int(evm_payload.authorization.valid_after), - int(evm_payload.authorization.valid_before), - hex_to_bytes(evm_payload.authorization.nonce), - v, - r, - s, - ) - else: - tx_hash = self._signer.write_contract( - token_address, - TRANSFER_WITH_AUTHORIZATION_BYTES_ABI, - "transferWithAuthorization", - payer, - evm_payload.authorization.to, - int(evm_payload.authorization.value), - int(evm_payload.authorization.valid_after), - int(evm_payload.authorization.valid_before), - hex_to_bytes(evm_payload.authorization.nonce), - inner_sig, - ) - + tx_hash = execute_transfer_with_authorization( + self._signer, + token_address, + parsed_authorization, + sig_data, + ) receipt = self._signer.wait_for_transaction_receipt(tx_hash) if receipt.status != TX_STATUS_SUCCESS: return SettleResponse( diff --git a/python/x402/mechanisms/evm/multicall.py b/python/x402/mechanisms/evm/multicall.py new file mode 100644 index 0000000000..8a99689286 --- /dev/null +++ b/python/x402/mechanisms/evm/multicall.py @@ -0,0 +1,172 @@ +"""Helpers for batching `eth_call` requests through Multicall3.""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import Any + +try: + from eth_abi import decode, encode + from eth_utils import keccak +except ImportError as e: + raise ImportError( + "EVM mechanism requires ethereum packages. Install with: pip install x402[evm]" + ) from e + +from .constants import MULTICALL3_ADDRESS, MULTICALL3_TRY_AGGREGATE_ABI +from .signer import FacilitatorEvmSigner + + +@dataclass +class MulticallCall: + """One call executed through Multicall3.""" + + address: str + abi: list[dict[str, Any]] | None = None + function_name: str = "" + args: tuple[Any, ...] = field(default_factory=tuple) + call_data: bytes = b"" + + +@dataclass +class MulticallResult: + """Decoded result for a single multicall entry.""" + + success: bool + result: Any = None + error: Exception | None = None + + +def encode_contract_call( + abi: list[dict[str, Any]], + function_name: str, + *args: Any, +) -> bytes: + """Encode calldata for a contract function.""" + function = _get_function_abi(abi, function_name) + input_types = [_canonical_type(item) for item in function.get("inputs", [])] + signature = f"{function_name}({','.join(input_types)})" + selector = keccak(text=signature)[:4] + return selector + encode(input_types, list(args)) + + +def multicall( + signer: FacilitatorEvmSigner, + calls: list[MulticallCall], +) -> list[MulticallResult]: + """Batch calls through Multicall3 and decode the results.""" + if not calls: + return [] + + aggregate_calls = [] + for call in calls: + call_data = call.call_data + if not call_data: + if not call.abi or not call.function_name: + raise ValueError("typed multicall entries require ABI and function name") + call_data = encode_contract_call(call.abi, call.function_name, *call.args) + aggregate_calls.append((call.address, call_data)) + + raw_results = signer.read_contract( + MULTICALL3_ADDRESS, + MULTICALL3_TRY_AGGREGATE_ABI, + "tryAggregate", + False, + aggregate_calls, + ) + normalized = _normalize_results(raw_results) + + if len(normalized) != len(calls): + raise ValueError( + f"multicall result length mismatch: got {len(normalized)}, want {len(calls)}" + ) + + results: list[MulticallResult] = [] + for raw_result, call in zip(normalized, calls, strict=True): + success, return_data = raw_result + if not success: + results.append( + MulticallResult( + success=False, + error=RuntimeError("multicall: call reverted"), + ) + ) + continue + + if call.call_data: + results.append(MulticallResult(success=True)) + continue + + try: + decoded = _decode_contract_result(call.abi or [], call.function_name, return_data) + except Exception as exc: + results.append(MulticallResult(success=False, error=exc)) + continue + + results.append(MulticallResult(success=True, result=decoded)) + + return results + + +def _decode_contract_result( + abi: list[dict[str, Any]], + function_name: str, + return_data: bytes, +) -> Any: + function = _get_function_abi(abi, function_name) + output_types = [_canonical_type(item) for item in function.get("outputs", [])] + if not output_types: + return None + + decoded = decode(output_types, return_data) + if len(decoded) == 1: + return decoded[0] + return list(decoded) + + +def _get_function_abi(abi: list[dict[str, Any]], function_name: str) -> dict[str, Any]: + for entry in abi: + if entry.get("type") == "function" and entry.get("name") == function_name: + return entry + raise ValueError(f"Function {function_name} not found in ABI") + + +def _canonical_type(abi_item: dict[str, Any]) -> str: + item_type = abi_item["type"] + if not item_type.startswith("tuple"): + return item_type + + suffix = item_type[len("tuple") :] + components = ",".join(_canonical_type(component) for component in abi_item["components"]) + return f"({components}){suffix}" + + +def _normalize_results(raw_results: Any) -> list[tuple[bool, bytes]]: + if not isinstance(raw_results, list | tuple): + raise ValueError(f"multicall returned {type(raw_results)!r}, want sequence") + + normalized: list[tuple[bool, bytes]] = [] + for index, entry in enumerate(raw_results): + if isinstance(entry, dict): + success = bool(entry["success"]) + return_data = entry["returnData"] + else: + if hasattr(entry, "success") and hasattr(entry, "returnData"): + success = bool(entry.success) + return_data = entry.returnData + elif isinstance(entry, list | tuple) and len(entry) == 2: + success = bool(entry[0]) + return_data = entry[1] + else: + raise ValueError(f"multicall entry {index} has unexpected type {type(entry)!r}") + + if isinstance(return_data, str): + return_data = bytes.fromhex(return_data.removeprefix("0x")) + if not isinstance(return_data, bytes): + raise ValueError( + f"multicall entry {index} returnData has unexpected type {type(return_data)!r}" + ) + + normalized.append((success, return_data)) + + return normalized diff --git a/python/x402/mechanisms/svm/exact/facilitator.py b/python/x402/mechanisms/svm/exact/facilitator.py index 94a87419e5..42b90ce1e8 100644 --- a/python/x402/mechanisms/svm/exact/facilitator.py +++ b/python/x402/mechanisms/svm/exact/facilitator.py @@ -131,7 +131,7 @@ def verify( - Token program is known (Token or Token-2022) - Mint matches requirements.asset - Destination ATA matches requirements.pay_to - - Amount >= requirements.amount + - Amount >= requirements.amount - Authority is not the facilitator (prevent self-transfer) - Simulates transaction to catch runtime errors diff --git a/python/x402/schemas/config.py b/python/x402/schemas/config.py index 22d22a6705..7aa14de12b 100644 --- a/python/x402/schemas/config.py +++ b/python/x402/schemas/config.py @@ -22,6 +22,7 @@ class ResourceConfig(BaseX402Model): price: Price network: Network max_timeout_seconds: int | None = None + extra: dict[str, Any] | None = None class FacilitatorConfig(TypedDict, total=False): diff --git a/python/x402/server_base.py b/python/x402/server_base.py index 75e06e4f13..150edc3377 100644 --- a/python/x402/server_base.py +++ b/python/x402/server_base.py @@ -325,7 +325,10 @@ def build_payment_requirements( amount=asset_amount.amount, pay_to=config.pay_to, max_timeout_seconds=config.max_timeout_seconds or 300, - extra=asset_amount.extra or {}, + extra={ + **(asset_amount.extra or {}), + **(config.extra or {}), + }, ) # Enhance with scheme-specific details diff --git a/python/x402/tests/integrations/test_http_integration.py b/python/x402/tests/integrations/test_http_integration.py index e0ef45e4a8..fcf26f6845 100644 --- a/python/x402/tests/integrations/test_http_integration.py +++ b/python/x402/tests/integrations/test_http_integration.py @@ -315,6 +315,46 @@ def create(routes: dict) -> HTTPComponentsFixture: return Factory # type: ignore + def test_route_option_extra_is_preserved( + self, + components_factory: Any, + ) -> None: + """Route-level extra should flow into built payment requirements.""" + routes = { + "GET /api/permit2": { + "accepts": { + "scheme": "cash", + "payTo": "merchant@example.com", + "price": "$0.10", + "network": "x402:cash", + "extra": { + "assetTransferMethod": "permit2", + "merchantNote": "route-level-extra", + }, + }, + }, + } + + components = components_factory.create(routes) + adapter = MockHTTPAdapter( + path="/api/permit2", + method="GET", + ) + context = HTTPRequestContext( + adapter=adapter, + path="/api/permit2", + method="GET", + ) + + result = components.process_http_request(context) + payment_required = decode_payment_required_header( + result.response.headers["PAYMENT-REQUIRED"] + ) + + assert payment_required.accepts[0].extra is not None + assert payment_required.accepts[0].extra["assetTransferMethod"] == "permit2" + assert payment_required.accepts[0].extra["merchantNote"] == "route-level-extra" + def test_dynamic_price_from_query_params( self, components_factory: Any, diff --git a/python/x402/tests/unit/core/test_server.py b/python/x402/tests/unit/core/test_server.py index 45dadadb54..400bc1f75f 100644 --- a/python/x402/tests/unit/core/test_server.py +++ b/python/x402/tests/unit/core/test_server.py @@ -4,6 +4,7 @@ from x402 import x402ResourceServer, x402ResourceServerSync from x402.schemas import ( + ResourceConfig, SettleResponse, SupportedKind, SupportedResponse, @@ -410,6 +411,64 @@ def enrich_declaration(self, declared, context): assert "test" in server._extensions +# ============================================================================= +# Build Requirements Tests +# ============================================================================= + + +class TestBuildPaymentRequirements: + """Tests for build_payment_requirements.""" + + def test_merges_resource_config_extra_with_parsed_price_extra(self): + """Merchant config extra should be preserved when requirements are built.""" + + class SchemeWithParsedExtra(MockSchemeServer): + def parse_price(self, price, network): + from dataclasses import dataclass + + @dataclass + class AssetAmount: + asset: str + amount: str + extra: dict | None = None + + return AssetAmount( + asset="0x0000000000000000000000000000000000000000", + amount="1000000", + extra={"parsed": "value"}, + ) + + kinds = [ + SupportedKind( + x402_version=2, + scheme="exact", + network="eip155:8453", + ) + ] + server = x402ResourceServerSync(MockFacilitatorClientSync(kinds)) + server.register("eip155:8453", SchemeWithParsedExtra("exact")) + server.initialize() + + requirements = server.build_payment_requirements( + ResourceConfig( + scheme="exact", + pay_to="0xmerchant", + price="$1.00", + network="eip155:8453", + extra={ + "assetTransferMethod": "permit2", + "merchantNote": "custom-scheme-data", + }, + ) + ) + + assert len(requirements) == 1 + assert requirements[0].extra is not None + assert requirements[0].extra.get("parsed") == "value" + assert requirements[0].extra.get("assetTransferMethod") == "permit2" + assert requirements[0].extra.get("merchantNote") == "custom-scheme-data" + + # ============================================================================= # Error Handling Tests # ============================================================================= diff --git a/python/x402/tests/unit/mechanisms/evm/test_facilitator.py b/python/x402/tests/unit/mechanisms/evm/test_facilitator.py index 6b40c3482c..be4bc71346 100644 --- a/python/x402/tests/unit/mechanisms/evm/test_facilitator.py +++ b/python/x402/tests/unit/mechanisms/evm/test_facilitator.py @@ -1,30 +1,220 @@ -"""Tests for ExactEvmScheme facilitator.""" - -from x402.mechanisms.evm import get_network_config +"""Tests for the exact EVM facilitator's simulation-based verification flow.""" + +from __future__ import annotations + +import time + +import pytest + +try: + from eth_abi import encode as abi_encode +except ImportError: + pytest.skip("eth-abi not available", allow_module_level=True) + +from x402.mechanisms.evm import ERC6492_MAGIC_VALUE, get_network_config +from x402.mechanisms.evm.constants import ( + ERR_AUTHORIZATION_VALUE_MISMATCH, + ERR_INSUFFICIENT_BALANCE, + ERR_INVALID_SIGNATURE, + ERR_NONCE_ALREADY_USED, + ERR_TOKEN_NAME_MISMATCH, + ERR_TOKEN_VERSION_MISMATCH, + ERR_TRANSACTION_SIMULATION_FAILED, + ERR_UNDEPLOYED_SMART_WALLET, +) from x402.mechanisms.evm.exact import ExactEvmFacilitatorScheme, ExactEvmSchemeConfig +from x402.mechanisms.evm.exact.v1.facilitator import ExactEvmSchemeV1 +from x402.mechanisms.evm.types import TransactionReceipt from x402.schemas import PaymentPayload, PaymentRequirements, ResourceInfo +from x402.schemas.v1 import PaymentPayloadV1, PaymentRequirementsV1 + +NETWORK = "eip155:8453" +TOKEN_ADDRESS = get_network_config(NETWORK)["default_asset"]["address"] +PAYER = "0x1234567890123456789012345678901234567890" +RECIPIENT = "0x0987654321098765432109876543210987654321" +FACILITATOR = "0x1111111111111111111111111111111111111111" +FACTORY = "0x2222222222222222222222222222222222222222" +NONCE = "0x" + "11" * 32 + + +def make_payment_payload( + *, + signature: str = "0x" + "00" * 65, + accepted_scheme: str = "exact", + accepted_network: str = NETWORK, + pay_to: str = RECIPIENT, + amount: str = "100000", + extra: dict | None = None, + authorization_overrides: dict | None = None, +) -> PaymentPayload: + now = int(time.time()) + authorization = { + "from": PAYER, + "to": RECIPIENT, + "value": amount, + "validAfter": str(now - 60), + "validBefore": str(now + 600), + "nonce": NONCE, + } + if authorization_overrides: + authorization.update(authorization_overrides) + + return PaymentPayload( + x402_version=2, + resource=ResourceInfo( + url="http://example.com/protected", + description="Test resource", + mime_type="application/json", + ), + accepted=PaymentRequirements( + scheme=accepted_scheme, + network=accepted_network, + asset=TOKEN_ADDRESS, + amount=amount, + pay_to=pay_to, + max_timeout_seconds=3600, + extra=extra if extra is not None else {"name": "USD Coin", "version": "2"}, + ), + payload={"authorization": authorization, "signature": signature}, + ) + + +def make_requirements( + *, + scheme: str = "exact", + network: str = NETWORK, + amount: str = "100000", + pay_to: str = RECIPIENT, + extra: dict | None = None, +) -> PaymentRequirements: + return PaymentRequirements( + scheme=scheme, + network=network, + asset=TOKEN_ADDRESS, + amount=amount, + pay_to=pay_to, + max_timeout_seconds=3600, + extra=extra if extra is not None else {"name": "USD Coin", "version": "2"}, + ) + + +def make_payment_payload_v1( + *, + signature: str = "0x" + "00" * 65, + scheme: str = "exact", + network: str = "base", + pay_to: str = RECIPIENT, + amount: str = "100000", + extra: dict | None = None, + authorization_overrides: dict | None = None, +) -> PaymentPayloadV1: + now = int(time.time()) + authorization = { + "from": PAYER, + "to": RECIPIENT, + "value": amount, + "validAfter": str(now - 60), + "validBefore": str(now + 600), + "nonce": NONCE, + } + if authorization_overrides: + authorization.update(authorization_overrides) + + return PaymentPayloadV1( + x402_version=1, + scheme=scheme, + network=network, + payload={"authorization": authorization, "signature": signature}, + ) + + +def make_requirements_v1( + *, + scheme: str = "exact", + network: str = "base", + amount: str = "100000", + pay_to: str = RECIPIENT, + extra: dict | None = None, +) -> PaymentRequirementsV1: + return PaymentRequirementsV1( + scheme=scheme, + network=network, + asset=TOKEN_ADDRESS, + max_amount_required=amount, + pay_to=pay_to, + max_timeout_seconds=3600, + resource="http://example.com/protected", + extra=extra if extra is not None else {"name": "USD Coin", "version": "2"}, + ) + + +def encode_result(abi_type: str, value): + return abi_encode([abi_type], [value]) + + +def make_diagnostic_results( + *, + balance: int = 100000, + name: str = "USD Coin", + version: str = "2", + nonce_used: bool = False, + authorization_state_supported: bool = True, +) -> list[tuple[bool, bytes]]: + return [ + (True, encode_result("uint256", balance)), + (True, encode_result("string", name)), + (True, encode_result("string", version)), + ( + authorization_state_supported, + encode_result("bool", nonce_used) if authorization_state_supported else b"", + ), + ] + + +def make_erc6492_signature(inner_signature: bytes) -> str: + payload = abi_encode( + ["address", "bytes", "bytes"], [FACTORY, b"\xde\xad\xbe\xef", inner_signature] + ) + return "0x" + (payload + ERC6492_MAGIC_VALUE).hex() class MockFacilitatorSigner: - """Mock facilitator signer for testing.""" + """Mock signer that exposes just enough behavior for facilitator tests.""" - def __init__(self, addresses: list[str] | None = None): - self._addresses = addresses or ["0xFacilitator123456789012345678901234567890"] + def __init__( + self, + *, + addresses: list[str] | None = None, + typed_data_valid: bool = True, + code: bytes = b"", + transfer_simulation_should_revert: bool = False, + multicall_results: list[tuple[bool, bytes]] | None = None, + deploy_tx_hash: str = "0x" + "12" * 32, + ): + self._addresses = addresses or [FACILITATOR] + self.typed_data_valid = typed_data_valid + self.code = code + self.transfer_simulation_should_revert = transfer_simulation_should_revert + self.multicall_results = multicall_results or [] + self.deploy_tx_hash = deploy_tx_hash + self.transfer_simulation_calls = 0 + self.write_calls = 0 + self.send_calls = 0 def get_addresses(self) -> list[str]: return self._addresses - def read_contract( - self, - address: str, - abi: list[dict], - function_name: str, - *args, - ) -> bool: - # Mock authorizationState - return False (nonce not used) - if function_name == "authorizationState": - return False - return False + def read_contract(self, address: str, abi: list[dict], function_name: str, *args): + if function_name == "tryAggregate": + return self.multicall_results + + if function_name == "transferWithAuthorization": + self.transfer_simulation_calls += 1 + if self.transfer_simulation_should_revert: + raise RuntimeError("simulation reverted") + return None + + raise AssertionError(f"unexpected read_contract call: {function_name}") def verify_typed_data( self, @@ -35,400 +225,323 @@ def verify_typed_data( message: dict, signature: bytes, ) -> bool: - # Mock verification - always return True for testing - return True + return self.typed_data_valid - def write_contract( - self, - address: str, - abi: list[dict], - function_name: str, - *args, - ) -> str: - return "0x" + "00" * 32 # Mock transaction hash + def write_contract(self, address: str, abi: list[dict], function_name: str, *args) -> str: + self.write_calls += 1 + return "0x" + "34" * 32 def send_transaction(self, to: str, data: bytes) -> str: - return "0x" + "00" * 32 - - def wait_for_transaction_receipt(self, tx_hash: str): - from x402.mechanisms.evm.types import TransactionReceipt + self.send_calls += 1 + return self.deploy_tx_hash + def wait_for_transaction_receipt(self, tx_hash: str) -> TransactionReceipt: return TransactionReceipt(status=1, block_number=1, tx_hash=tx_hash) def get_balance(self, address: str, token_address: str) -> int: - return 1000000000 # Mock balance + return 1_000_000_000 def get_chain_id(self) -> int: return 8453 def get_code(self, address: str) -> bytes: - return b"" # Mock EOA (no code) + return self.code class TestExactEvmSchemeConstructor: - """Test ExactEvmScheme facilitator constructor.""" - - def test_should_create_instance_with_correct_scheme(self): - """Should create instance with correct scheme.""" + def test_creates_instance_with_config(self): signer = MockFacilitatorSigner() - facilitator = ExactEvmFacilitatorScheme(signer) - - assert facilitator.scheme == "exact" + config = ExactEvmSchemeConfig( + deploy_erc4337_with_eip6492=True, + simulate_in_settle=True, + ) - def test_should_create_instance_with_config(self): - """Should create instance with config.""" - signer = MockFacilitatorSigner() - config = ExactEvmSchemeConfig(deploy_erc4337_with_eip6492=True) facilitator = ExactEvmFacilitatorScheme(signer, config) assert facilitator.scheme == "exact" assert facilitator._config.deploy_erc4337_with_eip6492 is True + assert facilitator._config.simulate_in_settle is True class TestVerify: - """Test verify method.""" - - def test_should_reject_if_scheme_does_not_match(self): - """Should reject if scheme does not match.""" + def test_rejects_wrong_scheme(self): signer = MockFacilitatorSigner() facilitator = ExactEvmFacilitatorScheme(signer) - network = "eip155:8453" - - payload = PaymentPayload( - x402_version=2, - resource=ResourceInfo( - url="http://example.com/protected", - description="Test resource", - mime_type="application/json", - ), - accepted=PaymentRequirements( - scheme="wrong", # Wrong scheme - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, - ), - payload={ - "authorization": { - "from": "0x1234567890123456789012345678901234567890", - "to": "0x0987654321098765432109876543210987654321", - "value": "100000", - "validAfter": "1000000000", - "validBefore": "1000003600", - "nonce": "0x" + "00" * 32, - }, - "signature": "0x" + "00" * 65, - }, - ) - requirements = PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, + result = facilitator.verify( + make_payment_payload(accepted_scheme="wrong"), + make_requirements(), ) - result = facilitator.verify(payload, requirements) - assert result.is_valid is False assert "unsupported_scheme" in result.invalid_reason - def test_should_reject_if_network_does_not_match(self): - """Should reject if network does not match.""" + def test_rejects_wrong_network(self): signer = MockFacilitatorSigner() facilitator = ExactEvmFacilitatorScheme(signer) - payload = PaymentPayload( - x402_version=2, - resource=ResourceInfo( - url="http://example.com/protected", - description="Test resource", - mime_type="application/json", - ), - accepted=PaymentRequirements( - scheme="exact", - network="eip155:1", # Ethereum Mainnet - asset="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, - ), - payload={ - "authorization": { - "from": "0x1234567890123456789012345678901234567890", - "to": "0x0987654321098765432109876543210987654321", - "value": "100000", - "validAfter": "1000000000", - "validBefore": "1000003600", - "nonce": "0x" + "00" * 32, - }, - "signature": "0x" + "00" * 65, - }, + result = facilitator.verify( + make_payment_payload(accepted_network="eip155:1"), + make_requirements(), ) - requirements = PaymentRequirements( - scheme="exact", - network="eip155:8453", # Base Mainnet - asset=get_network_config("eip155:8453")["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, - ) + assert result.is_valid is False + assert "network_mismatch" in result.invalid_reason + + def test_rejects_missing_eip712_domain(self): + signer = MockFacilitatorSigner() + facilitator = ExactEvmFacilitatorScheme(signer) - result = facilitator.verify(payload, requirements) + result = facilitator.verify( + make_payment_payload(extra={}), + make_requirements(extra={}), + ) - # Network check happens early assert result.is_valid is False - assert "network_mismatch" in result.invalid_reason + assert "missing_eip712_domain" in result.invalid_reason - def test_should_reject_if_eip712_domain_is_missing(self): - """Should reject if EIP-712 domain is missing.""" + def test_rejects_recipient_mismatch(self): signer = MockFacilitatorSigner() facilitator = ExactEvmFacilitatorScheme(signer) - network = "eip155:8453" - - payload = PaymentPayload( - x402_version=2, - resource=ResourceInfo( - url="http://example.com/protected", - description="Test resource", - mime_type="application/json", - ), - accepted=PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={}, # Missing EIP-712 domain + + result = facilitator.verify( + make_payment_payload( + authorization_overrides={"to": FACILITATOR}, + pay_to=RECIPIENT, ), - payload={ - "authorization": { - "from": "0x1234567890123456789012345678901234567890", - "to": "0x0987654321098765432109876543210987654321", - "value": "100000", - "validAfter": "1000000000", - "validBefore": "1000003600", - "nonce": "0x" + "00" * 32, - }, - "signature": "0x" + "00" * 65, - }, + make_requirements(), ) - requirements = PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={}, # Missing EIP-712 domain - ) + assert result.is_valid is False + assert "recipient_mismatch" in result.invalid_reason + + def test_rejects_amount_mismatch(self): + signer = MockFacilitatorSigner() + facilitator = ExactEvmFacilitatorScheme(signer) - result = facilitator.verify(payload, requirements) + result = facilitator.verify( + make_payment_payload(amount="50000"), + make_requirements(amount="100000"), + ) assert result.is_valid is False - assert "missing_eip712_domain" in result.invalid_reason + assert result.invalid_reason == ERR_AUTHORIZATION_VALUE_MISMATCH - def test_should_reject_if_recipient_does_not_match(self): - """Should reject if recipient does not match.""" + def test_rejects_overpayment_amount_mismatch(self): signer = MockFacilitatorSigner() facilitator = ExactEvmFacilitatorScheme(signer) - network = "eip155:8453" - - payload = PaymentPayload( - x402_version=2, - resource=ResourceInfo( - url="http://example.com/protected", - description="Test resource", - mime_type="application/json", - ), - accepted=PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, - ), - payload={ - "authorization": { - "from": "0x1234567890123456789012345678901234567890", - "to": "0xWrongRecipient1234567890123456789012345678", # Wrong recipient - "value": "100000", - "validAfter": "1000000000", - "validBefore": "1000003600", - "nonce": "0x" + "00" * 32, - }, - "signature": "0x" + "00" * 65, - }, + + result = facilitator.verify( + make_payment_payload(amount="150000"), + make_requirements(amount="100000"), ) - requirements = PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, + assert result.is_valid is False + assert result.invalid_reason == ERR_AUTHORIZATION_VALUE_MISMATCH + + def test_reports_name_mismatch_from_simulation_diagnostic(self): + signer = MockFacilitatorSigner( + typed_data_valid=False, + code=b"\x01", + transfer_simulation_should_revert=True, + multicall_results=make_diagnostic_results(name="Wrong Coin"), ) + facilitator = ExactEvmFacilitatorScheme(signer) - result = facilitator.verify(payload, requirements) + result = facilitator.verify( + make_payment_payload(signature="0x" + "22" * 66), + make_requirements(), + ) assert result.is_valid is False - assert "recipient_mismatch" in result.invalid_reason + assert result.invalid_reason == ERR_TOKEN_NAME_MISMATCH + + def test_reports_version_mismatch_from_simulation_diagnostic(self): + signer = MockFacilitatorSigner( + typed_data_valid=False, + code=b"\x01", + transfer_simulation_should_revert=True, + multicall_results=make_diagnostic_results(version="3"), + ) + facilitator = ExactEvmFacilitatorScheme(signer) - def test_should_reject_if_amount_is_insufficient(self): - """Should reject if amount is insufficient.""" - signer = MockFacilitatorSigner() + result = facilitator.verify( + make_payment_payload(signature="0x" + "22" * 66), + make_requirements(), + ) + + assert result.is_valid is False + assert result.invalid_reason == ERR_TOKEN_VERSION_MISMATCH + + def test_deployed_erc1271_falls_back_to_simulation(self): + signer = MockFacilitatorSigner( + typed_data_valid=False, + code=b"\x01", + ) facilitator = ExactEvmFacilitatorScheme(signer) - network = "eip155:8453" - - payload = PaymentPayload( - x402_version=2, - resource=ResourceInfo( - url="http://example.com/protected", - description="Test resource", - mime_type="application/json", - ), - accepted=PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, - ), - payload={ - "authorization": { - "from": "0x1234567890123456789012345678901234567890", - "to": "0x0987654321098765432109876543210987654321", - "value": "50000", # Less than required - "validAfter": "1000000000", - "validBefore": "1000003600", - "nonce": "0x" + "00" * 32, - }, - "signature": "0x" + "00" * 65, - }, + + result = facilitator.verify( + make_payment_payload(signature="0x" + "22" * 66), + make_requirements(), ) - requirements = PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, + assert result.is_valid is True + assert result.payer == PAYER + assert signer.transfer_simulation_calls == 1 + + def test_undeployed_erc6492_passes_when_deploy_and_transfer_simulate(self): + signer = MockFacilitatorSigner( + typed_data_valid=False, + code=b"", + multicall_results=[(True, b""), (True, b"")], + ) + facilitator = ExactEvmFacilitatorScheme(signer) + + result = facilitator.verify( + make_payment_payload(signature=make_erc6492_signature(b"\x33" * 66)), + make_requirements(), + ) + + assert result.is_valid is True + assert result.payer == PAYER + + def test_undeployed_erc6492_rejects_when_simulation_fails(self): + signer = MockFacilitatorSigner( + typed_data_valid=False, + code=b"", + multicall_results=[(True, b""), (False, b"")], ) + facilitator = ExactEvmFacilitatorScheme(signer) - result = facilitator.verify(payload, requirements) + result = facilitator.verify( + make_payment_payload(signature=make_erc6492_signature(b"\x33" * 66)), + make_requirements(), + ) assert result.is_valid is False - assert "authorization_value" in result.invalid_reason + assert result.invalid_reason == ERR_TRANSACTION_SIMULATION_FAILED + def test_undeployed_smart_wallet_without_deployment_info_is_rejected(self): + signer = MockFacilitatorSigner(typed_data_valid=False, code=b"") + facilitator = ExactEvmFacilitatorScheme(signer) -class TestSettle: - """Test settle method.""" + result = facilitator.verify( + make_payment_payload(signature="0x" + "22" * 66), + make_requirements(), + ) - def test_should_fail_settlement_if_verification_fails(self): - """Should fail settlement if verification fails.""" - signer = MockFacilitatorSigner() + assert result.is_valid is False + assert result.invalid_reason == ERR_UNDEPLOYED_SMART_WALLET + + def test_reports_nonce_used_from_simulation_diagnostic(self): + signer = MockFacilitatorSigner( + typed_data_valid=False, + code=b"\x01", + transfer_simulation_should_revert=True, + multicall_results=make_diagnostic_results(nonce_used=True), + ) facilitator = ExactEvmFacilitatorScheme(signer) - network = "eip155:8453" - - payload = PaymentPayload( - x402_version=2, - resource=ResourceInfo( - url="http://example.com/protected", - description="Test resource", - mime_type="application/json", - ), - accepted=PaymentRequirements( - scheme="wrong", # Wrong scheme - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, - ), - payload={ - "authorization": { - "from": "0x1234567890123456789012345678901234567890", - "to": "0x0987654321098765432109876543210987654321", - "value": "100000", - "validAfter": "1000000000", - "validBefore": "1000003600", - "nonce": "0x" + "00" * 32, - }, - "signature": "0x" + "00" * 65, - }, + + result = facilitator.verify( + make_payment_payload(signature="0x" + "22" * 66), + make_requirements(), ) - requirements = PaymentRequirements( - scheme="exact", - network=network, - asset=get_network_config(network)["default_asset"]["address"], - amount="100000", - pay_to="0x0987654321098765432109876543210987654321", - max_timeout_seconds=3600, - extra={"name": "USD Coin", "version": "2"}, + assert result.is_valid is False + assert result.invalid_reason == ERR_NONCE_ALREADY_USED + + def test_reports_insufficient_balance_from_simulation_diagnostic(self): + signer = MockFacilitatorSigner( + typed_data_valid=False, + code=b"\x01", + transfer_simulation_should_revert=True, + multicall_results=make_diagnostic_results(balance=1), + ) + facilitator = ExactEvmFacilitatorScheme(signer) + + result = facilitator.verify( + make_payment_payload(signature="0x" + "22" * 66), + make_requirements(amount="100000"), + ) + + assert result.is_valid is False + assert result.invalid_reason == ERR_INSUFFICIENT_BALANCE + + def test_eoa_invalid_signature_is_rejected_immediately(self): + signer = MockFacilitatorSigner(typed_data_valid=False, code=b"") + facilitator = ExactEvmFacilitatorScheme(signer) + + result = facilitator.verify( + make_payment_payload(signature="0x" + "00" * 65), + make_requirements(), ) - result = facilitator.settle(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_INVALID_SIGNATURE + + +class TestSettle: + def test_fails_settlement_if_verification_fails(self): + signer = MockFacilitatorSigner() + facilitator = ExactEvmFacilitatorScheme(signer) + + result = facilitator.settle( + make_payment_payload(accepted_scheme="wrong"), + make_requirements(), + ) assert result.success is False assert "unsupported_scheme" in result.error_reason - assert result.network == network + assert result.network == NETWORK + + def test_can_rerun_simulation_during_settle(self): + signer = MockFacilitatorSigner(typed_data_valid=True) + facilitator = ExactEvmFacilitatorScheme( + signer, + ExactEvmSchemeConfig(simulate_in_settle=True), + ) + result = facilitator.settle( + make_payment_payload(signature="0x" + "00" * 65), + make_requirements(), + ) -class TestFacilitatorSchemeAttributes: - """Test facilitator scheme attributes.""" + assert result.success is True + assert signer.transfer_simulation_calls == 1 + assert signer.write_calls == 1 - def test_scheme_attribute_is_exact(self): - """scheme attribute should be 'exact'.""" + +class TestVerifyV1: + def test_rejects_overpayment_amount_mismatch(self): signer = MockFacilitatorSigner() - facilitator = ExactEvmFacilitatorScheme(signer) + facilitator = ExactEvmSchemeV1(signer) + + result = facilitator.verify( + make_payment_payload_v1(amount="150000"), + make_requirements_v1(amount="100000"), + ) + assert result.is_valid is False + assert result.invalid_reason == ERR_AUTHORIZATION_VALUE_MISMATCH + + +class TestFacilitatorSchemeAttributes: + def test_scheme_attribute_is_exact(self): + facilitator = ExactEvmFacilitatorScheme(MockFacilitatorSigner()) assert facilitator.scheme == "exact" def test_caip_family_attribute(self): - """caip_family attribute should be 'eip155:*'.""" - signer = MockFacilitatorSigner() - facilitator = ExactEvmFacilitatorScheme(signer) - + facilitator = ExactEvmFacilitatorScheme(MockFacilitatorSigner()) assert facilitator.caip_family == "eip155:*" def test_get_extra_returns_none(self): - """get_extra should return None for EVM.""" - signer = MockFacilitatorSigner() - facilitator = ExactEvmFacilitatorScheme(signer) - - extra = facilitator.get_extra("eip155:8453") - - assert extra is None + facilitator = ExactEvmFacilitatorScheme(MockFacilitatorSigner()) + assert facilitator.get_extra(NETWORK) is None def test_get_signers_returns_signer_addresses(self): - """get_signers should return list of signer addresses.""" addresses = [ - "0xSigner1111111111111111111111111111111111111111", - "0xSigner2222222222222222222222222222222222222222", + "0x1111111111111111111111111111111111111111", + "0x2222222222222222222222222222222222222222", ] - signer = MockFacilitatorSigner(addresses) - facilitator = ExactEvmFacilitatorScheme(signer) - - result = facilitator.get_signers("eip155:8453") - - assert result == addresses + facilitator = ExactEvmFacilitatorScheme(MockFacilitatorSigner(addresses=addresses)) + assert facilitator.get_signers(NETWORK) == addresses diff --git a/python/x402/tests/unit/mechanisms/evm/test_verify.py b/python/x402/tests/unit/mechanisms/evm/test_verify.py new file mode 100644 index 0000000000..b0fe6c3eb8 --- /dev/null +++ b/python/x402/tests/unit/mechanisms/evm/test_verify.py @@ -0,0 +1,93 @@ +"""Tests for universal signature verification helpers.""" + +import pytest + +try: + from eth_abi import encode as eth_abi_encode +except ImportError: + pytest.skip("eth-abi not available", allow_module_level=True) + +from x402.mechanisms.evm.verify import verify_universal_signature + +# ERC-6492 magic bytes suffix +ERC6492_MAGIC = bytes.fromhex("6492649264926492649264926492649264926492649264926492649264926492") + + +def make_erc6492_sig(factory: bytes, calldata: bytes, inner_sig: bytes) -> bytes: + """Build a valid ERC-6492 wrapped signature for testing. + + Format: abi.encode(address, bytes, bytes) + magic + """ + encoded = eth_abi_encode(["address", "bytes", "bytes"], [factory, calldata, inner_sig]) + return encoded + ERC6492_MAGIC + + +FACTORY_ADDR = bytes.fromhex("1111111111111111111111111111111111111111") +FACTORY_CALLDATA = bytes.fromhex("deadbeef") +GARBAGE_INNER_SIG = b"\x00" * 65 # All-zero 65-byte "signature" β€” forged/invalid +WALLET_ADDRESS = "0x1234567890123456789012345678901234567890" +TEST_HASH = b"\x01" * 32 + + +class MockFacilitatorSigner: + """Minimal mock facilitator signer for verify tests.""" + + def __init__(self, read_contract_result=None, read_contract_raises=None, code=b""): + self._read_contract_result = read_contract_result + self._read_contract_raises = read_contract_raises + self._code = code + + def get_code(self, address: str) -> bytes: + return self._code + + def read_contract(self, address, abi, function_name, *args): + if self._read_contract_raises is not None: + raise self._read_contract_raises + return self._read_contract_result + + +class TestVerifyUniversalSignature: + """Generic verification should stay generic and not perform EIP-3009 simulation.""" + + def test_allow_undeployed_true_accepts_erc6492_wrapper(self): + erc6492_sig = make_erc6492_sig(FACTORY_ADDR, FACTORY_CALLDATA, GARBAGE_INNER_SIG) + signer = MockFacilitatorSigner( + code=b"", + ) + + valid, sig_data = verify_universal_signature( + signer, + WALLET_ADDRESS, + TEST_HASH, + erc6492_sig, + allow_undeployed=True, + ) + + assert valid is True + assert sig_data.factory == FACTORY_ADDR + + def test_allow_undeployed_false_raises(self): + erc6492_sig = make_erc6492_sig(FACTORY_ADDR, FACTORY_CALLDATA, GARBAGE_INNER_SIG) + signer = MockFacilitatorSigner( + code=b"", + ) + + with pytest.raises(ValueError, match="not allowed"): + verify_universal_signature( + signer, + WALLET_ADDRESS, + TEST_HASH, + erc6492_sig, + allow_undeployed=False, + ) + + def test_non_erc6492_non_eoa_signature_returns_false_for_undeployed_wallet(self): + signer = MockFacilitatorSigner(code=b"") + valid, _ = verify_universal_signature( + signer, + WALLET_ADDRESS, + TEST_HASH, + b"\x99" * 66, + allow_undeployed=True, + ) + assert valid is False diff --git a/typescript/.changeset/slimy-baths-marry.md b/typescript/.changeset/slimy-baths-marry.md new file mode 100644 index 0000000000..f62e5261e2 --- /dev/null +++ b/typescript/.changeset/slimy-baths-marry.md @@ -0,0 +1,5 @@ +--- +'@x402/evm': patch +--- + +Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling to prevent facilitator grieving and account for implementation dependent verifyTypedData diff --git a/typescript/package.json b/typescript/package.json index 602ca6fca1..8612926dc2 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -21,7 +21,7 @@ "lint:check": "turbo run lint:check", "format:check": "turbo run format:check", "test": "turbo run test", - "test:integration": "pnpm --filter @x402/core --filter @x402/evm --filter @x402/svm --filter @x402/aptos test:integration", + "test:integration": "pnpm --filter @x402/core --filter @x402/evm --filter @x402/svm --filter @x402/aptos --filter @x402/stellar test:integration", "test:all": "pnpm test && pnpm test:integration" }, "keywords": [], @@ -34,4 +34,4 @@ "@changesets/cli": "^2.28.1", "@changesets/changelog-github": "^0.5.1" } -} +} \ No newline at end of file diff --git a/typescript/packages/mechanisms/evm/src/constants.ts b/typescript/packages/mechanisms/evm/src/constants.ts index 55bd23f8d1..bc18ea067d 100644 --- a/typescript/packages/mechanisms/evm/src/constants.ts +++ b/typescript/packages/mechanisms/evm/src/constants.ts @@ -81,6 +81,23 @@ export const eip3009ABI = [ stateMutability: "view", type: "function", }, + { + inputs: [], + name: "name", + outputs: [{ name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { name: "authorizer", type: "address" }, + { name: "nonce", type: "bytes32" }, + ], + name: "authorizationState", + outputs: [{ name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, ] as const; /** diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009-utils.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009-utils.ts new file mode 100644 index 0000000000..2d8f2c4a69 --- /dev/null +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009-utils.ts @@ -0,0 +1,240 @@ +import { PaymentRequirements, VerifyResponse } from "@x402/core/types"; +import { encodeFunctionData, getAddress, Hex, parseErc6492Signature, parseSignature } from "viem"; +import { eip3009ABI } from "../../constants"; +import { multicall, ContractCall, RawContractCall } from "../../multicall"; +import { FacilitatorEvmSigner } from "../../signer"; +import { ExactEIP3009Payload } from "../../types"; +import * as Errors from "./errors"; + +export interface Eip6492Deployment { + factoryAddress: `0x${string}`; + factoryCalldata: `0x${string}`; +} + +/** + * Simulates transferWithAuthorization via eth_call. + * Returns true if simulation succeeded, false if it failed. + * + * @param signer - EVM signer for contract reads + * @param erc20Address - ERC-20 token contract address + * @param payload - EIP-3009 transfer authorization payload + * @param eip6492Deployment - Optional EIP-6492 factory info for undeployed smart wallets + * + * @returns true if simulation succeeded, false if it failed + */ +export async function simulateEip3009Transfer( + signer: FacilitatorEvmSigner, + erc20Address: `0x${string}`, + payload: ExactEIP3009Payload, + eip6492Deployment?: Eip6492Deployment, +): Promise { + const auth = payload.authorization; + const transferArgs = [ + getAddress(auth.from), + getAddress(auth.to), + BigInt(auth.value), + BigInt(auth.validAfter), + BigInt(auth.validBefore), + auth.nonce, + ] as const; + + if (eip6492Deployment) { + const { signature: innerSignature } = parseErc6492Signature(payload.signature!); + const transferCalldata = encodeFunctionData({ + abi: eip3009ABI, + functionName: "transferWithAuthorization", + args: [...transferArgs, innerSignature], + }); + + try { + const results = await multicall(signer.readContract.bind(signer), [ + { + address: getAddress(eip6492Deployment.factoryAddress), + callData: eip6492Deployment.factoryCalldata, + } satisfies RawContractCall, + { + address: erc20Address, + callData: transferCalldata, + } satisfies RawContractCall, + ]); + + return results[1]?.status === "success"; + } catch { + return false; + } + } + + const sig = payload.signature!; + const sigLength = sig.startsWith("0x") ? sig.length - 2 : sig.length; + const isECDSA = sigLength === 130; + + try { + if (isECDSA) { + const parsedSig = parseSignature(sig); + await signer.readContract({ + address: erc20Address, + abi: eip3009ABI, + functionName: "transferWithAuthorization", + args: [ + ...transferArgs, + (parsedSig.v as number | undefined) ?? parsedSig.yParity, + parsedSig.r, + parsedSig.s, + ], + }); + } else { + await signer.readContract({ + address: erc20Address, + abi: eip3009ABI, + functionName: "transferWithAuthorization", + args: [...transferArgs, sig], + }); + } + return true; + } catch { + return false; + } +} + +/** + * After simulation fails, runs a single diagnostic multicall to determine the most specific error reason. + * Checks balanceOf, name, version and authorizationState in one RPC round-trip. + * + * @param signer - EVM signer used for the payment + * @param erc20Address - Address of the ERC-20 token contract + * @param payload - The EIP-3009 transfer authorization payload + * @param requirements - Payment requirements to validate against + * @param amountRequired - Required amount for the payment (balance check) + * + * @returns Promise resolving to the verification result with validity and optional invalid reason + */ +export async function diagnoseEip3009SimulationFailure( + signer: FacilitatorEvmSigner, + erc20Address: `0x${string}`, + payload: ExactEIP3009Payload, + requirements: PaymentRequirements, + amountRequired: string, +): Promise { + const payer = payload.authorization.from; + + const diagnosticCalls: ContractCall[] = [ + { + address: erc20Address, + abi: eip3009ABI, + functionName: "balanceOf", + args: [payload.authorization.from], + }, + { + address: erc20Address, + abi: eip3009ABI, + functionName: "name", + }, + { + address: erc20Address, + abi: eip3009ABI, + functionName: "version", + }, + { + address: erc20Address, + abi: eip3009ABI, + functionName: "authorizationState", + args: [payload.authorization.from, payload.authorization.nonce], + }, + ]; + + try { + const results = await multicall(signer.readContract.bind(signer), diagnosticCalls); + + const [balanceResult, nameResult, versionResult, authStateResult] = results; + + if (authStateResult.status === "failure") { + return { isValid: false, invalidReason: Errors.ErrEip3009NotSupported, payer }; + } + + if (authStateResult.status === "success" && authStateResult.result === true) { + return { isValid: false, invalidReason: Errors.ErrEip3009NonceAlreadyUsed, payer }; + } + + if ( + nameResult.status === "success" && + requirements.extra?.name && + nameResult.result !== requirements.extra.name + ) { + return { isValid: false, invalidReason: Errors.ErrEip3009TokenNameMismatch, payer }; + } + + if ( + versionResult.status === "success" && + requirements.extra?.version && + versionResult.result !== requirements.extra.version + ) { + return { isValid: false, invalidReason: Errors.ErrEip3009TokenVersionMismatch, payer }; + } + + if (balanceResult.status === "success") { + const balance = balanceResult.result as bigint; + if (balance < BigInt(amountRequired)) { + return { + isValid: false, + invalidReason: Errors.ErrEip3009InsufficientBalance, + payer, + }; + } + } + } catch { + // Diagnostic multicall failed β€” fall through to generic error + } + + return { isValid: false, invalidReason: Errors.ErrEip3009SimulationFailed, payer }; +} + +/** + * Executes transferWithAuthorization onchain. + * + * @param signer - EVM signer for contract writes + * @param erc20Address - ERC-20 token contract address + * @param payload - EIP-3009 transfer authorization payload + * + * @returns Transaction hash + */ +export async function executeTransferWithAuthorization( + signer: FacilitatorEvmSigner, + erc20Address: `0x${string}`, + payload: ExactEIP3009Payload, +): Promise { + const { signature } = parseErc6492Signature(payload.signature!); + const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; + const isECDSA = signatureLength === 130; + + const auth = payload.authorization; + const baseArgs = [ + getAddress(auth.from), + getAddress(auth.to), + BigInt(auth.value), + BigInt(auth.validAfter), + BigInt(auth.validBefore), + auth.nonce, + ] as const; + + if (isECDSA) { + const parsedSig = parseSignature(signature); + return signer.writeContract({ + address: erc20Address, + abi: eip3009ABI, + functionName: "transferWithAuthorization", + args: [ + ...baseArgs, + (parsedSig.v as number | undefined) || parsedSig.yParity, + parsedSig.r, + parsedSig.s, + ], + }); + } + + return signer.writeContract({ + address: erc20Address, + abi: eip3009ABI, + functionName: "transferWithAuthorization", + args: [...baseArgs, signature], + }); +} diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts index bbe26de00f..69056a938b 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/eip3009.ts @@ -4,11 +4,22 @@ import { SettleResponse, VerifyResponse, } from "@x402/core/types"; -import { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from "viem"; -import { authorizationTypes, eip3009ABI } from "../../constants"; +import { getAddress, Hex, isAddressEqual, parseErc6492Signature } from "viem"; +import { authorizationTypes } from "../../constants"; import { FacilitatorEvmSigner } from "../../signer"; import { getEvmChainId } from "../../utils"; import { ExactEIP3009Payload } from "../../types"; +import * as Errors from "./errors"; +import { + diagnoseEip3009SimulationFailure, + executeTransferWithAuthorization, + simulateEip3009Transfer, +} from "./eip3009-utils"; + +export interface VerifyEIP3009Options { + /** Run onchain simulation. Defaults to true. */ + simulate?: boolean; +} export interface EIP3009FacilitatorConfig { /** @@ -18,6 +29,12 @@ export interface EIP3009FacilitatorConfig { * @default false */ deployERC4337WithEIP6492: boolean; + /** + * If enabled, simulates transaction before settling. Defaults to false, ie only simulate during verify. + * + * @default false + */ + simulateInSettle?: boolean; } /** @@ -27,6 +44,7 @@ export interface EIP3009FacilitatorConfig { * @param payload - The payment payload to verify * @param requirements - The payment requirements * @param eip3009Payload - The EIP-3009 specific payload + * @param options - Optional verification options * @returns Promise resolving to verification response */ export async function verifyEIP3009( @@ -34,14 +52,18 @@ export async function verifyEIP3009( payload: PaymentPayload, requirements: PaymentRequirements, eip3009Payload: ExactEIP3009Payload, + options?: VerifyEIP3009Options, ): Promise { const payer = eip3009Payload.authorization.from; + let eip6492Deployment: + | { factoryAddress: `0x${string}`; factoryCalldata: `0x${string}` } + | undefined; // Verify scheme matches if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { return { isValid: false, - invalidReason: "unsupported_scheme", + invalidReason: Errors.ErrInvalidScheme, payer, }; } @@ -50,7 +72,7 @@ export async function verifyEIP3009( if (!requirements.extra?.name || !requirements.extra?.version) { return { isValid: false, - invalidReason: "missing_eip712_domain", + invalidReason: Errors.ErrMissingEip712Domain, payer, }; } @@ -62,7 +84,7 @@ export async function verifyEIP3009( if (payload.accepted.network !== requirements.network) { return { isValid: false, - invalidReason: "network_mismatch", + invalidReason: Errors.ErrNetworkMismatch, payer, }; } @@ -88,71 +110,70 @@ export async function verifyEIP3009( }; // Verify signature + // Note: verifyTypedData is implementation-dependent and pluggable on FacilitatorEvmSigner + // Some implementations only do EOA-style ECDSA recovery (e.g. viem/utils verifyTypedData, ethers.verifyTypedData) + // Viem's publicClient.verifyTypedData supports EOA and Smart Contract Account (ERC-1271 / ERC-6492) signature verification + let isValid = false; try { - const recoveredAddress = await signer.verifyTypedData({ + isValid = await signer.verifyTypedData({ address: eip3009Payload.authorization.from, ...permitTypedData, signature: eip3009Payload.signature!, }); + } catch { + isValid = false; + } + const signature = eip3009Payload.signature!; + const sigLen = signature.startsWith("0x") ? signature.length - 2 : signature.length; - if (!recoveredAddress) { + // Extract EIP-6492 deployment info (factory address + calldata) if present + const erc6492Data = parseErc6492Signature(signature); + const hasDeploymentInfo = + erc6492Data.address && + erc6492Data.data && + !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000"); + + if (hasDeploymentInfo) { + eip6492Deployment = { + factoryAddress: erc6492Data.address!, + factoryCalldata: erc6492Data.data!, + }; + } + + if (!isValid) { + // Check if signature is from a smart wallet + const isSmartWallet = sigLen > 130; // 65 bytes = 130 hex chars for EOA + + // EOA signature that failed verification β€” definitely invalid + if (!isSmartWallet) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_signature", + invalidReason: Errors.ErrInvalidSignature, payer, }; } - } catch { - // Signature verification failed - could be an undeployed smart wallet - // Check if smart wallet is deployed - const signature = eip3009Payload.signature!; - const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; - const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA - if (isSmartWallet) { - const payerAddress = eip3009Payload.authorization.from; - const bytecode = await signer.getCode({ address: payerAddress }); - - if (!bytecode || bytecode === "0x") { - // Wallet is not deployed. Check if it's EIP-6492 with deployment info. - const erc6492Data = parseErc6492Signature(signature); - const hasDeploymentInfo = - erc6492Data.address && - erc6492Data.data && - !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000"); + // Smart wallet signature: check if deployed or has ERC-6492 deployment info + const bytecode = await signer.getCode({ address: payer }); + const isDeployed = bytecode && bytecode !== "0x"; - if (!hasDeploymentInfo) { - // Non-EIP-6492 undeployed smart wallet - will always fail at settlement - return { - isValid: false, - invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet", - payer: payerAddress, - }; - } - // EIP-6492 signature with deployment info - allow through - } else { - // Wallet is deployed but signature still failed - invalid signature - return { - isValid: false, - invalidReason: "invalid_exact_evm_payload_signature", - payer, - }; - } - } else { - // EOA signature failed + if (!isDeployed && !hasDeploymentInfo) { + // Undeployed smart wallet with no factory info return { isValid: false, - invalidReason: "invalid_exact_evm_payload_signature", + invalidReason: Errors.ErrUndeployedSmartWallet, payer, }; } + // Deployed smart wallet or undeployed with ERC-6492 factory info + // fall through to remaining field checks and onchain simulation } // Verify payment recipient matches if (getAddress(eip3009Payload.authorization.to) !== getAddress(requirements.payTo)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_recipient_mismatch", + invalidReason: Errors.ErrRecipientMismatch, payer, }; } @@ -162,7 +183,7 @@ export async function verifyEIP3009( if (BigInt(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_valid_before", + invalidReason: Errors.ErrValidBeforeExpired, payer, }; } @@ -171,41 +192,39 @@ export async function verifyEIP3009( if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_valid_after", + invalidReason: Errors.ErrValidAfterInFuture, payer, }; } - // Check balance - try { - const balance = (await signer.readContract({ - address: erc20Address, - abi: eip3009ABI, - functionName: "balanceOf", - args: [eip3009Payload.authorization.from], - })) as bigint; - - if (BigInt(balance) < BigInt(requirements.amount)) { - return { - isValid: false, - invalidReason: "insufficient_funds", - invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`, - payer, - }; - } - } catch { - // If we can't check balance, continue with other validations - } - // Verify amount exactly matches requirements if (BigInt(eip3009Payload.authorization.value) !== BigInt(requirements.amount)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_value_mismatch", + invalidReason: Errors.ErrInvalidAuthorizationValue, payer, }; } + // Transaction simulation + if (options?.simulate !== false) { + const simulationSucceeded = await simulateEip3009Transfer( + signer, + erc20Address, + eip3009Payload, + eip6492Deployment, + ); + if (!simulationSucceeded) { + return diagnoseEip3009SimulationFailure( + signer, + erc20Address, + eip3009Payload, + requirements, + requirements.amount, + ); + } + } + return { isValid: true, invalidReason: undefined, @@ -233,21 +252,24 @@ export async function settleEIP3009( const payer = eip3009Payload.authorization.from; // Re-verify before settling - const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload); + const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload, { + simulate: config.simulateInSettle ?? false, + }); if (!valid.isValid) { return { success: false, network: payload.accepted.network, transaction: "", - errorReason: valid.invalidReason ?? "invalid_scheme", + errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme, payer, }; } try { - // Parse ERC-6492 signature if applicable - const parseResult = parseErc6492Signature(eip3009Payload.signature!); - const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; + // Parse ERC-6492 signature if applicable (for optional deployment) + const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature( + eip3009Payload.signature!, + ); // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed if ( @@ -271,48 +293,11 @@ export async function settleEIP3009( } } - // Determine if this is an ECDSA signature (EOA) or smart wallet signature - const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; - const isECDSA = signatureLength === 130; - - let tx: Hex; - if (isECDSA) { - // For EOA wallets, parse signature into v, r, s and use that overload - const parsedSig = parseSignature(signature); - - tx = await signer.writeContract({ - address: getAddress(requirements.asset), - abi: eip3009ABI, - functionName: "transferWithAuthorization", - args: [ - getAddress(eip3009Payload.authorization.from), - getAddress(eip3009Payload.authorization.to), - BigInt(eip3009Payload.authorization.value), - BigInt(eip3009Payload.authorization.validAfter), - BigInt(eip3009Payload.authorization.validBefore), - eip3009Payload.authorization.nonce, - (parsedSig.v as number | undefined) || parsedSig.yParity, - parsedSig.r, - parsedSig.s, - ], - }); - } else { - // For smart wallets, use the bytes signature overload - tx = await signer.writeContract({ - address: getAddress(requirements.asset), - abi: eip3009ABI, - functionName: "transferWithAuthorization", - args: [ - getAddress(eip3009Payload.authorization.from), - getAddress(eip3009Payload.authorization.to), - BigInt(eip3009Payload.authorization.value), - BigInt(eip3009Payload.authorization.validAfter), - BigInt(eip3009Payload.authorization.validBefore), - eip3009Payload.authorization.nonce, - signature, - ], - }); - } + const tx = await executeTransferWithAuthorization( + signer, + getAddress(requirements.asset), + eip3009Payload, + ); // Wait for transaction confirmation const receipt = await signer.waitForTransactionReceipt({ hash: tx }); @@ -320,7 +305,7 @@ export async function settleEIP3009( if (receipt.status !== "success") { return { success: false, - errorReason: "invalid_transaction_state", + errorReason: Errors.ErrTransactionFailed, transaction: tx, network: payload.accepted.network, payer, @@ -336,7 +321,7 @@ export async function settleEIP3009( } catch { return { success: false, - errorReason: "transaction_failed", + errorReason: Errors.ErrTransactionFailed, transaction: "", network: payload.accepted.network, payer, diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts index 4a22fc4316..e3d1f25dec 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts @@ -5,9 +5,24 @@ * go/mechanisms/evm/exact/facilitator/errors.go to maintain cross-SDK parity. */ -// EIP-3009 verify errors export const ErrInvalidScheme = "invalid_exact_evm_scheme"; export const ErrNetworkMismatch = "invalid_exact_evm_network_mismatch"; +export const ErrMissingEip712Domain = "invalid_exact_evm_missing_eip712_domain"; +export const ErrRecipientMismatch = "invalid_exact_evm_recipient_mismatch"; +export const ErrInvalidSignature = "invalid_exact_evm_signature"; +export const ErrValidBeforeExpired = "invalid_exact_evm_payload_authorization_valid_before"; +export const ErrValidAfterInFuture = "invalid_exact_evm_payload_authorization_valid_after"; +export const ErrInvalidAuthorizationValue = "invalid_exact_evm_authorization_value"; +export const ErrUndeployedSmartWallet = "invalid_exact_evm_payload_undeployed_smart_wallet"; +export const ErrTransactionFailed = "invalid_exact_evm_transaction_failed"; + +// EIP-3009 verify errors +export const ErrEip3009TokenNameMismatch = "invalid_exact_evm_token_name_mismatch"; +export const ErrEip3009TokenVersionMismatch = "invalid_exact_evm_token_version_mismatch"; +export const ErrEip3009NotSupported = "invalid_exact_evm_eip3009_not_supported"; +export const ErrEip3009NonceAlreadyUsed = "invalid_exact_evm_nonce_already_used"; +export const ErrEip3009InsufficientBalance = "invalid_exact_evm_insufficient_balance"; +export const ErrEip3009SimulationFailed = "invalid_exact_evm_transaction_simulation_failed"; // Permit2 verify errors export const ErrPermit2InvalidSpender = "invalid_permit2_spender"; diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/register.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/register.ts index 61224d7a0d..9ab056175d 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/register.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/register.ts @@ -27,6 +27,13 @@ export interface EvmFacilitatorConfig { * @default false */ deployERC4337WithEIP6492?: boolean; + + /** + * If enabled, reruns on-chain simulation during settle's re-verify. + * + * @default false + */ + simulateInSettle?: boolean; } /** @@ -70,6 +77,7 @@ export function registerExactEvmScheme( config.networks, new ExactEvmScheme(config.signer, { deployERC4337WithEIP6492: config.deployERC4337WithEIP6492, + simulateInSettle: config.simulateInSettle, }), ); @@ -78,6 +86,7 @@ export function registerExactEvmScheme( NETWORKS as Network[], new ExactEvmSchemeV1(config.signer, { deployERC4337WithEIP6492: config.deployERC4337WithEIP6492, + simulateInSettle: config.simulateInSettle, }), ); diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts index e44c338695..833743e760 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts @@ -19,6 +19,12 @@ export interface ExactEvmSchemeConfig { * @default false */ deployERC4337WithEIP6492?: boolean; + /** + * If enabled, run on-chain simulation during settle's re-verify. + * + * @default false + */ + simulateInSettle?: boolean; } /** @@ -44,6 +50,7 @@ export class ExactEvmScheme implements SchemeNetworkFacilitator { ) { this.config = { deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false, + simulateInSettle: config?.simulateInSettle ?? false, }; } diff --git a/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts b/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts index 0abfc8d9a7..381aa8ca2f 100644 --- a/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/evm/src/exact/v1/facilitator/scheme.ts @@ -7,11 +7,22 @@ import { VerifyResponse, } from "@x402/core/types"; import { PaymentRequirementsV1 } from "@x402/core/types/v1"; -import { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from "viem"; -import { authorizationTypes, eip3009ABI } from "../../../constants"; +import { getAddress, Hex, isAddressEqual, parseErc6492Signature } from "viem"; +import { authorizationTypes } from "../../../constants"; import { FacilitatorEvmSigner } from "../../../signer"; import { ExactEvmPayloadV1 } from "../../../types"; import { EvmNetworkV1, getEvmChainIdV1 } from "../../../v1"; +import * as Errors from "../../facilitator/errors"; +import { + diagnoseEip3009SimulationFailure, + executeTransferWithAuthorization, + simulateEip3009Transfer, +} from "../../facilitator/eip3009-utils"; + +export interface VerifyV1Options { + /** Run onchain simulation. Defaults to true. */ + simulate?: boolean; +} export interface ExactEvmSchemeV1Config { /** @@ -21,6 +32,12 @@ export interface ExactEvmSchemeV1Config { * @default false */ deployERC4337WithEIP6492?: boolean; + /** + * If enabled, simulates transaction before settling. Defaults to false, ie only simulate during verify. + * + * @default false + */ + simulateInSettle?: boolean; } /** @@ -43,6 +60,7 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { ) { this.config = { deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false, + simulateInSettle: config?.simulateInSettle ?? false, }; } @@ -78,17 +96,131 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { async verify( payload: PaymentPayload, requirements: PaymentRequirements, + ): Promise { + return this._verify(payload, requirements); + } + + /** + * Settles a payment by executing the transfer (V1). + * + * @param payload - The payment payload to settle + * @param requirements - The payment requirements + * @returns Promise resolving to settlement response + */ + async settle( + payload: PaymentPayload, + requirements: PaymentRequirements, + ): Promise { + const payloadV1 = payload as unknown as PaymentPayloadV1; + const exactEvmPayload = payload.payload as ExactEvmPayloadV1; + + // Re-verify before settling + const valid = await this._verify(payload, requirements, { + simulate: this.config.simulateInSettle ?? false, + }); + if (!valid.isValid) { + return { + success: false, + network: payloadV1.network, + transaction: "", + errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme, + payer: exactEvmPayload.authorization.from, + }; + } + + try { + // Parse ERC-6492 signature if applicable (for optional deployment) + const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature( + exactEvmPayload.signature!, + ); + + // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed + if ( + this.config.deployERC4337WithEIP6492 && + factoryAddress && + factoryCalldata && + !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000") + ) { + // Check if smart wallet is already deployed + const payerAddress = exactEvmPayload.authorization.from; + const bytecode = await this.signer.getCode({ address: payerAddress }); + + if (!bytecode || bytecode === "0x") { + // Send the factory calldata directly as a transaction + // The factoryCalldata already contains the complete encoded function call + const deployTx = await this.signer.sendTransaction({ + to: factoryAddress as Hex, + data: factoryCalldata as Hex, + }); + + // Wait for deployment transaction + await this.signer.waitForTransactionReceipt({ hash: deployTx }); + } + } + + const tx = await executeTransferWithAuthorization( + this.signer, + getAddress(requirements.asset), + exactEvmPayload, + ); + + // Wait for transaction confirmation + const receipt = await this.signer.waitForTransactionReceipt({ hash: tx }); + + if (receipt.status !== "success") { + return { + success: false, + errorReason: Errors.ErrTransactionFailed, + transaction: tx, + network: payloadV1.network, + payer: exactEvmPayload.authorization.from, + }; + } + + return { + success: true, + transaction: tx, + network: payloadV1.network, + payer: exactEvmPayload.authorization.from, + }; + } catch (error) { + return { + success: false, + errorReason: error instanceof Error ? error.message : Errors.ErrTransactionFailed, + transaction: "", + network: payloadV1.network, + payer: exactEvmPayload.authorization.from, + }; + } + } + + /** + * Internal verify with optional simulation control. + * + * @param payload - The payment payload to verify + * @param requirements - The payment requirements + * @param options - Verification options (e.g. simulate) + * @returns Promise resolving to verification response + */ + private async _verify( + payload: PaymentPayload, + requirements: PaymentRequirements, + options?: VerifyV1Options, ): Promise { const requirementsV1 = requirements as unknown as PaymentRequirementsV1; const payloadV1 = payload as unknown as PaymentPayloadV1; const exactEvmPayload = payload.payload as ExactEvmPayloadV1; + const payer = exactEvmPayload.authorization.from; + let eip6492Deployment: + | { factoryAddress: `0x${string}`; factoryCalldata: `0x${string}` } + | undefined; // Verify scheme matches if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") { return { isValid: false, - invalidReason: "unsupported_scheme", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrInvalidScheme, + payer, }; } @@ -99,16 +231,16 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { } catch { return { isValid: false, - invalidReason: `invalid_network`, - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrNetworkMismatch, + payer, }; } if (!requirements.extra?.name || !requirements.extra?.version) { return { isValid: false, - invalidReason: "missing_eip712_domain", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrMissingEip712Domain, + payer, }; } @@ -119,8 +251,8 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { if (payloadV1.network !== requirements.network) { return { isValid: false, - invalidReason: "network_mismatch", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrNetworkMismatch, + payer, }; } @@ -144,67 +276,54 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { }, }; - // Verify signature + // Verify signature (flatten EIP-6492 handling out of catch block) + let isValid = false; try { - const recoveredAddress = await this.signer.verifyTypedData({ - address: exactEvmPayload.authorization.from, + isValid = await this.signer.verifyTypedData({ + address: payer, ...permitTypedData, signature: exactEvmPayload.signature!, }); + } catch { + isValid = false; + } + + const signature = exactEvmPayload.signature!; + const sigLen = signature.startsWith("0x") ? signature.length - 2 : signature.length; - if (!recoveredAddress) { + // Extract EIP-6492 deployment info (factory address + calldata) if present + const erc6492Data = parseErc6492Signature(signature); + const hasDeploymentInfo = + erc6492Data.address && + erc6492Data.data && + !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000"); + + if (hasDeploymentInfo) { + eip6492Deployment = { + factoryAddress: erc6492Data.address!, + factoryCalldata: erc6492Data.data!, + }; + } + + if (!isValid) { + const isSmartWallet = sigLen > 130; // 65 bytes = 130 hex chars for EOA + + if (!isSmartWallet) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_signature", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrInvalidSignature, + payer, }; } - } catch { - // Signature verification failed - could be an undeployed smart wallet - // Check if smart wallet is deployed - const signature = exactEvmPayload.signature!; - const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; - const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA - if (isSmartWallet) { - const payerAddress = exactEvmPayload.authorization.from; - const bytecode = await this.signer.getCode({ address: payerAddress }); + const bytecode = await this.signer.getCode({ address: payer }); + const isDeployed = bytecode && bytecode !== "0x"; - if (!bytecode || bytecode === "0x") { - // Wallet is not deployed. Check if it's EIP-6492 with deployment info. - // EIP-6492 signatures contain factory address and calldata needed for deployment. - // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them). - const erc6492Data = parseErc6492Signature(signature); - const hasDeploymentInfo = - erc6492Data.address && - erc6492Data.data && - !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000"); - - if (!hasDeploymentInfo) { - // Non-EIP-6492 undeployed smart wallet - will always fail at settlement - // since EIP-3009 requires on-chain EIP-1271 validation - return { - isValid: false, - invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet", - payer: payerAddress, - }; - } - // EIP-6492 signature with deployment info - allow through - // Facilitators with sponsored deployment support can handle this in settle() - } else { - // Wallet is deployed but signature still failed - invalid signature - return { - isValid: false, - invalidReason: "invalid_exact_evm_payload_signature", - payer: exactEvmPayload.authorization.from, - }; - } - } else { - // EOA signature failed + if (!isDeployed && !hasDeploymentInfo) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_signature", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrUndeployedSmartWallet, + payer, }; } } @@ -213,8 +332,8 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { if (getAddress(exactEvmPayload.authorization.to) !== getAddress(requirements.payTo)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_recipient_mismatch", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrRecipientMismatch, + payer, }; } @@ -223,8 +342,8 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_valid_before", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrValidBeforeExpired, + payer, }; } @@ -232,188 +351,43 @@ export class ExactEvmSchemeV1 implements SchemeNetworkFacilitator { if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_valid_after", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrValidAfterInFuture, + payer, }; } - // Check balance - try { - const balance = (await this.signer.readContract({ - address: erc20Address, - abi: eip3009ABI, - functionName: "balanceOf", - args: [exactEvmPayload.authorization.from], - })) as bigint; - - if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) { - return { - isValid: false, - invalidReason: "insufficient_funds", - invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`, - payer: exactEvmPayload.authorization.from, - }; - } - } catch { - // If we can't check balance, continue with other validations - } - // Verify amount exactly matches requirements if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) { return { isValid: false, - invalidReason: "invalid_exact_evm_payload_authorization_value_mismatch", - payer: exactEvmPayload.authorization.from, + invalidReason: Errors.ErrInvalidAuthorizationValue, + payer, }; } + // Transaction simulation + if (options?.simulate !== false) { + const simulationSucceeded = await simulateEip3009Transfer( + this.signer, + erc20Address, + exactEvmPayload, + eip6492Deployment, + ); + if (!simulationSucceeded) { + return diagnoseEip3009SimulationFailure( + this.signer, + erc20Address, + exactEvmPayload, + requirements, + requirementsV1.maxAmountRequired, + ); + } + } + return { isValid: true, invalidReason: undefined, - payer: exactEvmPayload.authorization.from, + payer, }; } - - /** - * Settles a payment by executing the transfer (V1). - * - * @param payload - The payment payload to settle - * @param requirements - The payment requirements - * @returns Promise resolving to settlement response - */ - async settle( - payload: PaymentPayload, - requirements: PaymentRequirements, - ): Promise { - const payloadV1 = payload as unknown as PaymentPayloadV1; - const exactEvmPayload = payload.payload as ExactEvmPayloadV1; - - // Re-verify before settling - const valid = await this.verify(payload, requirements); - if (!valid.isValid) { - return { - success: false, - network: payloadV1.network, - transaction: "", - errorReason: valid.invalidReason ?? "invalid_scheme", - payer: exactEvmPayload.authorization.from, - }; - } - - try { - // Parse ERC-6492 signature if applicable - const parseResult = parseErc6492Signature(exactEvmPayload.signature!); - const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; - - // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed - if ( - this.config.deployERC4337WithEIP6492 && - factoryAddress && - factoryCalldata && - !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000") - ) { - // Check if smart wallet is already deployed - const payerAddress = exactEvmPayload.authorization.from; - const bytecode = await this.signer.getCode({ address: payerAddress }); - - if (!bytecode || bytecode === "0x") { - // Wallet not deployed - attempt deployment - try { - console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`); - - // Send the factory calldata directly as a transaction - // The factoryCalldata already contains the complete encoded function call - const deployTx = await this.signer.sendTransaction({ - to: factoryAddress as Hex, - data: factoryCalldata as Hex, - }); - - // Wait for deployment transaction - await this.signer.waitForTransactionReceipt({ hash: deployTx }); - console.log(`Successfully deployed smart wallet for ${payerAddress}`); - } catch (deployError) { - console.error("Smart wallet deployment failed:", deployError); - // Deployment failed - cannot proceed - throw deployError; - } - } else { - console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`); - } - } - - // Determine if this is an ECDSA signature (EOA) or smart wallet signature - // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x) - const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; - const isECDSA = signatureLength === 130; - - let tx: Hex; - if (isECDSA) { - // For EOA wallets, parse signature into v, r, s and use that overload - const parsedSig = parseSignature(signature); - - tx = await this.signer.writeContract({ - address: getAddress(requirements.asset), - abi: eip3009ABI, - functionName: "transferWithAuthorization", - args: [ - getAddress(exactEvmPayload.authorization.from), - getAddress(exactEvmPayload.authorization.to), - BigInt(exactEvmPayload.authorization.value), - BigInt(exactEvmPayload.authorization.validAfter), - BigInt(exactEvmPayload.authorization.validBefore), - exactEvmPayload.authorization.nonce, - (parsedSig.v as number | undefined) || parsedSig.yParity, - parsedSig.r, - parsedSig.s, - ], - }); - } else { - // For smart wallets, use the bytes signature overload - // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data - tx = await this.signer.writeContract({ - address: getAddress(requirements.asset), - abi: eip3009ABI, - functionName: "transferWithAuthorization", - args: [ - getAddress(exactEvmPayload.authorization.from), - getAddress(exactEvmPayload.authorization.to), - BigInt(exactEvmPayload.authorization.value), - BigInt(exactEvmPayload.authorization.validAfter), - BigInt(exactEvmPayload.authorization.validBefore), - exactEvmPayload.authorization.nonce, - signature, - ], - }); - } - - // Wait for transaction confirmation - const receipt = await this.signer.waitForTransactionReceipt({ hash: tx }); - - if (receipt.status !== "success") { - return { - success: false, - errorReason: "invalid_transaction_state", - transaction: tx, - network: payloadV1.network, - payer: exactEvmPayload.authorization.from, - }; - } - - return { - success: true, - transaction: tx, - network: payloadV1.network, - payer: exactEvmPayload.authorization.from, - }; - } catch (error) { - console.error("Failed to settle transaction:", error); - return { - success: false, - errorReason: "transaction_failed", - transaction: "", - network: payloadV1.network, - payer: exactEvmPayload.authorization.from, - }; - } - } } diff --git a/typescript/packages/mechanisms/evm/src/multicall.ts b/typescript/packages/mechanisms/evm/src/multicall.ts new file mode 100644 index 0000000000..9e0534ab64 --- /dev/null +++ b/typescript/packages/mechanisms/evm/src/multicall.ts @@ -0,0 +1,140 @@ +import { encodeFunctionData, decodeFunctionResult } from "viem"; + +/** + * Multicall3 contract address. + * Same address on all EVM chains via CREATE2 deployment. + * + * @see https://github.com/mds1/multicall + */ +export const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11" as const; + +/** Multicall3 getEthBalance ABI for querying native token balance. */ +export const multicall3GetEthBalanceAbi = [ + { + name: "getEthBalance", + inputs: [{ name: "addr", type: "address" }], + outputs: [{ name: "balance", type: "uint256" }], + stateMutability: "view", + type: "function", + }, +] as const; + +/** Multicall3 tryAggregate ABI for batching calls. */ +const multicall3ABI = [ + { + inputs: [ + { name: "requireSuccess", type: "bool" }, + { + name: "calls", + type: "tuple[]", + components: [ + { name: "target", type: "address" }, + { name: "callData", type: "bytes" }, + ], + }, + ], + name: "tryAggregate", + outputs: [ + { + name: "returnData", + type: "tuple[]", + components: [ + { name: "success", type: "bool" }, + { name: "returnData", type: "bytes" }, + ], + }, + ], + stateMutability: "payable", + type: "function", + }, +] as const; + +export type ContractCall = { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args?: readonly unknown[]; +}; + +export type RawContractCall = { + address: `0x${string}`; + callData: `0x${string}`; +}; + +export type MulticallSuccess = { status: "success"; result: unknown }; +export type MulticallFailure = { status: "failure"; error: Error }; +export type MulticallResult = MulticallSuccess | MulticallFailure; + +/** + * Batches contract calls via Multicall3 `tryAggregate(false, ...)`. + * + * Accepts a mix of typed ContractCall (ABI-encoded + decoded) and + * RawContractCall (pre-encoded calldata, no decoding) entries. + * Raw calls are useful for the EIP-6492 factory deployment case + * where calldata is pre-encoded with no ABI available. + */ +type ReadContractFn = (args: { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args?: readonly unknown[]; +}) => Promise; + +/** + * Executes multiple contract read calls in a single RPC round-trip using Multicall3. + * + * @param readContract - Function that performs a single contract read (e.g. viem readContract) + * @param calls - Array of contract calls to batch (ContractCall or RawContractCall) + * @returns A promise that resolves to an array of decoded results, one per call + */ +export async function multicall( + readContract: ReadContractFn, + calls: ReadonlyArray, +): Promise { + const aggregateCalls = calls.map(call => { + if ("callData" in call) { + return { target: call.address, callData: call.callData }; + } + const callData = encodeFunctionData({ + abi: call.abi, + functionName: call.functionName, + args: call.args as unknown[], + }); + return { target: call.address, callData }; + }); + + const rawResults = (await readContract({ + address: MULTICALL3_ADDRESS, + abi: multicall3ABI, + functionName: "tryAggregate", + args: [false, aggregateCalls], + })) as { success: boolean; returnData: `0x${string}` }[]; + + return rawResults.map((raw, i) => { + if (!raw.success) { + return { + status: "failure" as const, + error: new Error(`multicall: call reverted (returnData: ${raw.returnData})`), + }; + } + + const call = calls[i]; + if ("callData" in call) { + return { status: "success" as const, result: undefined }; + } + + try { + const decoded = decodeFunctionResult({ + abi: call.abi, + functionName: call.functionName, + data: raw.returnData, + }); + return { status: "success" as const, result: decoded }; + } catch (err) { + return { + status: "failure" as const, + error: err instanceof Error ? err : new Error(String(err)), + }; + } + }); +} diff --git a/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts b/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts index 853be2a4a9..e7a03d08f0 100644 --- a/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts +++ b/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts @@ -5,6 +5,9 @@ import type { ClientEvmSigner, FacilitatorEvmSigner } from "../../../src/signer" import { PaymentRequirements, PaymentPayload } from "@x402/core/types"; import { x402ExactPermit2ProxyAddress, PERMIT2_ADDRESS } from "../../../src/constants"; import { ERC20_APPROVAL_GAS_SPONSORING_KEY } from "../../../src/exact/extensions"; +import { MULTICALL3_ADDRESS } from "../../../src/multicall"; +import { concat, encodeAbiParameters } from "viem"; +import * as Errors from "../../../src/exact/facilitator/errors"; // Mock viem's transaction parsing utilities for ERC-20 approval tests // Uses importOriginal to preserve all other viem exports (getAddress, etc.) @@ -113,7 +116,7 @@ describe("ExactEvmScheme (Facilitator)", () => { const result = await facilitator.verify(payload, requirements); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("unsupported_scheme"); + expect(result.invalidReason).toBe(Errors.ErrInvalidScheme); }); it("should reject if missing EIP-712 domain parameters", async () => { @@ -141,7 +144,7 @@ describe("ExactEvmScheme (Facilitator)", () => { const result = await facilitator.verify(fullPayload, requirements); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("missing_eip712_domain"); + expect(result.invalidReason).toBe(Errors.ErrMissingEip712Domain); }); it("should reject if network doesn't match", async () => { @@ -159,7 +162,7 @@ describe("ExactEvmScheme (Facilitator)", () => { const fullPayload: PaymentPayload = { ...paymentPayload, - accepted: { ...requirements, network: "eip155:1" }, // Wrong network in accepted + accepted: requirements, resource: { url: "", description: "", mimeType: "" }, }; @@ -168,7 +171,7 @@ describe("ExactEvmScheme (Facilitator)", () => { const result = await facilitator.verify(fullPayload, wrongNetworkRequirements); expect(result.isValid).toBe(false); - // Verification should fail (network mismatch or other validation error) + expect(result.invalidReason).toBe(Errors.ErrNetworkMismatch); }); it("should reject if recipient doesn't match payTo", async () => { @@ -199,7 +202,7 @@ describe("ExactEvmScheme (Facilitator)", () => { const result = await facilitator.verify(fullPayload, modifiedRequirements); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("invalid_exact_evm_payload_recipient_mismatch"); + expect(result.invalidReason).toBe(Errors.ErrRecipientMismatch); }); it("should reject if amount doesn't match", async () => { @@ -596,7 +599,7 @@ describe("ExactEvmScheme (Facilitator)", () => { const result = await facilitator.verify(payload, requirements); expect(result.isValid).toBe(false); - expect(result.invalidReason).toContain("invalid_exact_evm_payload_signature"); + expect(result.invalidReason).toBe(Errors.ErrInvalidSignature); }); it("should normalize addresses (case-insensitive)", async () => { @@ -774,6 +777,234 @@ describe("ExactEvmScheme (Facilitator)", () => { }); }); + describe("ERC-6492 counterfactual signature verification", () => { + const ERC6492_MAGIC = "0x6492649264926492649264926492649264926492649264926492649264926492"; + + function makeERC6492Sig( + factory: `0x${string}`, + calldata: `0x${string}`, + innerSig: `0x${string}`, + ): `0x${string}` { + const encoded = encodeAbiParameters( + [{ type: "address" }, { type: "bytes" }, { type: "bytes" }], + [factory, calldata, innerSig], + ); + return concat([encoded, ERC6492_MAGIC]) as `0x${string}`; + } + + const erc6492Requirements: PaymentRequirements = { + scheme: "exact", + network: "eip155:84532", + amount: "1000000", + asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + payTo: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0", + maxTimeoutSeconds: 300, + extra: { name: "USDC", version: "2" }, + }; + + const erc6492Payer = "0x1234567890123456789012345678901234567890"; + const factory = "0x1111111111111111111111111111111111111111" as `0x${string}`; + const factoryCalldata = "0xdeadbeef" as `0x${string}`; + const garbageInnerSig = ("0x" + "00".repeat(65)) as `0x${string}`; + const erc6492Sig = makeERC6492Sig(factory, factoryCalldata, garbageInnerSig); + + function makeERC6492Payload(sig: `0x${string}`): PaymentPayload { + return { + x402Version: 2, + payload: { + authorization: { + from: erc6492Payer, + to: erc6492Requirements.payTo, + value: erc6492Requirements.amount, + validAfter: "0", + validBefore: "999999999999", + nonce: "0x0000000000000000000000000000000000000000000000000000000000000001", + }, + signature: sig, + }, + accepted: erc6492Requirements, + resource: { url: "", description: "", mimeType: "" }, + }; + } + + it("should accept ERC-6492 when verifyTypedData returns true and simulation passes", async () => { + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(true); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x"); + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { success: true, returnData: "0x" }, + { success: true, returnData: "0x" }, + ]); + } + return Promise.resolve(BigInt("10000000")); + }); + + const result = await facilitator.verify(makeERC6492Payload(erc6492Sig), erc6492Requirements); + + expect(result.isValid).toBe(true); + expect(result.payer).toBe(erc6492Payer); + }); + + it("should accept ERC-6492 when verifyTypedData fails but simulation passes (EOA-only signer)", async () => { + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(false); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x"); + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { success: true, returnData: "0x" }, + { success: true, returnData: "0x" }, + ]); + } + return Promise.resolve(BigInt("10000000")); + }); + + const result = await facilitator.verify(makeERC6492Payload(erc6492Sig), erc6492Requirements); + + expect(result.isValid).toBe(true); + expect(result.payer).toBe(erc6492Payer); + }); + + it("should accept ERC-6492 when verifyTypedData throws but simulation passes", async () => { + mockFacilitatorSigner.verifyTypedData = vi + .fn() + .mockRejectedValue(new Error("invalid signature length")); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x"); + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { success: true, returnData: "0x" }, + { success: true, returnData: "0x" }, + ]); + } + return Promise.resolve(BigInt("10000000")); + }); + + const result = await facilitator.verify(makeERC6492Payload(erc6492Sig), erc6492Requirements); + + expect(result.isValid).toBe(true); + expect(result.payer).toBe(erc6492Payer); + }); + + it("should reject ERC-6492 when simulation fails (multicall transfer reverts)", async () => { + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(true); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x"); + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { success: true, returnData: "0x" }, + { success: false, returnData: "0x" }, + ]); + } + return Promise.resolve([ + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000000000000f4240", + }, + { success: true, returnData: "0x" }, + { success: true, returnData: "0x" }, + { + success: true, + returnData: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + ]); + }); + + const result = await facilitator.verify(makeERC6492Payload(erc6492Sig), erc6492Requirements); + + expect(result.isValid).toBe(false); + }); + + it("should reject forged ERC-6492 when verifyTypedData fails and simulation fails", async () => { + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(false); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x"); + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { success: true, returnData: "0x" }, + { success: false, returnData: "0x" }, + ]); + } + return Promise.resolve([ + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000000000000f4240", + }, + { success: true, returnData: "0x" }, + { success: true, returnData: "0x" }, + { + success: true, + returnData: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + ]); + }); + + const result = await facilitator.verify(makeERC6492Payload(erc6492Sig), erc6492Requirements); + + expect(result.isValid).toBe(false); + expect(result.payer).toBe(erc6492Payer); + }); + + it("should reject undeployed smart wallet without ERC-6492 deployment info", async () => { + const longNonERC6492Sig = ("0x" + "ab".repeat(100)) as `0x${string}`; + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(false); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x"); + + const result = await facilitator.verify( + makeERC6492Payload(longNonERC6492Sig), + erc6492Requirements, + ); + + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe("invalid_exact_evm_payload_undeployed_smart_wallet"); + expect(result.payer).toBe(erc6492Payer); + }); + + it("should accept deployed smart wallet when verifyTypedData fails but simulation passes (ERC-1271)", async () => { + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(false); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x6080604052"); + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { success: true, returnData: "0x" }, + { success: true, returnData: "0x" }, + ]); + } + return Promise.resolve(undefined); + }); + + const result = await facilitator.verify(makeERC6492Payload(erc6492Sig), erc6492Requirements); + + expect(result.isValid).toBe(true); + expect(result.payer).toBe(erc6492Payer); + }); + + it("should reject deployed smart wallet when both verifyTypedData and simulation fail", async () => { + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(false); + mockFacilitatorSigner.getCode = vi.fn().mockResolvedValue("0x6080604052"); + mockFacilitatorSigner.readContract = vi + .fn() + .mockRejectedValue(new Error("execution reverted")); + + const result = await facilitator.verify(makeERC6492Payload(erc6492Sig), erc6492Requirements); + + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe(Errors.ErrEip3009SimulationFailed); + }); + }); + describe("EIP-2612 Gas Sponsoring - Settlement", () => { const permit2Requirements: PaymentRequirements = { scheme: "exact", diff --git a/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts b/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts index 3d1e53761d..b6171afc0e 100644 --- a/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts +++ b/typescript/packages/mechanisms/evm/test/unit/v1/facilitator.test.ts @@ -3,6 +3,7 @@ import { ExactEvmSchemeV1 } from "../../../src/exact/v1/facilitator/scheme"; import type { FacilitatorEvmSigner } from "../../../src/signer"; import type { PaymentRequirementsV1 } from "@x402/core/types/v1"; import type { PaymentPayloadV1 } from "@x402/core/types/v1"; +import * as Errors from "../../../src/exact/facilitator/errors"; describe("ExactEvmSchemeV1", () => { let mockSigner: FacilitatorEvmSigner; @@ -97,7 +98,7 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.verify(payload as never, requirements as never); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("unsupported_scheme"); + expect(result.invalidReason).toBe(Errors.ErrInvalidScheme); }); it("should reject if network does not match", async () => { @@ -133,7 +134,7 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.verify(payload as never, requirements as never); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("network_mismatch"); + expect(result.invalidReason).toBe(Errors.ErrNetworkMismatch); }); it("should reject if amount is insufficient (maxAmountRequired)", async () => { @@ -169,11 +170,12 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.verify(payload as never, requirements as never); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("invalid_exact_evm_payload_authorization_value_mismatch"); + expect(result.invalidReason).toBe(Errors.ErrInvalidAuthorizationValue); }); it("should reject if balance is insufficient", async () => { - mockSigner.readContract = vi.fn().mockResolvedValue(BigInt("50000")); // Low balance + // Simulation fails (transfer would revert due to insufficient balance) + mockSigner.readContract = vi.fn().mockRejectedValue(new Error("simulation reverted")); const facilitator = new ExactEvmSchemeV1(mockSigner); @@ -207,7 +209,7 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.verify(payload as never, requirements as never); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("insufficient_funds"); + expect(result.invalidReason).toBe("invalid_exact_evm_transaction_simulation_failed"); }); it("should reject if recipient does not match", async () => { @@ -243,7 +245,7 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.verify(payload as never, requirements as never); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("invalid_exact_evm_payload_recipient_mismatch"); + expect(result.invalidReason).toBe(Errors.ErrRecipientMismatch); }); it("should reject if network not supported", async () => { @@ -278,7 +280,7 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.verify(payload as never, requirements as never); expect(result.isValid).toBe(false); - expect(result.invalidReason).toBe("invalid_network"); + expect(result.invalidReason).toBe(Errors.ErrNetworkMismatch); }); }); @@ -359,7 +361,7 @@ describe("ExactEvmSchemeV1", () => { const result = await facilitator.settle(payload as never, requirements as never); expect(result.success).toBe(false); - expect(result.errorReason).toBe("invalid_exact_evm_payload_signature"); + expect(result.errorReason).toBe(Errors.ErrInvalidSignature); }); }); }); From edad758bca341714134bb4c09487ece102f18aa7 Mon Sep 17 00:00:00 2001 From: IDAPIXL Date: Tue, 10 Mar 2026 16:51:09 -0700 Subject: [PATCH 049/129] Add Idapixl Cortex to ecosystem directory (#1478) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cognitive infrastructure service for AI agents β€” semantic deduplication, novelty detection, and belief consistency checking. Accepts x402 USDC micropayments on Base. Co-authored-by: Claude Opus 4.6 --- .../partners-data/idapixl-cortex/metadata.json | 7 +++++++ .../site/public/logos/idapixl-cortex.jpg | Bin 0 -> 351556 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/idapixl-cortex/metadata.json create mode 100644 typescript/site/public/logos/idapixl-cortex.jpg diff --git a/typescript/site/app/ecosystem/partners-data/idapixl-cortex/metadata.json b/typescript/site/app/ecosystem/partners-data/idapixl-cortex/metadata.json new file mode 100644 index 0000000000..9aac78b9f8 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/idapixl-cortex/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Idapixl Cortex", + "category": "Services/Endpoints", + "logoUrl": "/logos/idapixl-cortex.jpg", + "description": "Cognitive infrastructure for AI agents. Semantic deduplication, novelty detection, and belief consistency checking powered by a persistent memory graph. Pay with USDC via x402 micropayments on Base.", + "websiteUrl": "https://idapixl.com/tools" +} diff --git a/typescript/site/public/logos/idapixl-cortex.jpg b/typescript/site/public/logos/idapixl-cortex.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef425f7015548d934cd983f160d036ca23fa6be8 GIT binary patch literal 351556 zcmbTd1yEeg)~G##ySux)yE_DTm%)7?SP1SG+}+(Bf)m^w5=fB25D8-ct?pgby=Ugn=AQ$AhPhl02T1yF z76CE=!2jq$FX>-lpBMrF7_t6+eNp|n1W0K*xI^8&9o#*rcsaNLLNdzga0o9&001HY z0SE-Vy#LYB|D(hDC;hMF&u274Wm#DZP3>0-%4+g|%>igiYL0I1pch+LH>j7kq70Rx zkueqGJOBhh1|R^q0RSr-Zx3}H1>L_5Da*@JdA}I_SEDcZu>OxnfE9KnO)9GYS@wU; zVcU3kL0>|m`C`dyYv*nA!Vxd*@*3*#SAX@wc-GE;83gy2yMz^6y4k+i{2jB0t*h-{9(&;!Umv>{2CKbrl&_=R>la>qVLBHdSH~Cr@xpknc2?d1 z036z1J=D&|;f1+g7|lypTlR&;UM3RF{=eAzzZh!g_cBfZK-S&E-^De_Q>Z;qTo3%i>n+pE&~(%>GCBpSu6ixt9U}LiaDRN%@b?ItKvgiUa_Nw*RA} zD+T~CBLINTh5z!0;O}~IfI>Y)I5}Uxe$C-%XT$L~p#PTttHHl5|M&1;{c-&5@87Yb zlCy(Y`M5x-{sz^?-NoI%Epe0{r|s+|DP-V*RcL;9BkTl5IZkBx0kN;Usjo; zoBhjlyV*KI9o^li9NqqRGyMNp?Z3wG7yq@cUjVoKHvrFq1Aw)F2LNBr0^o2_0btX@ zmlEK==S>Y+AMp3iGoU>A*Sde0j+>8KtEs@FaekWECSX5JAi$_5#Stf1$Y4b1OkDGKy)B3kQhh_ zqzAGBd4NJd37|Ys4X6z?0$Kv?fo?z_U=T1I7!OPZ<^oHAHNX~N4{#Vb1zZAd0S|zu zz#HHb2n<34;ep6O3?NRB5J(!N3ep9cf$Tw^pa4(=C<&AeDh1VpIzhvr8PFPNA9N17 z2Lr&UU;;2Tm>nzxmIc288-pQWFK{q84x9-t1vi3w!IR(>@ILqg{0N5thYLpq#||e7 zrv#@5X9MR67YvsGmkU=7*9kWUw*q$ncLnzw9vz+xo)umMUK!pH-X8und=z{pd?kDb z{5bp?{1N;E0s;a70waPTf)auef)hd@LIOeoLKDIe!VLjoOU* z0rdd&5e)~81x*&s6wL=M39Slk2yF}P79Aa(0bL5+7#)h9gkFO_ivAJ(2L>(%2Zl0+ zEyi1nJd93^WsI+w$e8q)(wOF$0hpPXZI}y~7g)$x3|O*QR#?GUd00JI8(8<)xY*p- zudrRQ6R>Nsr?6o-h&T*5@;J6Q5jbTyqc~r1!ML=zvbZ+5;kf0v?})pI_ekJKSV*);UXv7(jFViD;*pAy+K|SPwvuj> zfyh|Mw8;X=%E)HP?#U_070ErwbI3=@FDM8oq$r#y(kTWhPAPFIB`6&!(<$Fmo>Adb zNmIE{WmAn&T~U)!D^dGUmr&1B|D<80(W42YX`f zZPO#u3(-5!XVFj6e`jE1Fkpyg=wg5|5-}<>1~Aq!?lPe>Niumdl`^d|BQOgwJ2MwB zFS3AG_*ooS@>mvFL97C-j;sZ&OKk9L!fbAArEDAQXzbGLzU+1E2OI<(Y8+u4T^wII z={Su!-*HZI{^sK6a^WiH+Tq6GR^blg?&ZGWVd1gi$>Uk&MdwxEeaqX;d(FqnXUA8_ zx5@qGy@2}_A$iG4|GNh`@x$Qnpf+QYX^P z(oWL#(qCn`WV~cLWWLLa$i9&sk^{>r%Eige%j3xF$>+*{RG?9?SEy6CQsh?*R2))* zS5j4ar?jC=u56=RqkN?zsPaZ-OchO4M>SXVvl@$lNUY z@~gC0dzy@zo|=7H2wIw2d0NNX+}c6flRCIM7CN;$54tkC$+|mwOnN?gBl?*7rusGd z-wospQVsSEISt5AFuUaxA|fFx%tidv-rpQ zp9ClbR0P5W+60aSQ3r(v9lVi#QxXgewhkV7OZztB?NNwgNOdSmsB`FC7*|+o*j>0m zcy9!GL`cM!NX5vyD2yntsEugR=%N_77{{3TSl-y2*xzxsantc!@tN_@2{sASiQI|V ziGPwHN%P49$%QEhDQ+q2?sw%dp6p%H+!|%0kKV$=c6W z%kIvh%Sp+3&UMIL%ah4#$|uW@&Hr9tTd-UxRoGZWUKC&SRP0#1S)y3dS;|nFS%y&N zTXtNoUp`qOR8dn&QW;jZZCcV2ZlbnSN=buaa(^o;b1_IC7f z^i}m!_va1Z4X_Ep{J84)hY5v=(Mjpa z_aDSR^iPRQ^-K#*cg+aQbk6e6cFgh5b<7LQcP~Gp`!nRztuD5-+f9{0r!tciIVeMspB>PzUiTP90zQF##f!x9D zXPwVGUu?ddA9^1?A4MFaA7`FWp47m2VEv~Gr;BGMXGiBA=RYr^F0n83zcPJo|0eZq z_R8?;=-TW0&rQND@om)|-`&W)=KaS9*N30q<9-nTsD2cBoP08PI{Eqf8Sy#$7xS;) z->ScN|G577^XDsoTH4m#+74hV^|BWLf&o}y5cpq5lfRpT7x}XThyZ~8E#Mad!@Z(@PUW`BxK;r zsqMc@06-8J@G@FNtbcg}{^#aMo0uh*#xR&3;A&|zb^WYJM6xY$X2~g)cU7J--_AO% z)Vtgp`dKq&TRo8%$hur)=3^GrGbnl=nOu2}Krdn@KNvQRvs9z^Ond%J1JUQi3w4={ zu!tFhIs*&$)=~#@`eNCa-K8eZO+5AZ4f?^tl?BC8CdTNoE6V2b`PTdQ;`X_jiN@AM zdgNQt3LB4zcDr;Ws<2lx{(l}#ed_4m^WA2YWq+BpxgtQw1G1e+8UEDvMWt~`he%!5Bu5I_-Lhu`B zSlB+CS7Efqn+@Z`wV!$EIAaVb?ibnI_W#D~Rf4_4Uu(%+He)28a~c@RCJkE!GjNv@ zwO6PuO&RcT;+K#V6XVI)5Tv?z*|Mxe=wz ze%aD-3TYj^BMf>*jW4#9REV06n$A2kO|-rEKpE~yc3+kbv&~$7H8B0L_&@|Xvm^Ub z`2eD2tmy!E9ZHEH9?-~_{RzIhOCaWxtJ~TES((`6?rM7tGft!>gO-Xx#MDoWMjD@s z-3)H^vEWKZQt-qZ#EQ#>U~Fau{Pu~_`f|R^5G@iFv{m)7yQun&1`T6nw=KsTVsZ~& z1L|>a-#{%~FB~2PXE7qEy0O@%(IV#?5uj9SSeSEZbMG&`czZmH^0!6i8^iWyXv?Hj zM`}VrB5--0*;gZcyOZ@j=3QEA`_g#9(T8(w&gF;fC>rs4KY4brGiJ~hjm9o(l1mz+ zef(#jN*)&_j%2Vz7Bjj5dowChg#&NGvXD$4l>nH~>fwR->Vb;a^6nQRrTPB%RvOr> z`iMM?Gke|jL*h6#c&mwP0`eCKDi7>A?E96^7b;ac8%3LhZ6uRIb%uiW2Ya}AAeCn( z2QTkbj$b~v71>t<2R0os$77yqN0n#_=S>c&ZR4S<*>HKv5fmCiGiC-IXcsLWHsG*7 z0I^?1VGH=q@38YgK)cMfOGirX+{D82$Dg`3R1aBA2+npwSc%p+dSA2j&Rh|scB;(- zvA9%Ss9^z|j8%(YbTG7|05&G`(i0?YD8{}9*&Y{NcESzYtnIEdX(Zty#Bj95@>TjO zH(F_Lm8|sNZ8wCkG{<=ykAW`mR5s)jGZ4|OJ3dIDL!X*Ve3XH|Nm3<5`vN%a84JDc z^!cuT#HKoHl!@qmM{Y~;4!P7%z=^CQtZ@UeY@RR0=A|^4$|sjD*u-EXxV7#s1A*y= zxF&9`H&c4R0aS+Zwcz+a0LeG+=a(9w^sJ5-xgJ~De0 z&on92AlnUYAGtMfsA9Db7++f(s$ymlr9WU`zE&u(>>(SH<8RKSbAo1DOOThUr+Y_X zij}#VND=P$^bFzrDE_IJfDvWli_7WR=ImQysLj`tG9MXvMnp!^;=PonZ0>BrxTw-| zaH=1(%WD3~Y8FYf$|!V9sddr6qesO`$`!lqp)7ZM&Z0A{o>nr`bjC{~iSeOsPL2YQzR35BmkvuQ+A14wlB zPChbb8Uo1bQi{Y8KVbMxq`p6qaTk#$`|v~22x|^R0(A6$DRw|MyR<3;h4dR`=4E{n zv*jEwy__-}!LZokuuvFVb4?4LvEfh{sUl@vO=WLS;(F&~@$a{RZ;OtMy@KBmd>E01 z5H-=L$C^(?(W`g&7ird12+(rR1jf`DpYD`Yw)Z&@?5_|N+sgJp&ul(bM;pPPL{A48 zmVN>nad{SL$>YlIkzH`|IfUZlN%Bk{KrPcSh(8*WmK}|>HZC<|>jp7vccfL>FY05( zFKZU3PnSc^^0Xd{j{J@V*@0GB7bw%%do#PP>|89H2PJJXVA9Y;-#h0AW8)1kQWh;fyB~&V7F|}0!`hY$++-6&>3@oH6^c99KB?gac~PCHM;kD>SnbYftOEV$3Tibn zc`nx!Yi}*0n)?7k@G5bvnx-r?#H3mV_V4)?^|=?OYr02Qu&X@jxSJ%mwh`djAWhs9d9bDz{rMLgr)lNP%NFjWEKL~ zzI*2;sassxMH~8dHGfTn&aJgH6zDl_s(C zouu#io^)xq?BrznEpoiN0&cvjb4IhX_N1T$)#}=C?yc!X+zxag1VZ5+=>V0gZ~bGnnWNT)ImTa_Upxfd*)ONein(yckh z1gQr3jS6eFaCqG2sB>-#v(MOOr`8Wdn54wKK_PV51MpTJR)JfrJbicKI zrP}&-_k)A~0J&T*KiMz4GyINm+??el4ebZj*8}Do++mywC^|s0{-f zC9e!m`v>tQX?!t~VlkIdu?;l&Lu2#^Zif&7%!Sr1tBgjXez^rIiOo(~0q=?&<8=xZ z`v^vndG2&0vCY>w8b9JYvk5HM)+60xgXa3G40FqcnosGzEeR^lB) zgbL@lX!yZe(E>56AEZgnIroHWi_tck@%ZZZP)*$W_-U^w7k>xj9GYhvHV+5$PFx&T zuq}92l$0j&xrY-Ovl>R;^Sv#7CP!jjei~@Ziu5Ez$Fz_ z(4N3+LmD#co^{*^pItUJVF#P&t*;bGF05*xl1&7J?9E(jq$%$%%g*zPg|MwB3cP){ z54^~Tv=F$S48+O$9%2z)a#_)f_@0~wLG$te(4ZD zxv(y&_C2I>bb#7#o5Pj4sBo)##pipl94P>IW`%d}$Z z!2s#XCt4>~EXWXR#BBbQuaON(>oe6kn_-x@lR&ZHCLTfRErTU~$YoTHq#D+-NJK@F zyl{wm!WT2-IJ{!J8e@~Hk;d88`68RE^~z@UxRFFpRD?o7pp_2Uua+-jj&bE*2CX&N zH_y&j1lg*q*x=t08%F2l@i5tmJ)c&tmwY90i*w>YFF!|vGcMO{<^zb`tHw9KIrAnt zPu{<%j@2ti@6$aw!|e4$c^@tje_QT{hem8o+Wjup`W=4eYi<}^N8D{%wyJnq$c-6A z-}rd|r)24<_Wt;#+b41(00?94576@3V`q@Hi})-mF| z%lF-EM!iqY z_ch623?c~^(^%?paH%N?7ab__HV5r;ShxIQ^xT)XiM6Rv04JIX?PjZAH&CemAd{uwXc^#+Hk z%?#9!Y!DI4A@%#kJMp%>{_fp^#TgJ+6UntjGc5*R_Ot%s(gdCU#OG40i5bI)X=){| z{vYYR+Y7vFf!~~m^NgDBL%~RQ@akyDtMl(#W7E&6pfZ>1_LSNvv8`EVP0G% zvv~aP)~CwV)k?jE&|^HNI?|Ym76M!nqV02vI^~!OX4eg8Gc?a1lCVJ_asJKqYOx7Q z4b3m}ItxZab7;?8!WMuV0)}F4-0>1S z1T-8_5)moN`0V_^0@A^&9OFnrTXhi>MSbAci7>xPBO~pg5!Gsh`cL?e=F}fpSmKgC zQ_#WWiPdqf)-3UEn&&1oA23{{*h~c=*4`vlC7SMQyJ2JTc}msQ>#dC{EZWUXsJy$W zhwAStRl*O4<{DYE!$aWXlu+cp;}T4p;|DPh z_J?>XzYpKC$!c5FiHrF*<%HcZT**}1>qurP9pW04HGO|XQm-MzTFnGW+qsS`NB1%n zNRSX;qN53?XXGwg<~6bv61YwvWWe;!qj!oqa$45rR42;h;ZN?4UrF1NlO?cD&_YSB z9-E~j0b1o#_xvFLDP4YPyvBFfDsrf4-u!iq+3bi?P9w2|@Yadq`FB$m;)7eKBoC7AJ6xA7CrvE|vP%)#*epvy_L?4vr$wjF^?2(wM<&Z2nzCeC-)BOAI69Jom9b)jnt8=wB7RoHSeGV>TCeSnEKy z2$kcuf{Z-M$zX5C@CSl@DiG}zYjhUD%L(u-h*x#2a%)iWJqbSLQegd((Xl$Q*+=w= z)Gm#rHRi%aaCwlNOac;ml#osJEDFn1N;>0~%XhEJaBl?fr6g8VU@pS6Vb71K_S~9w z0oX{v6@Qwm^8}^H{S-z!cS(qE)o1sL=X)&&+jIJ%Sz%U%sW(zBEc>I?Yvl&TzY>ZR z5_}YVd`;&R{pQS7Bc#pOTh|rm`zJb8ij_~9llB{RBbd{v{;DA3HcQr7bJSw)7M?1F8xjVl%RyKKH z>5lVfdBfNgm(e7tdha~p8o7$$H)=8qplf7YC?}cfsVRkaWc&lTzRP;UZXfdDfASRi zUd+w)xOj`P3`g3h9uzx`3DuCK2KOnH(%YL&f?A$s?=6a$AuVW~-2^OSsDjbzX)V14 zs#!H&Ju?c<%fUT$vZw;az2i`lxj3H32*-M8;L2>OIC$z5VYpqFF+^i`%&K9eAgdrw z;H)m=U8r_vlIz>D@wm@tFOa<%%Qfb1 zx+v?d9un5uqZ5<)Plo}>habxh9iq^^+A_(Q*YRNs3SVihG*qq*R(X+7u5gOyD;32b z@R@RPQYd<&NYd2#a~DB+H2@VQma>9VHNHFUulQ*`h#OSGX`##wu0P(MzZWqnI`s8! z4-wL9e?rRGs?+B1EniN+IYtrKXx_HUjgv5*L<%mBW|kxbgSvJ3GR*;GS6@d{xXg zjMA@v@)&NKxF)YZB+goXH3hN4ROYl?N{5u$(6@Tt18vNCMWjGz%??<=${`QCoFp{8 zVDw;kAVeT>ud)uyFtMz(-L_>FFwWzK-N9!TT{T>I+XsK#wUv@CR|&V)F3?>9=u%@| zq$w%hM$~D&(pKk&A&B^)^Elv*CkS_MXSvdQ+_IFjnyGxHX*hCVJ}|dgW|~{aX81ae zazShT;aU9t4PZ z7k3&XW4M!9OZmkpPFT^Zx3@5&4!`F<$gb(}EMd$QHHN0El?X!<8H#&YWSQVzbHF;w z3*J{9+x9Q0GzO@pqr+35qG9ii=9xtPl%lwFFjh(n$rv_G_5M)8QY$bzyBnqLSmszH z!E{q$Yp8r?pj3wt<|e|CNHua@OS0|MNz@^Z{$1*43CHBsxAotaHSJZ4pUK_Eo1z`- zY$_J5XzM=Zq%_>X*!qE7S=QUc&>nwgWBsu21U5J%cZynWZ&mKZ#(BGnuAX%1Vd!ZX zdh}r@7d6v9UNYP~hVJR())lp_P2$2t7t(7k+M%~>3=NUPF~**4PCiQ7fvi+c3f}FS z&2~u}F3Nayc)Vl@L%up1mKzQ==NNoeboMkgatyPJ0U8tOlnJMWu#7Mba%g z(jzxlXHKbkwIeJJny6*b7eL6T0k*4Y_8* zldr}1Si;lFuKobFg7xzVmd^#m6HeBuvoxn{2&=lc`@*702r?cWR(p)vabcDn9m}($ zw7AlNb-6e29ARTQYaDDeI~S)4^V3`J^txkaxq&sjuEa%o*6Ftx+Aa~my&BZFl{hC4q;|CRO4|t{~oGVezp*AaIf;qwa_>rzlm5x3Nyt@gHKJURv{oY ztp5P2^6*Cku%^_a;)(O$Eay`6VcL*1jRuqcd^MF8FLCm1NwuTBm#IjZ)mnGb_;~`` ztp~RS)Nm`P(uSXKignmJm)OXzHLjhX&0vQ2Jj1wTQmd?m;X|Kp4|ngZ<0~!GKy!h zSTru9)XY%yuvz1_l?{2s2DvpfhdR`5t|OZ5+xXe^67zV+a)gD7vd66T;!UAb)5xaA zxL%kH&F2<4J?W#$@t!^_jN;lX#oJUhuVN0whf1rgYjLP^zz*++xS&>gwp$f(CUVq^OkG!|+CA^}0q5btJY1Qr~)? zMYQ21VcH*Qmv5Ow>KQo$9lvuIWKaJA&~7pr_w%2`j`HrYF)klDjkApk#ml0D5SrDP zG!S@pD|t6WgMP?H5-ZiV!n{kYYva$~3>w6HJViPd2dgcG9rA@KuxYpu$F&)Wjw6EB z{ZnSv?p@-JbPi9X6ZKePhwJpe3P9?FXQOMIr)L=2O3_S6w6iMOmA`;k;f@K3XJK=_ z4a?LW^4f@;>~!`1SCL2cJ9)&BQ*Hj|2>Eb!XgtM6eCxCF4~4r&p1Z3anw$75b{~d; z%yuYv#qZ?OYAT?aUbTdP@sY4S;U+n$iR_K5s_kGML=2l0 zRffd+>EbRg*BCpSil&SCTE3;qVon5hFVR`?9V>no1P)&$N5$o5F%e%7Qtq%=-mr#6 zMjrEuMq_5BO8pmwx;Phoe5E4VN;zSY#b<-B}#V>whQ?;WU7+`ngn{R4dQ2f(T(`|+)G z>O)F_2(Wol=0)>KJC-O!FC<9tPWSo?HKFCRo;$CTL5{e8Wpja6M@UiZ`c=VwPPIy0F$L zDg0vap^M{O>WZ2wRwQIEkCni2t18s?v-8jC3Z8Jv6@2y5R+7iX}yv5#b#iWK;Z>GJOx&dP|ebJFBHK>?${g4 z`Bu5nn|p}fOX%Y@Nmj?YTy?QTa8E>9MU8n^S_wyx{VLt-h$@FX1|UzQJNvGyKWN;Q zNzMKQ!%%!}pPmS;B(p7a9zRU9NsXAHSACo|8(4kM*V!BvuM%d$GOMlo;YlK!R8k@g z3nz`+!H+f{=UcVyT9iln@i58tsAdqTKW8`{naikMqkzQcER7{Y#lR{ZS(H`-F=b9_ z(W|Utf`vf)?zksijE%krp9=ED#@r%xF2{gXrTXJRIMurn>c_+ny!oGnl#uESi9+Vw zu^8QSq?gj>0=QXtR%?Llp*nmr&+&IT_NOYjZIYj3#h)IB)t+B}IESg_j@i z2D3b;wq_%p(uoM*ta(p`en2THj+@Wvfr>oaQ(+l)i8&M6{Y!zXw6S20E!H_%OIZ|S*88)!0Zwsfr8>^$`cd9$RMQ5H4qGB-Wkq(CSP!V_PbveLgH!4Oq1 zYgM`OQEXYIE4pw9GH;Wd6qOgD?tmH@r_jSBO~;(ameNRVM_6BjJsmF{cV@XcKH-(2 zsG$86tzi>idwh!1J|AmO3zPBpakOPu*W^WkDNGR&eSE%OQMagZV8v;wpj|v!KTeMi ziDHWSZnj~oVA4@qsPoAA@?<8=_z_A_kXW_)WOk6A+9ETt$-&xyr#3){k(!x_rri*l zoAHT}LplInp}|RcwT-X84d)bJfG0lL%Gf5?iF>YfEvc7$*F+2%&sj%U`l@_X!t@ft zvDV0MyFWZGY>4Nq90IG!qM1D_F6Tr!#Wt&Ln{hOQ;MvE0?KCx^Vm`WVMLyq<0N#{5 zx{b8X616Jk7Bb_=8O$)PuVE?Yg+V*0SB-K$O85p0LkLopJbrL^ru2tEx0vidoE>wR zsya4iYk%QoXz-$F-F|(2Abg5fzS_kHX*xe?X<)*_MiXV7Ao-fFnhHxOq@4QXe6Y^% zUT~=@mRvqUUf&wg+5FxyVfDaaf7CGK;ix@|+H?v56Ft#1OLK@E>)^!zdOG`vFgJH^-M%>f zhQmMVes5i?cAziOEpeQmoM@WSh}2ke8q@xBIxmk&9>s>K`C*o+oN}9P{_});j6KvG zHHRf%`=Z}~-l!zC-G}9}S==~!7G%G5N;-Yo$`FP%V0?GlV(zSppTiKAD3MV;uSJyI zzX+AJPV?Jdp{uZx6=jz$@Pi}^i1hn!90CtoPTp=lON`>c&*U)cVFv=IA1@!@GWq!b zX4k7B>oJSw)ac4u{HWTtywRl3E?yNYm0s_-fMBUm8s`KrtH~Gh*qKA21yikV+>vnM zrRX2EV+U~X@Nc1%BkfMeUTcpz6A^fyeHheR^Ip&q-n{`=JJRnxtQRz!bk(6Cb?ZgN z<|!_=H@C)|J%5_!v^m5V%}-x>`~#46d8!0PXsZJcovi2x7zuvtq$iYDw>f4Cv7cu| zcSBgajo*dtaNP~{jlB|6xvwHvt#D;f+OYIyB~ENF^}3~4UbJ)gu)Olq4xqa%%?Pja zp=j>b;BeR^W%~AEF-a83V7t2yvU2;i(8*9-Uw>!zi8igh|M!P9;B^Wv!kYJyf$1Kb ze=pSQ^j`S;Q+Z!Sp?_anq_+ZJTb6=4!vY6KIk})*#!OxRo)kTR-p_gWV@Xlj_({;O zJ0A6t<9oi4?|F{?A>A{CL_(=goMLai9{eZ*7nVNDE?WkajxgjtY_nLV4i|dp-4SrO zg&sA;_`l8lBz^5n2J?U88)QDYor$;a9-CT}Eku88dC$} zS$?J08(YC*PH=cP__`qtxHVna7OFa&+8oiqniwQZhCmub8d}~cqrK|%E=OkD!RP7a zTj{E^o4Z|ll=1C^1MyiK-T+li|Je55B~=hdjT@g&3y!?ZcoW7MxD&&zD@xQe1y)j+ zmZpk0-te3m0$4?-9B+jgEZsL-6LDpc{o{|VwTk1X!=Ds45t}13te*b>zW-JayHB3m zwe3TOOUug4B)AO3#p{A2cLourKaANm?44%EjD~7|Yk4HDc6DOl$QawOfd|4-OSeU2 zhG}M^$+#F4tyG;DRM~J0g|fEF2YvQZvRBrpWvCK7a()#0p5mG%(l$J(z!%;-UTu!| z%4nlydbaYj72*enGHe_g?lwu*1~#6&)Q{l{TY1dcfE@0X&aR@qJ5I?K*v+L|Qb6ql z_IMd$r21Kij|q}qL)me0{sz8?ti6un{EE8#PkJVC1|R>MoI3R4Oz&AD&@F98W*leh>9XCws^g2cyHtJnHpW9feu?v7KyLuGX_C>Nd|UvYfrezYv26?CTt)D(H@%e%)|}W?s9eK zk@6p}?^UyE?>NowpIeITA!+w9{e@1wd{Wdf)=NTP1GP|MhJ7J;zHXsGh`r<~k$o~p4}s~0$Brc351 z$&YttD+1BVFi|DtS(nF%z+drZ2+vh75@)|RSgP>WP3kUX_c{m<8bLnE><~RhWpOFi z3ZP`U6Xsn@HbbU4b5!4G5K7iEvzdGqzP&(-(ZCaNbb~IHjWumXpIuOq0TKSb1;Pj1 zW>(reneQzbI<%s&sFU zXtzhtR9y0cCFZJ%KK=m|^^`7N1()Cc8gw#mr0-1TX+P;3H1E_p9bh%zT`4(|r^2V! zK~2qMsB!5ubEq!MxvIb3xP=BM-V9(uib|?sJx-~JeC}n66KOWR$r}EmhDM!}`2(L@ zwAd4F`pUq|MOcQPxFo4Voq3QF?FBaK&9dSXMf%p<)6B_gA$m&SqP!AJ6We+3bQ*RN z<^HtATW#oYvLY^u+F_?nQD=EWXgfeD#U&t)ze(C!=g(J(fk5z=01Q%B`N8 z|1w=hvn!m4VDRgThA-bB9d?CPg*I(-1kV@RdGAFR*E}C!{=M5XmDhFFm95f#kjoE^ z{UKslcQ;M-DEiD~UtfOM-4jr1TrqZTqy7g#KES#FyO;mAuHPG0?h<)fYV7~9dtInV zK4X9>elRyc%m(e?hEoyr^7|OA6E6PskWYtmX@C8rg11dmB_p1#J}I zO7$en;-@b^ZeGKqx9t&N!htEDS*EU1DEzUIMyp-ySMFDdUyPU~RTOO)2O!w+N&GHd#F!ksb}wS8 zQs}NaS<*`0qtM{(N40(>`eW%H7vIE6gkTjCpx7R(c`>~X&wNK*$Fn@4vlren8WFD^ z;%wkk!qh{gCQ%P#v@RPH|CXY&v|w35w?h%dbxGh80vlk51sLJ`!kqA>evy!I9olX} zs=eH5iGzvQFpzr`+mX+U>d3UxX=%Z8Fd6g=N`oAe3BCdc*2CoEiQE0ZB60h{SHNs%+W%n{Bh3HfYq$QY~j1`)nOoN z%$&sZvZrt$W@~%y>8P?Jy7o+}Jwg^=`zd+mJ9cJ+bQ7hVZ`?=6H~P1UjzJL8Ir8K@ zlp|+u5#c*`RAaMkMP~iL@lU584H`e2ajeh5Ul$bW)qd-FgQ<8ka7x=c!}cDZmo{TE zfvPafMvvwj(6q|Cpm@rdm?K$q;b*tl?cz<5!eIF5c6T!WWfI4dC8foJh16l=ZPL?M zjqan?yc(?(SNvbeRju(N@hb}=IUE&VNJxHjG|2IUZGP-oK5?&_TJf)fu|?`zr$MMo z8`ZN;>hx+*(^lX5%eJJXP4T>g6lrv@S@!CU;9(l-0LYXHiungoC;f&UDR@uTbTWp_1^L1CqZ3W7T2w^ zGFWM-GRpN7yQ;~n$nD^jM*c$qFOYIBb5PiR+$TSy;)wjWWZsiG#H1{KJLtV~LeY$9 z&+|qt9)Vl*N_VfoZs+#(oxlmK@tviJqP%5%d7g9N&o9nKi|f13^|bbG(hgx`a)gaRfx^@Mh6 zinovY>8+2HPR0u})IP=szZJ?*G*cc$yGzK~icY*cQ7S;l6zWh_>WtCOHI`=Ah^|~o z5EmtRTk!Z8blv|QbACBL1^q#%*RTJluYXb_&JF$XR^=xIdImkL*Uu8sb&rEnC{IbR ze%i0wlVYS_eV_eyJz{V<9m0>rh}HuqT~QFM-vgeW%*x(@l_TxW?7iJTbRbXrCSi3 zx!j)?s)L!eUr$t*q$c`klT;?~FO)heZ7QHhZ`c%F-54>GI+vi{4AD}tEgr4Py1G8Y zw7Mn>O03#LGnF1I5q#kBH*eEX#1AjsV8YH%Rc$lc=~o(@*4mZMQ0v0=L{~^2!P$GB zJCvncwHRaG(q?@8>HCgJZs-q=G(}U!(qQG4u&knF#k8rcXtn3dnprb{1misoJ4`jK zZ#P!01=vn24?hZGOfT&-ZPHbr2=mSY2r(;1#6>A2t#EG=(pktKBIZ|$76Saz%n5kR zS8^1DNtmpw>=xWNBsgE)X>Az!j|q<1`iV-ikCqJ$fOA^?zE>RjcU67<*8S9;zdpS! zfqU+MfP)Vl6+VJJeBGW}A!BybIiBnLR(pDZaqoPt%y!Y9`nl8FRA_rT z;n)V_6LL>GpIc$c*5s+U`Ri2AK)5;2DlQrh$J9Ey`x!;WvPUVN|glO1|u$~`_MpuT~!&@8hp_6 zA=JNXC0;214I21sD0!jFO>5ek?QU^<{Mt=BijBMR%|I9K z>6ZWR#-ila*=2&6GInJSHy1<$k{R#eN@+#45Wd6}w~`SZBb490*MX9j*E=77G3}o3 z@(kL)KH>=Ub1zX_n}9qQI-dF?*G--VyL+L^-fr|9vA!v+O|{pSJe8ze-+H`X^oB|# z=H7u^V=q37gv{=@eo(WdV%7VEvoh?0tFKla`hxdi=OtRyUB_47}Dn=gIx2EHWi zHfz!E@oYito5{q|fModlhlPcJL65qoBbW_h5*fOR6O+ot`}$AinQp$8eWb_si}Od} zkcFN()$*%6gOj_qS<>Z#8dm8|3G)z7?e?f$D>)|~7&d9fw_1o`c-sf@g>+L6+b6$v z^6050r8Cv)ZjqIOlpgZmQmva;@6kGo8@M9ck}a~EEu|ni(7>XlO!H7>xZSnFS1cBi zLjggJK973Kiu)hcocOrDVy)ghe7mW{>wgF(p0^OZ&_UNG+5RD{F}zfTN+sApuhvAXx(PFh>z(W z$w!X-EOnkYiN|}w&aa49#<e9Va5ldBH|##l&dX|Kr&6|+oRvS%c& zbg7KQBogw>eTlb5sF-v_xpn0@*>I$=RrjBE!^F%gI%@xHvvr&kERoJ02{V#Eiq|xm z>6*uUbu>Sy*gfFTMyo>jzW`T2sK0&3e3vJy=H8!{^NYLLJg<9O$Lc-h?&{xR5$ASa z4(;*~baAS;I@)tM!Ldxer8Y-^X{2Dlxi_Zs(Xi); zSqK>Vd0Cssz&-x}882@N{Y;~a@@o0|Ke7J+DfGA=XYzg*bb@Ni9cegcRJ}RNU(|Yf z>!H`Kcj(V6)m1d2)qCcex<%m zMt9eiG~>x959W09@9W`Z)4}y6W2L1_n=^x+DWO;NE-zQatG^riUVFgpYs^j`qdBnN zXSbM#cb0n|Bd%V*Rr5X1Nb`Nh(CU)fYIDyI1@G|}TbLVjtgkgMJID@_yoLo>X}?Dd zk8|R;lU+wj**=Dl>HRa~dY;F@+OqHEm%}$bVUIvxN0I0KyuK6f_;Kmvj(mF&8DB!b z)*q7kjZ`b)UQ;z)rborq6*_@LLDYkb`qg@!_0+X(jg|iZYGSPUb?7@!MOl@WD8)gm zR-v-W6sYIW3QF118C^8xI%Oqlu`-K7kaLSWVCgkU)>fhypv9wt=1|!e6g0CLgVuV8 z6_!LzmYFGOWvNDt;TO2iQnK7=>)HuMg}Ci*9~gW7}>G{l+qi%0Ybmvt_hgs+p(Mf{yB&MoG?C7ZFZ@yZY&(d@+w&v~qW8!;UX7UcC zd?i?{=Z@*{yr-Rz`C!p#8M%Sn?_^iS-MhIU_? z5p+VhZPiY37!IvV0BC@)BW6Grlh{S;3z@p7s?zY!xB*@)cLH{ivPm*B2!S4Qem^IN zpXU7@Rd(ef{JrVqAg%apd3ptDhEr+H*{PNNFNf9qeduxiPxXA(YHp`L>#kOxH)&oM z)GSN+Pp#ph>E!gEFWmI+Gu+qncX~fNr3cNrBl-UTzr#(_$|J{pHBZscn5u2#ynnxx z8cxhTKb`*oLUHtdJ@jEP<|P=Ur9tX69a;W0yw8w6#&E;G^po-$QqYyKX&rE>o&F+D=juaC^m5#ko zz~d&ms2h$%>zL@0`bZa;gv93~J`?q{inErK9fb)WABUTY>ho-`KU!k?9z#Nn5%*l3 zgpHN!^ZT~Lo3CRIk4W=AS#QG=a7N1VAF$rR)T_h^C zEu-h_{Z-<7SvuD#Ozjzf+R?#{^*k>$^}Nl6IL@~vEIj*P&8xJ0{XfuOm-;Wz9JiMP z)yTTRyya;|Dd?&kuIM5**7o$<((o^@uy=Wp(yYuMt zyQ?VKvc9L%=0B-51ovG|Yt^p6O{!oJan7iVFC3)WhE(!>14BA08odcrQ>uy{P4Zm6 zf<~aj9YI#h*zo7zu!(ZAsc@EGJL`&ibI)T~JJD(vc{vzWdBaWc$euUP&zQdi`god< zQ%JK5`Z+dS_VmtP$Ef~W-{s=FeC@9>O$BaN_*w+MkI1ZcKkiAg=)L04Wgb5bH5o zVm!AJd?!TXjf&;YhR%jU<|jv~@OqjKUqu6v3wlfgOZj=vL(9GOWJjlfI!aysJ}_4Y zL+BiRKdZcNTlEi{>2A30R3SBgHRPvMsJH>gI!ShX=x6?w$c4&U6W2dM@8;T)GTZ{h zh75(wgE1VDFoURgDaw}zFC>$(nt1f-qdLOiR|Pl4d7i44alyXg7?Mfk+al^|daPS# zI-!r~=bqbSE)+T(&mWh%O9=C6zl%jFg9hBn`#kpyj1lXvJ4WWdoc^)N+2~yTDk%>% z?ejC;Jf4Tk*wI|ky&uo@zZ!acAB_F46`IrZI&*re%7}G?^Zx*2=sq{o3L~WE=+Xw% zU|L=Br@zC^^6s(x()OX|{XAm41FV+X3+c~Ir&}O2p4ufPR`q^Pgsb{g&zC1lS@wEY zpXwkz1PT_b>I=tJxj1UQ$hPDf+}!En`@h4+T6x_2-aGz_^8J6;K1Z$SyuA)wq~(?~ zjhZ{63V(B&6LL9X$7m5LFnW1mF)9x8`(tEt=WSq1hko+&n; z%7;WnKcmp%Dl4^)HWW9+n9G9 zoph;KiqV)rYsR99Tq$5FG&+WHR-FwaEzhlJ=XtuavZ@5BO_a{{f>TTLN1N}hqqqw~ zP@>jtdD?}M43;oZr$5=xp+TULc!13l4-g$3d7g-VXy?}Pbt;2rx;WQfKA-1$ci)V* zN-GdMe9gpP&|%R2T@=%u?w%8?gQYZa=;&`j;`FiC`M;$0{vOT9 z=ryw%o0|)cKbmWL5U!Rc#kX*7w0O#tRKZ(Tk|Z@@j-VJ7&z!ZEoshf1#q@*TjxW%j zhk=S--#Fm*G5p;i15{{Xf3__*&+mW2ZAg3c;jB=tIw<+ivh}|M>sUgkto1@o;x+MIK9>H` zDv9~Zt@$^;S^CSwJNa`r=Ur(E^Q#Y2ney7|$hlm!=)QfH%elO4x29v!@3RV7(pN{C ztn$xs6|1fzK5&E&jb&H12sq7zWs}QIZa;kQ@i6P#=YD^%o^)A>gLYN9UC>X({9elJ z=&D?nBWW&4; zuQ6BTu#D$d1NEP&b9U|{ZHixa9+cFMAFs)1uheFf>FSK_XZU~H@jPqN^1U-d(GfaM zYs~jOL*{d*5_I-6ll2~ zjjh|OM*9|<@$Z}LDi$n)rU{rh1E`~u2Om{l71WiO4_+oLvYozGKD*2yzJ2GjK34rD z<$AkLXHi*xeeGN~ZzD@{U(v;LO?$zfpQgj7(PPuFowX}#GNgFr@8@V?)z%`BAbhi< zlk#V`;iByGeF-L8s8Y3F57ciwpP|=r^=|p7*PhxKjW`-X6SVg|eC_)oTMxkV>-=-- z&&_(E3!v-=EAYl8v~lZUH?)yU)E{b$&8E?6N>}V%ql(cszA}#97+0D1N1wSd^&Wox ztMq$)I{grJSU_sa!wRe#xP`(wV;E;0+AXvw%;qd27_K`dRP#3|+e0ggPL^XfCTv98 z;f*1dTky2wimXRsX1ysAyFM%W@1NDHp7hR-JMr&NZ#`S&z0%HuBKA7eWDG&`Q+a+qzE zx0+4s-i!+eh2g%;<~^Y(}f>D`btKLGvTJOz_W zUQc?ed-?73XXs*4+!Isk1IDd9GHt ziuTn!63eedfr;0yxk+R(WRmD18k?%6S2uJ`3jR{^{m@c}Ot4*8(I=-2%X7?{E6c-6 z3TQORX#{!vqqCFD8eQ_3&pW?$%Gxe>eLK3-@}9xxeUQ%eaq|4}uN|#FKvS(lqQla8 z`}8YAMxbakg9u2;?Ht`xD$^+&%=&n|yVUZ2>ho@CCtB0y`#NtY+Vu}3-qu2$M!r>C zy&E*=*CYx=hR|`4qhMONsWAvVl4RD4lKqc#}yhLx$vB{KV5Y!AJw)hsP^T=d}naBxKe# zK$KREsoBnLOiQ3BL-8!Aj8!)ihT@!F9DOzJ=1>ZRgkQ{FSGufPXiJs?gR}+hz)572 zPTDT%S7ed6&pgue{?1P}tkwB~t~8(?~+gX-q_)9UllZhuTo>u`OV zRpz6t(gUCntPV>9uBS4J%grs%{neFJVm@MIASPpmv21j-)tl6#st1njMFsxIFomAP|?wIdM!D+^l|L? zsTK0JT|P&?b)V1{rqek%URI3NhM84qW#WqkLRxjO8R|H4)aKyKO0reGmLo51=hYs6 zY>=q)9oi1VjlsAVSV42MS%Mi@<$+^L>$g2f*}7NfQfwr`h&Sc0E87TKQ#YYhMV)Z5 zb8(Ui?1DIH=oNMeD?(-HF#T{3qmecgN$f^(r)mkwuYolJ8(~NjCNM+>kF!8}&ox=< zv3Hdc@ZgCZI?zJ%HPz=zcZK%(c~+jbXD8jsnDl&r-b+qv=X$%Jp8B01H&M~(xhM+N zVdz5CV!KHeDJDu!EWyviviy#0EfFIQj5=+887=56ie zeyr}7v|8FVKW*^bBz#59Q6XvqDN3-4@fw2E5-w=4tUCg&T35OPlv=|FU5>o-DXUQ1 zDlJ-=-I~ixH!R4Tat{qip%pCq2!`v+2_i79zWFQPetm!pTYV)*PrPQ_-Xau%jg1?99c8I zW!lx+Nf#5uD1wlff>=^SdE>o5BPr^5^t`W)^_)J(p?Tih6|(#Jx_fzFs5)cs{rgio zS~oLLa=}2ez>x(iC!0{YYQMyiFk$6P2&YD1^R$VuhRaCH(Q}GASBWH449gV6 zv5Z{#MAh0Tw2KG}G>V->h!xyi>hUG`%g*+eZjA`VOq3TR(6!?^>ye%`{W5!NIq6IS zO*}0nX(%#-NYkWZ%-{*jXaYRU~hW$zDZN6i{8EHXfI*Ut-p0NEJ;uot4 zmIp&I0N!`*MHF8s>EQfp z>v+aeTlR@>70evvJt@_q#i88YO}zgAT~{xrjy;NlfDJ-`v!?6w#_RKJD<_m~&LKg= zG34}hTprf@&-Sj#=bp#R?Ixa|&fl}T+t)fBs!}C_6jW%RR+8KXta<>Wb)*b z5wuGaM5SDi4|#`}5LMAoRAqKVaEc17l_hUSXtgeOE!}}w^Rsg@8gw#_Rv|@o%~T<( z6?B;oV85GrJ$owp<->DT{+3%B9%1cv(`7B0w4ZY+?4q8NxY19fIxwtrW%5ARzmvURAj&VJ z9%R&!qZ(HaQJ10KLYuB@8O_wwhtgD?D6?cMG~FEI^m6f(rP5XrYQ8;}a{3Q>eI17% zpm|JxqvDwG^f>Qqn|{sjuFY=56wA<*)l3>)NzAGT?CW! zw=b{gSBz4TiKPWOTu~_vQ#!+uXABpUO19radh*8Pddp{=qBG7Tla!#X#KTz{$n}#+ zNO=(I(rAotc@8hMGOMfc5s6)O4Tl-IlGv1_8Ts%5sSiC^UZj+Y5LY*O$YWZ z{S9ooMM|O<%<6%?#o<1O2c2|7RXXZx%#)*(R$RST&sv9OY?zfX z4b@^}dgaw*I&GbaMi zMo~zir^cHcnqAIeOs43}8=^KMnzdk3o!Pt1T2Lne)JpIcgcN$83LJ!HQZbDe$D)l} zNg)RU7hZS$o_Z`$4V$3P(N!*Fqeue`G`e06dKlCig^5G<;u*=U1O%unK=Y+7nXv^y zsCc5XUJ2+#8%$b;dFMAN7R<%6b>)2#eKO0khjQ6N2bflKVqc^*k>_OqPZvX&(tlGHHEI8*=)XFc|l}TkuYKvZWIKFDjeAtvVVp^#q zn^daEJb^BFgloYni8tq^wPj-NuEitJQr`y^wLsmAA`cU3G(VLL^ZAS6ji`mXSkobq zZDP98#@=30)z9PoyqG%6Ln`d1>AE4C>*LB^S+>Z_jf|D0I$o8FA%KQfk`86}B!AF} zUs6l%(x#;wHuYX_Q_(p+6>#gIwpdtNr)J$&ihzoW>PsWT9a-kk(jI2LxLwzptwW$v zw5&A2EMpljWSgP3l9a5008p9&5vi4lCpQj&QN#>m%r}bbL6y04n=B6p$>pqE<%5L| z)M{p)BhXmU})`1(<^} zsDX_FqKf?Lq_Vf7gMPCs+QM&qTV`3OJnbagk_xyX_npedD#3-7l@*Y-fX^>I>E`o3 zo^_N(wM7gAWzBTO1>v2lAbh(JF&}Q=PTHx{^ptu(QctV&nsgJaPTV*oqK1~AlhfMq z`h1nSvNGVZkiZGn(yKrPfzLP)H+UPPerQDhOoh7SUm~gh88% z(?{Z5cc2rcT6JWL#SzpxDrA8aun}-+qp_q(4!NhJfb)LNb`0fh0tzgB5XsTEInTw7d?5K5Tomwz>{BoA)0+(9Cr&7p} zW^I8>aJBPYT>0te4|sWR^WbD;#pj&~ntA7XVUg+O$93|ktnOq{MD7&k^G=y&EhKfA zPAMwLA6||B0B`g5{)1k8ARQT2Fe7(ULId=dg`8)srtcteLZgUKQqkfI0rJ2 z)fZPjmU4X@sA@C`5}9T&24z&K6_$c3Wu;h*M9!Bw7a`b!?Ol`vKQe_YI(fXLV>ht} z%ciI&IVu5?i_G^-+N z<7wFzVZt&p4IaUvCW4lk1J|HEn>mnAvow~B@!A!lD>cpX=mHjIbtJ-x7gd`Sp^ha| zcLMBb21%Mqvqq#E<7dSLIz?{{(wnKh$ASALv9M`RqINpfXke~Lb+7}VfHg(UftMaE7Xa! zUs;1bVXdz%tjw0WXHux86V)aG5{s87QqU=ZQ^tqj$0t*4mOiJ^!{aga2uih8(l4~Fa`BK&b6-5Pu172_0Y}QWW3wODYm~Fdc0sJL>yEdxo6>u{lA3;P&FkeM*PDk@`SbvehE#}LqFGxu z8l4L%m&-m;cn;>8Zei%Vm&sSJF-j_XTc{i9Y`rV+d81K)R6r>hRXIe}mGwx&&|tbi z8Q^|LZxND~19sC~M&BI`xwV88%ThIkV(WKANVF64-AY_ld1Vb)Qbl3|WhA673CY6( z`YaU}9h#6yIDwetCD81b)laal z;IL8Ra`y1NzLsrz6wb9HtesS=BUW3NFlmi@Fv=)8T@HIeXaO%OE3ku5_VPhxG9`^bE z;pu$mfq7p{i?_b{5WvcGHPfds#7b z!SV;Pl*6idDjUw^NLdHkbaG^Q`pcq9s?)2PmsE9q+&8l4`Fqeqy-2c|&;_SZAQa0S zxUzK_p=1qGPHZHKbTkIhT@+QE#k)x4_@^Z!Iy%4I1p}5WnXN@EeNu4tNv?rIG|Yth z1D8uMEG?mk%UUt-FcO~~@jN=rE-Pa#ZH%lK+6#I52c3qS)O7^Vx|6QIJ{w;yX-kK1 zEReQX(Ez0^NFwE5wz<-$4<2euaN>c4-kFjx0d-7AXI!9FoO1UILedKyGOW>N9B7b5 z1^Rx~$;vYls11EXP|D_nI5N4{q*Eg46~U22IeAes4>jk_Vxg`=GCj?v;>sx%kyV)w zGpd25!%nKTSFJ}4@I`Df<+3@2M_ja1tBq%oEEP_Yny6Hcgf8YYbS3A_bh|4oD{7kn z#T8f%hGgsOl1*x76EA{OJ$6IrhqU6YXvGzxZD!Sm>*?+A)Z-#8B$k}Y#f*ThT98Il zNh5+`kZ-e$>KKiTTPuBx)LIz4poc1nbBdj4Y;vYCt;XLa87QS1Yr0UHGK9+20acb* z7Uo{;v=Lm6bwtv_hSW5FMDX)g?CF#fOC6cjNZI?(r8=OcEcDnqIWzVPd5v=T_Xn&G zFGt+$>7@G7NSz?9qJ!o`8g@M5#ZlCuW)SrKb3IGSRKdMdtR)tF@!FkHh(e)-!RbV<3-^>5NWtX zXd%~8M9yYqu{KDYv!I#NAVr`ovV=89M+jpUD<4B;Ifq~)s@9k3{s>o`)-h*eMHJ`G zj7f0QFHTd;-bWDJrj_An3gLPr;d9u)4WjT`s9s77ZgrETlvZ640CZYtKynD?FdO0( zv*v?f*4a(f#9@l8w9+A&1mPriimxKAG*$o|0_NW^1T?m-S)n^YpWxJEP)=Zsvu)QE zVP+TM@Gt_RM$JhrOvhTD0ik3X$6jS~*UOKOYTUvD!HCLHTbC1r7y?LSq0EtrS2UH4 zky&L+Kr>jxQ>}5Dfx4C>=9RfW)+#gyJg(Mog?qlm+TcKrHC8RTn?Pr$&rXV446}>+^_J&c15N zYVLzdya5+DWpHh53Fucog@so%+N`9-eCPmeOG-0iRzrq35s!JUogz(nz66{Z0C?908S?VW$y-KF&MK2~5Ek={P{1kfi`CPX zPT5@*Q=hLq>eW7F1@COJULl?tu5AFus821`Bn%$QG6}OI6=mrmZZSKJk(Q%nG$j;9 z;3r$Azp4EBj9$FO&|1dos{$VtXhk3ph(K0sj9qk%CK6XDv?~T3652U~ooqxli4fZ7_zZj4k1!o||Ly#?(&?R1Os!J`rgg0=f`NdpssKtN)hZ6GPqveX=$(H63- z8FP zWsYFlrpd7pvd1$x6RpaqtqLhR4jiuiDd)~kSBHt#F(H`KnJFCZ;>RmNI{t?yJcRZy⩔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
    +inB}J%08SVn$Q5kxj`^rc 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%0DFZPeWMJU4fdPKNG{8$$ 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%0DIwS9J+Z{Y_7w19sWf3tc9GjS%N#@GC#jL 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

    9>q}*J>61Oa>W^A(L4e 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 Date: Tue, 10 Mar 2026 19:52:37 -0400 Subject: [PATCH 050/129] Add AskClaude to x402 ecosystem (#1490) AskClaude is a pay-per-question Claude AI service using x402. Supports Haiku ($0.01), Sonnet ($0.03), Opus ($0.10) with streaming. No subscription or API key needed. USDC on Base. https://askclaude.shop --- .../partners-data/askclaude/metadata.json | 7 +++++++ typescript/site/public/logos/askclaude.png | Bin 0 -> 5362 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/askclaude/metadata.json create mode 100644 typescript/site/public/logos/askclaude.png diff --git a/typescript/site/app/ecosystem/partners-data/askclaude/metadata.json b/typescript/site/app/ecosystem/partners-data/askclaude/metadata.json new file mode 100644 index 0000000000..a82ecee07a --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/askclaude/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "AskClaude", + "category": "Services/Endpoints", + "logoUrl": "/logos/askclaude.png", + "description": "Pay-per-question Claude AI service. Ask Claude Haiku ($0.01), Sonnet ($0.03), or Opus ($0.10) per question with no subscription or API key. Supports streaming. Pay with USDC on Base via x402.", + "websiteUrl": "https://askclaude.shop" +} diff --git a/typescript/site/public/logos/askclaude.png b/typescript/site/public/logos/askclaude.png new file mode 100644 index 0000000000000000000000000000000000000000..33caf15530db745504b01c6329b3e69de417acff GIT binary patch literal 5362 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 u>-O%D;3e?CBf|fWocezqO6TI1-Pl6HCCW@x Date: Wed, 11 Mar 2026 00:54:37 +0100 Subject: [PATCH 051/129] Add Run402 to ecosystem (#1456) Co-authored-by: Claude Opus 4.6 (1M context) --- .../site/app/ecosystem/partners-data/run402/metadata.json | 7 +++++++ typescript/site/public/logos/run402.svg | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/run402/metadata.json create mode 100644 typescript/site/public/logos/run402.svg diff --git a/typescript/site/app/ecosystem/partners-data/run402/metadata.json b/typescript/site/app/ecosystem/partners-data/run402/metadata.json new file mode 100644 index 0000000000..df9e087c42 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/run402/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Run402", + "description": "AI-native Postgres databases, REST API, auth, storage, static sites, and serverless functions β€” all payable via x402. No signups.", + "logoUrl": "/logos/run402.svg", + "websiteUrl": "https://run402.com", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/run402.svg b/typescript/site/public/logos/run402.svg new file mode 100644 index 0000000000..93f3337a92 --- /dev/null +++ b/typescript/site/public/logos/run402.svg @@ -0,0 +1,5 @@ + + + >$ + From d5fe2b7a9cfe7714a17136912e8bce64a2a49024 Mon Sep 17 00:00:00 2001 From: phdargen Date: Wed, 11 Mar 2026 09:39:04 +0900 Subject: [PATCH 052/129] chore: version typescript legacy packages (#1544) --- typescript/packages/legacy/x402-axios/package.json | 2 +- typescript/packages/legacy/x402-express/package.json | 2 +- typescript/packages/legacy/x402-fetch/package.json | 2 +- typescript/packages/legacy/x402-hono/package.json | 2 +- typescript/packages/legacy/x402-next/package.json | 2 +- typescript/packages/legacy/x402/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/typescript/packages/legacy/x402-axios/package.json b/typescript/packages/legacy/x402-axios/package.json index a01b89e730..59d7c191e1 100644 --- a/typescript/packages/legacy/x402-axios/package.json +++ b/typescript/packages/legacy/x402-axios/package.json @@ -1,6 +1,6 @@ { "name": "x402-axios", - "version": "1.1.0", + "version": "1.2.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/legacy/x402-express/package.json b/typescript/packages/legacy/x402-express/package.json index f4bec6691d..a27ee14af6 100644 --- a/typescript/packages/legacy/x402-express/package.json +++ b/typescript/packages/legacy/x402-express/package.json @@ -1,6 +1,6 @@ { "name": "x402-express", - "version": "1.1.0", + "version": "1.2.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/legacy/x402-fetch/package.json b/typescript/packages/legacy/x402-fetch/package.json index c45173373e..9ee5ac84a9 100644 --- a/typescript/packages/legacy/x402-fetch/package.json +++ b/typescript/packages/legacy/x402-fetch/package.json @@ -1,6 +1,6 @@ { "name": "x402-fetch", - "version": "1.1.0", + "version": "1.2.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/legacy/x402-hono/package.json b/typescript/packages/legacy/x402-hono/package.json index 760203999e..b69cd019b6 100644 --- a/typescript/packages/legacy/x402-hono/package.json +++ b/typescript/packages/legacy/x402-hono/package.json @@ -1,6 +1,6 @@ { "name": "x402-hono", - "version": "1.1.0", + "version": "1.2.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/legacy/x402-next/package.json b/typescript/packages/legacy/x402-next/package.json index 7e502e52d1..c2ebebfdcd 100644 --- a/typescript/packages/legacy/x402-next/package.json +++ b/typescript/packages/legacy/x402-next/package.json @@ -1,6 +1,6 @@ { "name": "x402-next", - "version": "1.1.0", + "version": "1.2.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/legacy/x402/package.json b/typescript/packages/legacy/x402/package.json index cd5a86d4f3..a180d01184 100644 --- a/typescript/packages/legacy/x402/package.json +++ b/typescript/packages/legacy/x402/package.json @@ -1,6 +1,6 @@ { "name": "x402", - "version": "1.1.0", + "version": "1.2.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", From 4a31a6318e0e3018e6fa89bc847ff00f8085680b Mon Sep 17 00:00:00 2001 From: Keepeeto - ETHERCODE <95889492+CryptoFamilyNFT@users.noreply.github.com> Date: Wed, 11 Mar 2026 02:58:26 +0100 Subject: [PATCH 053/129] Add OOBE Protocol to ecosystem directory (#1548) --- .../partners-data/oobe-protocol/metadata.json | 7 +++++++ typescript/site/public/logos/oobe-protocol.png | Bin 0 -> 85037 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/oobe-protocol/metadata.json create mode 100644 typescript/site/public/logos/oobe-protocol.png diff --git a/typescript/site/app/ecosystem/partners-data/oobe-protocol/metadata.json b/typescript/site/app/ecosystem/partners-data/oobe-protocol/metadata.json new file mode 100644 index 0000000000..dce326f086 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/oobe-protocol/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "OOBE Protocol & Synapse", + "category": "Infrastructure & Tooling", + "logoUrl": "/logos/oobe-protocol.png", + "description": "Decentralized protocol for AI agent identity, discovery, and reputation on Solana. Agents register on-chain via indexed PDAs, publish capabilities, and are discovered trustlessly. Synapse, its TypeScript SDK, enables agent registration, transaction building, and x402 micropayments β€” each agent stores an x402Endpoint in its PDA for automatic per-call payments with SOL or USDC.", + "websiteUrl": "https://oobeprotocol.ai" +} diff --git a/typescript/site/public/logos/oobe-protocol.png b/typescript/site/public/logos/oobe-protocol.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2e53ba61bd348d790023b5ce3d4f5290ab211d GIT binary patch literal 85037 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

    &mLMmf- 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 Date: Tue, 10 Mar 2026 18:59:57 -0700 Subject: [PATCH 054/129] Add Stakevia to ecosystem (Client-Side Integrations) (#1539) --- .../partners-data/stakevia/metadata.json | 7 +++++++ typescript/site/public/logos/stakevia.png | Bin 0 -> 15356 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/stakevia/metadata.json create mode 100644 typescript/site/public/logos/stakevia.png diff --git a/typescript/site/app/ecosystem/partners-data/stakevia/metadata.json b/typescript/site/app/ecosystem/partners-data/stakevia/metadata.json new file mode 100644 index 0000000000..77cf4073bb --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/stakevia/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Stakevia", + "category": "Client-Side Integrations", + "logoUrl": "/logos/stakevia.png", + "description": "AI-powered Solana validator intelligence. Pay $1 USDC per report via x402 for scoring, risk analysis, and stake simulations across 1,000+ validators.", + "websiteUrl": "https://stakevia.xyz" +} \ No newline at end of file diff --git a/typescript/site/public/logos/stakevia.png b/typescript/site/public/logos/stakevia.png new file mode 100644 index 0000000000000000000000000000000000000000..7bdd39ee1cd63e87dd0a39c60656474f502da929 GIT binary patch literal 15356 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 literal 0 HcmV?d00001 From 4178ed96704010c547f0caac252b69361ab0b6fb Mon Sep 17 00:00:00 2001 From: Sean B Date: Tue, 10 Mar 2026 22:06:05 -0400 Subject: [PATCH 055/129] Add Octomil to ecosystem (Services/Endpoints) (#1538) Octomil is an on-device ML inference platform exposed as an x402-gated MCP server. Agents pay per tool call (code generation, code review, inference, benchmarking) and payments are batch-settled via settle402. - Website: https://octomil.com - MCP server: octomil mcp serve --x402 - 60+ models, auto engine selection (MLX, llama.cpp, ONNX) --- .../site/app/ecosystem/partners-data/octomil/metadata.json | 7 +++++++ typescript/site/public/logos/octomil.svg | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/octomil/metadata.json create mode 100644 typescript/site/public/logos/octomil.svg diff --git a/typescript/site/app/ecosystem/partners-data/octomil/metadata.json b/typescript/site/app/ecosystem/partners-data/octomil/metadata.json new file mode 100644 index 0000000000..3d413bbf04 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/octomil/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Octomil", + "description": "On-device ML inference as an x402-gated MCP server. Agents pay per tool call to run LLMs locally β€” code generation, code review, inference, model benchmarking, and more. Payments are accumulated and batch-settled via settle402.", + "logoUrl": "/logos/octomil.svg", + "websiteUrl": "https://octomil.com", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/octomil.svg b/typescript/site/public/logos/octomil.svg new file mode 100644 index 0000000000..77ab9843ed --- /dev/null +++ b/typescript/site/public/logos/octomil.svg @@ -0,0 +1,4 @@ + + + octomil + From db321ae06488f3399e964f9b23853a4243604f67 Mon Sep 17 00:00:00 2001 From: Giacomo Barbieri Date: Wed, 11 Mar 2026 17:46:50 +0100 Subject: [PATCH 056/129] feat(ecosystem): add WalletIQ wallet intelligence API (#1552) WalletIQ is a wallet intelligence API for EVM addresses. One x402 call (/bin/zsh.005 USDC on Base) returns a full wallet profile including age, activity stats, DeFi protocol usage, risk score, and behavioral labels across 5+ chains. Category: Services/Endpoints Endpoint: https://walletiq-zeta.vercel.app/api/v1/x402/profile/{address} Network: Base mainnet (USDC) Scheme: exact (x402 v2) --- .../partners-data/walletiq/metadata.json | 7 +++++++ typescript/site/public/logos/walletiq.png | Bin 0 -> 3411 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/walletiq/metadata.json create mode 100644 typescript/site/public/logos/walletiq.png diff --git a/typescript/site/app/ecosystem/partners-data/walletiq/metadata.json b/typescript/site/app/ecosystem/partners-data/walletiq/metadata.json new file mode 100644 index 0000000000..e5bd3f9ee8 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/walletiq/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "WalletIQ", + "description": "Wallet intelligence API for EVM addresses. One x402 call returns a full wallet profile: age, activity stats, DeFi protocol usage, risk score, and behavioral labels across 5+ chains. Pay $0.005 USDC per lookup on Base β€” no API key or signup required.", + "logoUrl": "/logos/walletiq.png", + "websiteUrl": "https://walletiq-zeta.vercel.app", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/walletiq.png b/typescript/site/public/logos/walletiq.png new file mode 100644 index 0000000000000000000000000000000000000000..94b7bf290677cd57dd7385092cff7cc1489b7e6a GIT binary patch literal 3411 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 SFFW)02-d({zx0C3?SBIzuP$u> literal 0 HcmV?d00001 From ab5628c1b7252f5be45fba13222696f1c02bd116 Mon Sep 17 00:00:00 2001 From: Ethan Oroshiba Date: Wed, 11 Mar 2026 12:08:13 -0500 Subject: [PATCH 057/129] feat: add Polygon mainnet to CDP Facilitator ecosystem entry on x402.org (#1564) Co-authored-by: Claude Sonnet 4.6 --- typescript/site/app/ecosystem/partners-data/cdp/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/site/app/ecosystem/partners-data/cdp/metadata.json b/typescript/site/app/ecosystem/partners-data/cdp/metadata.json index db0e4aceab..c6431f4693 100644 --- a/typescript/site/app/ecosystem/partners-data/cdp/metadata.json +++ b/typescript/site/app/ecosystem/partners-data/cdp/metadata.json @@ -6,7 +6,7 @@ "category": "Facilitators", "facilitator": { "baseUrl": "https://api.cdp.coinbase.com/platform/v2/x402", - "networks": ["base", "base-sepolia", "solana", "solana-devnet"], + "networks": ["base", "base-sepolia", "solana", "solana-devnet", "polygon"], "schemes": ["exact"], "assets": ["EIP-3009", "SPL"], "supports": { "verify": true, "settle": true, "supported": true, "list": true } From 713907fce8ecd13584eddedae656159eb28cc07b Mon Sep 17 00:00:00 2001 From: Carson Roscoe Date: Wed, 11 Mar 2026 16:20:20 -0700 Subject: [PATCH 058/129] fix: remove facilitator from exact scheme witness struct (#1322) * feat: remove facilitator from exact scheme witness struct The facilitator field in the witness was only needed for the upto scheme where settlement amounts are variable. For exact, the amount is always the full permitted amount so no facilitator binding is necessary. Co-authored-by: Cursor * feat: re-mine vanity salts and deploy updated contracts to Base Sepolia Exact: 0x402085c248EeA27D92E8b30b2C58ed07f9E20001 Upto: 0x402039b3d6E6BEC5A02c2C9fd937ac17A6940002 Co-authored-by: Cursor --------- Co-authored-by: Cursor --- contracts/evm/README.md | 4 +- contracts/evm/script/ComputeAddress.s.sol | 8 +- contracts/evm/script/Deploy.s.sol | 8 +- contracts/evm/src/x402BasePermit2Proxy.sol | 71 ++++------------ contracts/evm/src/x402ExactPermit2Proxy.sol | 45 +++++++++- contracts/evm/src/x402UptoPermit2Proxy.sol | 44 ++++++++-- .../test/invariants/X402ExactInvariants.t.sol | 5 +- .../test/invariants/X402UptoInvariants.t.sol | 4 +- .../test/mocks/MaliciousReentrantExact.sol | 6 +- .../evm/test/mocks/MaliciousReentrantUpto.sol | 4 +- .../evm/test/x402ExactPermit2Proxy.fork.t.sol | 43 ++++------ .../evm/test/x402ExactPermit2Proxy.t.sol | 82 ++++++++----------- .../evm/test/x402UptoPermit2Proxy.fork.t.sol | 32 ++++---- contracts/evm/test/x402UptoPermit2Proxy.t.sol | 6 +- contracts/evm/vanity-miner/src/main.rs | 4 +- specs/schemes/exact/scheme_exact_evm.md | 4 +- 16 files changed, 189 insertions(+), 181 deletions(-) diff --git a/contracts/evm/README.md b/contracts/evm/README.md index e744fb71b1..b00504883a 100644 --- a/contracts/evm/README.md +++ b/contracts/evm/README.md @@ -24,8 +24,8 @@ Both contracts: | Contract | Address | Verified | |----------|---------|----------| -| x402ExactPermit2Proxy | [`0x4020cd856c882d5fb903d99ce35316a085bb0001`](https://sepolia.basescan.org/address/0x4020cd856c882d5fb903d99ce35316a085bb0001) | βœ“ | -| x402UptoPermit2Proxy | [`0x40204513ec14919adfd30d77c0a991371b420002`](https://sepolia.basescan.org/address/0x40204513ec14919adfd30d77c0a991371b420002) | βœ“ | +| x402ExactPermit2Proxy | [`0x402085c248EeA27D92E8b30b2C58ed07f9E20001`](https://sepolia.basescan.org/address/0x402085c248EeA27D92E8b30b2C58ed07f9E20001) | βœ“ | +| x402UptoPermit2Proxy | [`0x402039b3d6E6BEC5A02c2C9fd937ac17A6940002`](https://sepolia.basescan.org/address/0x402039b3d6E6BEC5A02c2C9fd937ac17A6940002) | βœ“ | ## Prerequisites diff --git a/contracts/evm/script/ComputeAddress.s.sol b/contracts/evm/script/ComputeAddress.s.sol index be92590f2e..d7e03e33c0 100644 --- a/contracts/evm/script/ComputeAddress.s.sol +++ b/contracts/evm/script/ComputeAddress.s.sol @@ -28,12 +28,12 @@ contract ComputeAddress is Script { address constant CANONICAL_PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; /// @notice Default salt for x402ExactPermit2Proxy - /// @dev Vanity mined for address 0x4020cd856c882d5fb903d99ce35316a085bb0001 - bytes32 constant DEFAULT_EXACT_SALT = 0x0000000000000000000000000000000000000000000000002c00000003c30a30; + /// @dev Vanity mined for address 0x402085c248eea27d92e8b30b2c58ed07f9e20001 + bytes32 constant DEFAULT_EXACT_SALT = 0x0000000000000000000000000000000000000000000000003000000007263b0e; /// @notice Default salt for x402UptoPermit2Proxy - /// @dev Vanity mined for address 0x40204513ec14919adfd30d77c0a991371b420002 - bytes32 constant DEFAULT_UPTO_SALT = 0x00000000000000000000000000000000000000000000000084000000275d7dbb; + /// @dev Vanity mined for address 0x402039b3d6e6bec5a02c2c9fd937ac17a6940002 + bytes32 constant DEFAULT_UPTO_SALT = 0x0000000000000000000000000000000000000000000000000000000000edb738; /** * @notice Computes the CREATE2 addresses using the default salts diff --git a/contracts/evm/script/Deploy.s.sol b/contracts/evm/script/Deploy.s.sol index ee758bea09..2f0dce6e60 100644 --- a/contracts/evm/script/Deploy.s.sol +++ b/contracts/evm/script/Deploy.s.sol @@ -29,12 +29,12 @@ contract DeployX402Proxies is Script { address constant CREATE2_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C; /// @notice Salt for x402ExactPermit2Proxy deterministic deployment - /// @dev Vanity mined for address 0x4020cd856c882d5fb903d99ce35316a085bb0001 - bytes32 constant EXACT_SALT = 0x0000000000000000000000000000000000000000000000002c00000003c30a30; + /// @dev Vanity mined for address 0x402085c248eea27d92e8b30b2c58ed07f9e20001 + bytes32 constant EXACT_SALT = 0x0000000000000000000000000000000000000000000000003000000007263b0e; /// @notice Salt for x402UptoPermit2Proxy deterministic deployment - /// @dev Vanity mined for address 0x40204513ec14919adfd30d77c0a991371b420002 - bytes32 constant UPTO_SALT = 0x00000000000000000000000000000000000000000000000084000000275d7dbb; + /// @dev Vanity mined for address 0x402039b3d6e6bec5a02c2c9fd937ac17a6940002 + bytes32 constant UPTO_SALT = 0x0000000000000000000000000000000000000000000000000000000000edb738; function run() public { // Allow override of Permit2 address for chains with non-canonical deployments diff --git a/contracts/evm/src/x402BasePermit2Proxy.sol b/contracts/evm/src/x402BasePermit2Proxy.sol index c180bd7a9f..46c6c8863a 100644 --- a/contracts/evm/src/x402BasePermit2Proxy.sol +++ b/contracts/evm/src/x402BasePermit2Proxy.sol @@ -28,15 +28,6 @@ abstract contract x402BasePermit2Proxy is ReentrancyGuard { /// @notice The Permit2 contract address (set once at construction, immutable) ISignatureTransfer public immutable PERMIT2; - /// @notice EIP-712 type string for witness data - /// @dev Must match the exact format expected by Permit2 - /// Types must be in ALPHABETICAL order after the primary type (TokenPermissions < Witness) - string public constant WITNESS_TYPE_STRING = - "Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,address facilitator,uint256 validAfter)"; - - /// @notice EIP-712 typehash for witness struct - bytes32 public constant WITNESS_TYPEHASH = keccak256("Witness(address to,address facilitator,uint256 validAfter)"); - /// @notice Emitted when settle() completes successfully event Settled(); @@ -79,24 +70,6 @@ abstract contract x402BasePermit2Proxy is ReentrancyGuard { /// @notice Thrown when EIP-2612 permit value doesn't match Permit2 permitted amount error Permit2612AmountMismatch(); - /// @notice Thrown when msg.sender does not match the facilitator in the witness - error UnauthorizedFacilitator(); - - /** - * @notice Witness data structure for payment authorization - * @param to Destination address (immutable once signed) - * @param facilitator Address authorized to settle this payment (must be msg.sender) - * @param validAfter Earliest timestamp when payment can be settled - * @dev The upper time bound is enforced by Permit2's deadline field. - * The facilitator field prevents frontrunning/griefing by binding the - * settlement caller to the payer's signature. - */ - struct Witness { - address to; - address facilitator; - uint256 validAfter; - } - /** * @notice EIP-2612 permit parameters grouped to reduce stack depth * @param value Approval amount for Permit2 @@ -129,43 +102,37 @@ abstract contract x402BasePermit2Proxy is ReentrancyGuard { /** * @notice Internal settlement logic shared by all settlement functions - * @dev Validates all parameters and executes the Permit2 transfer + * @dev Validates common parameters and executes the Permit2 witness transfer. + * Each child contract computes its own witnessHash and witnessTypeString + * based on its Witness struct definition. * @param permit The Permit2 transfer authorization * @param settlementAmount The actual amount to transfer (may be <= permit.permitted.amount) * @param owner The token owner (payer) - * @param witness The witness data containing destination and validity window + * @param to The destination address for the transfer + * @param validAfter Earliest timestamp when payment can be settled + * @param witnessHash The EIP-712 hash of the child's witness struct + * @param witnessTypeString The EIP-712 type string for the child's witness * @param signature The payer's signature */ function _settle( ISignatureTransfer.PermitTransferFrom calldata permit, uint256 settlementAmount, address owner, - Witness calldata witness, + address to, + uint256 validAfter, + bytes32 witnessHash, + string memory witnessTypeString, bytes calldata signature ) internal { - // Validate amount is non-zero to prevent no-op settlements that consume nonces if (settlementAmount == 0) revert InvalidAmount(); - - // Validate addresses if (owner == address(0)) revert InvalidOwner(); - if (witness.to == address(0)) revert InvalidDestination(); - - // Validate caller is the authorized facilitator signed over by the payer - if (msg.sender != witness.facilitator) revert UnauthorizedFacilitator(); + if (to == address(0)) revert InvalidDestination(); + if (block.timestamp < validAfter) revert PaymentTooEarly(); - // Validate time window (upper bound enforced by Permit2's deadline) - if (block.timestamp < witness.validAfter) revert PaymentTooEarly(); - - // Prepare transfer details with destination from witness ISignatureTransfer.SignatureTransferDetails memory transferDetails = - ISignatureTransfer.SignatureTransferDetails({to: witness.to, requestedAmount: settlementAmount}); - - // Reconstruct witness hash to enforce integrity - bytes32 witnessHash = - keccak256(abi.encode(WITNESS_TYPEHASH, witness.to, witness.facilitator, witness.validAfter)); + ISignatureTransfer.SignatureTransferDetails({to: to, requestedAmount: settlementAmount}); - // Execute transfer via Permit2 - PERMIT2.permitWitnessTransferFrom(permit, transferDetails, owner, witnessHash, WITNESS_TYPE_STRING, signature); + PERMIT2.permitWitnessTransferFrom(permit, transferDetails, owner, witnessHash, witnessTypeString, signature); } /** @@ -184,21 +151,19 @@ abstract contract x402BasePermit2Proxy is ReentrancyGuard { EIP2612Permit calldata permit2612, uint256 permittedAmount ) internal { - if (permit2612.value != permittedAmount) revert Permit2612AmountMismatch(); + if (permit2612.value != permittedAmount) { + revert Permit2612AmountMismatch(); + } try IERC20Permit(token).permit( owner, address(PERMIT2), permit2612.value, permit2612.deadline, permit2612.v, permit2612.r, permit2612.s ) { // EIP-2612 permit succeeded } catch Error(string memory reason) { - // Legacy revert(string) or require(condition, string) β€” e.g. older token implementations emit EIP2612PermitFailedWithReason(token, owner, reason); } catch Panic(uint256 errorCode) { - // Solidity panic β€” e.g. arithmetic overflow in non-standard implementations emit EIP2612PermitFailedWithPanic(token, owner, errorCode); } catch (bytes memory data) { - // Custom errors (e.g. OZ v5 ERC2612ExpiredSignature, ERC2612InvalidSigner), - // empty reverts, or out-of-gas from non-EIP-2612 tokens emit EIP2612PermitFailedWithData(token, owner, data); } } diff --git a/contracts/evm/src/x402ExactPermit2Proxy.sol b/contracts/evm/src/x402ExactPermit2Proxy.sol index 44083c1992..56e0e5a4a1 100644 --- a/contracts/evm/src/x402ExactPermit2Proxy.sol +++ b/contracts/evm/src/x402ExactPermit2Proxy.sol @@ -12,12 +12,29 @@ import {ISignatureTransfer} from "./interfaces/ISignatureTransfer.sol"; * It uses the "witness" pattern to cryptographically bind the payment destination, * preventing facilitators from redirecting funds. * - * Unlike x402UptoPermit2Proxy, this contract always transfers the EXACT permitted - * amount, similar to EIP-3009's transferWithAuthorization behavior. + * This contract always transfers the EXACT permitted amount, similar to + * EIP-3009's transferWithAuthorization behavior. * * @author x402 Protocol */ contract x402ExactPermit2Proxy is x402BasePermit2Proxy { + /// @notice EIP-712 type string for witness data + string public constant WITNESS_TYPE_STRING = + "Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,uint256 validAfter)"; + + /// @notice EIP-712 typehash for witness struct + bytes32 public constant WITNESS_TYPEHASH = keccak256("Witness(address to,uint256 validAfter)"); + + /** + * @notice Witness data structure for payment authorization + * @param to Destination address (immutable once signed) + * @param validAfter Earliest timestamp when payment can be settled + */ + struct Witness { + address to; + uint256 validAfter; + } + constructor( address _permit2 ) x402BasePermit2Proxy(_permit2) {} @@ -37,7 +54,17 @@ contract x402ExactPermit2Proxy is x402BasePermit2Proxy { Witness calldata witness, bytes calldata signature ) external nonReentrant { - _settle(permit, permit.permitted.amount, owner, witness, signature); + bytes32 witnessHash = keccak256(abi.encode(WITNESS_TYPEHASH, witness.to, witness.validAfter)); + _settle( + permit, + permit.permitted.amount, + owner, + witness.to, + witness.validAfter, + witnessHash, + WITNESS_TYPE_STRING, + signature + ); emit Settled(); } @@ -63,7 +90,17 @@ contract x402ExactPermit2Proxy is x402BasePermit2Proxy { bytes calldata signature ) external nonReentrant { _executePermit(permit.permitted.token, owner, permit2612, permit.permitted.amount); - _settle(permit, permit.permitted.amount, owner, witness, signature); + bytes32 witnessHash = keccak256(abi.encode(WITNESS_TYPEHASH, witness.to, witness.validAfter)); + _settle( + permit, + permit.permitted.amount, + owner, + witness.to, + witness.validAfter, + witnessHash, + WITNESS_TYPE_STRING, + signature + ); emit SettledWithPermit(); } } diff --git a/contracts/evm/src/x402UptoPermit2Proxy.sol b/contracts/evm/src/x402UptoPermit2Proxy.sol index fc03b23a06..236e9e858d 100644 --- a/contracts/evm/src/x402UptoPermit2Proxy.sol +++ b/contracts/evm/src/x402UptoPermit2Proxy.sol @@ -12,20 +12,42 @@ import {ISignatureTransfer} from "./interfaces/ISignatureTransfer.sol"; * It uses the "witness" pattern to cryptographically bind the payment destination, * preventing facilitators from redirecting funds. * - * Unlike x402ExactPermit2Proxy, this contract allows the facilitator to specify - * how much to transfer (up to the permitted amount), useful for scenarios where - * the actual amount is determined at settlement time. + * This contract allows the facilitator to transfer up to the permitted amount. + * The witness includes a facilitator field so only the authorized caller can + * choose the final settlement amount. * * @author x402 Protocol */ contract x402UptoPermit2Proxy is x402BasePermit2Proxy { - constructor( - address _permit2 - ) x402BasePermit2Proxy(_permit2) {} + /// @notice EIP-712 type string for witness data + string public constant WITNESS_TYPE_STRING = + "Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,address facilitator,uint256 validAfter)"; + + /// @notice EIP-712 typehash for witness struct + bytes32 public constant WITNESS_TYPEHASH = keccak256("Witness(address to,address facilitator,uint256 validAfter)"); + + /// @notice Thrown when msg.sender does not match the facilitator in the witness + error UnauthorizedFacilitator(); /// @notice Thrown when requested amount exceeds permitted amount error AmountExceedsPermitted(); + /** + * @notice Witness data structure for payment authorization + * @param to Destination address (immutable once signed) + * @param facilitator Address authorized to settle this payment (must be msg.sender) + * @param validAfter Earliest timestamp when payment can be settled + */ + struct Witness { + address to; + address facilitator; + uint256 validAfter; + } + + constructor( + address _permit2 + ) x402BasePermit2Proxy(_permit2) {} + /** * @notice Settles a payment using a Permit2 signature * @dev This is the standard settlement path when user has already approved Permit2 @@ -43,7 +65,10 @@ contract x402UptoPermit2Proxy is x402BasePermit2Proxy { bytes calldata signature ) external nonReentrant { if (amount > permit.permitted.amount) revert AmountExceedsPermitted(); - _settle(permit, amount, owner, witness, signature); + if (msg.sender != witness.facilitator) revert UnauthorizedFacilitator(); + bytes32 witnessHash = + keccak256(abi.encode(WITNESS_TYPEHASH, witness.to, witness.facilitator, witness.validAfter)); + _settle(permit, amount, owner, witness.to, witness.validAfter, witnessHash, WITNESS_TYPE_STRING, signature); emit Settled(); } @@ -70,8 +95,11 @@ contract x402UptoPermit2Proxy is x402BasePermit2Proxy { bytes calldata signature ) external nonReentrant { if (amount > permit.permitted.amount) revert AmountExceedsPermitted(); + if (msg.sender != witness.facilitator) revert UnauthorizedFacilitator(); _executePermit(permit.permitted.token, owner, permit2612, permit.permitted.amount); - _settle(permit, amount, owner, witness, signature); + bytes32 witnessHash = + keccak256(abi.encode(WITNESS_TYPEHASH, witness.to, witness.facilitator, witness.validAfter)); + _settle(permit, amount, owner, witness.to, witness.validAfter, witnessHash, WITNESS_TYPE_STRING, signature); emit SettledWithPermit(); } } diff --git a/contracts/evm/test/invariants/X402ExactInvariants.t.sol b/contracts/evm/test/invariants/X402ExactInvariants.t.sol index 74c6407bd9..9c20f7133f 100644 --- a/contracts/evm/test/invariants/X402ExactInvariants.t.sol +++ b/contracts/evm/test/invariants/X402ExactInvariants.t.sol @@ -45,12 +45,11 @@ contract X402ExactHandler is Test { deadline: t + 3600 }); - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t > 60 ? t - 60 : 0}); + x402ExactPermit2Proxy.Witness memory witness = + x402ExactPermit2Proxy.Witness({to: recipient, validAfter: t > 60 ? t - 60 : 0}); bytes memory sig = abi.encodePacked(bytes32(uint256(1)), bytes32(uint256(2)), uint8(27)); - // Exact variant has no amount parameter - always transfers the full permitted amount try proxy.settle(permit, payer, witness, sig) { totalSettled += amount; settleCallCount++; diff --git a/contracts/evm/test/invariants/X402UptoInvariants.t.sol b/contracts/evm/test/invariants/X402UptoInvariants.t.sol index 534fa8c96c..038d820126 100644 --- a/contracts/evm/test/invariants/X402UptoInvariants.t.sol +++ b/contracts/evm/test/invariants/X402UptoInvariants.t.sol @@ -45,8 +45,8 @@ contract X402UptoHandler is Test { deadline: t + 3600 }); - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t > 60 ? t - 60 : 0}); + x402UptoPermit2Proxy.Witness memory witness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t > 60 ? t - 60 : 0}); bytes memory sig = abi.encodePacked(bytes32(uint256(1)), bytes32(uint256(2)), uint8(27)); diff --git a/contracts/evm/test/mocks/MaliciousReentrantExact.sol b/contracts/evm/test/mocks/MaliciousReentrantExact.sol index 1d44f8ad61..8d9d522d32 100644 --- a/contracts/evm/test/mocks/MaliciousReentrantExact.sol +++ b/contracts/evm/test/mocks/MaliciousReentrantExact.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import {ISignatureTransfer} from "../../src/interfaces/ISignatureTransfer.sol"; import {x402ExactPermit2Proxy} from "../../src/x402ExactPermit2Proxy.sol"; -import {x402BasePermit2Proxy} from "../../src/x402BasePermit2Proxy.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract MaliciousReentrantExact is ISignatureTransfer { @@ -12,7 +11,7 @@ contract MaliciousReentrantExact is ISignatureTransfer { ISignatureTransfer.PermitTransferFrom public storedPermit; address public storedOwner; - x402BasePermit2Proxy.Witness public storedWitness; + x402ExactPermit2Proxy.Witness public storedWitness; bytes public storedSignature; mapping(address => mapping(uint256 => uint256)) public nonceBitmapStorage; @@ -32,7 +31,7 @@ contract MaliciousReentrantExact is ISignatureTransfer { function setAttackParams( ISignatureTransfer.PermitTransferFrom calldata permit, address owner, - x402BasePermit2Proxy.Witness calldata witness, + x402ExactPermit2Proxy.Witness calldata witness, bytes calldata signature ) external { storedPermit = permit; @@ -67,7 +66,6 @@ contract MaliciousReentrantExact is ISignatureTransfer { nonceBitmapStorage[owner][wordPos] |= (1 << bitPos); if (attemptReentry && address(target) != address(0)) { - // Exact variant has no amount parameter target.settle(storedPermit, storedOwner, storedWitness, storedSignature); } diff --git a/contracts/evm/test/mocks/MaliciousReentrantUpto.sol b/contracts/evm/test/mocks/MaliciousReentrantUpto.sol index 38a4d2f019..73e6310687 100644 --- a/contracts/evm/test/mocks/MaliciousReentrantUpto.sol +++ b/contracts/evm/test/mocks/MaliciousReentrantUpto.sol @@ -13,7 +13,7 @@ contract MaliciousReentrantUpto is ISignatureTransfer { ISignatureTransfer.PermitTransferFrom public storedPermit; uint256 public storedAmount; address public storedOwner; - x402BasePermit2Proxy.Witness public storedWitness; + x402UptoPermit2Proxy.Witness public storedWitness; bytes public storedSignature; mapping(address => mapping(uint256 => uint256)) public nonceBitmapStorage; @@ -34,7 +34,7 @@ contract MaliciousReentrantUpto is ISignatureTransfer { ISignatureTransfer.PermitTransferFrom calldata permit, uint256 amount, address owner, - x402BasePermit2Proxy.Witness calldata witness, + x402UptoPermit2Proxy.Witness calldata witness, bytes calldata signature ) external { storedPermit = permit; diff --git a/contracts/evm/test/x402ExactPermit2Proxy.fork.t.sol b/contracts/evm/test/x402ExactPermit2Proxy.fork.t.sol index 66a3e367ff..9a599e12eb 100644 --- a/contracts/evm/test/x402ExactPermit2Proxy.fork.t.sol +++ b/contracts/evm/test/x402ExactPermit2Proxy.fork.t.sol @@ -15,7 +15,7 @@ contract X402ExactPermit2ProxyForkTest is Test { bytes32 constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); bytes32 constant PERMIT_TYPEHASH = keccak256( - "PermitWitnessTransferFrom(TokenPermissions permitted,address spender,uint256 nonce,uint256 deadline,Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,address facilitator,uint256 validAfter)" + "PermitWitnessTransferFrom(TokenPermissions permitted,address spender,uint256 nonce,uint256 deadline,Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,uint256 validAfter)" ); bytes32 constant TOKEN_PERMISSIONS_TYPEHASH = keccak256("TokenPermissions(address token,uint256 amount)"); @@ -35,7 +35,6 @@ contract X402ExactPermit2ProxyForkTest is Test { if (block.chainid == 31_337) return; require(PERMIT2.code.length > 0, "Permit2 not deployed"); - // Use a key that produces an EOA (not a deployed contract) on the fork payerKey = uint256(keccak256("x402-test-payer")); payer = vm.addr(payerKey); recipient = makeAddr("recipient"); @@ -68,11 +67,9 @@ contract X402ExactPermit2ProxyForkTest is Test { uint256 amount, uint256 nonce, uint256 deadline, - x402BasePermit2Proxy.Witness memory witness + x402ExactPermit2Proxy.Witness memory witness ) internal view returns (bytes memory) { - // Must match contract's witness hash computation order - bytes32 witnessHash = - keccak256(abi.encode(proxy.WITNESS_TYPEHASH(), witness.to, witness.facilitator, witness.validAfter)); + bytes32 witnessHash = keccak256(abi.encode(proxy.WITNESS_TYPEHASH(), witness.to, witness.validAfter)); bytes32 tokenHash = keccak256(abi.encode(TOKEN_PERMISSIONS_TYPEHASH, tokenAddr, amount)); @@ -90,8 +87,8 @@ contract X402ExactPermit2ProxyForkTest is Test { uint256 nonce = _nonce(1); uint256 deadline = t + 3600; - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402ExactPermit2Proxy.Witness memory witness = + x402ExactPermit2Proxy.Witness({to: recipient, validAfter: t - 60}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, witness); @@ -115,8 +112,8 @@ contract X402ExactPermit2ProxyForkTest is Test { uint256 t = block.timestamp; uint256 nonce = _nonce(2); - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402ExactPermit2Proxy.Witness memory witness = + x402ExactPermit2Proxy.Witness({to: recipient, validAfter: t - 60}); ISignatureTransfer.PermitTransferFrom memory permit = ISignatureTransfer.PermitTransferFrom({ permitted: ISignatureTransfer.TokenPermissions({token: address(token), amount: TRANSFER_AMOUNT}), @@ -135,12 +132,11 @@ contract X402ExactPermit2ProxyForkTest is Test { uint256 nonce = _nonce(3); uint256 deadline = t + 3600; - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402ExactPermit2Proxy.Witness memory witness = + x402ExactPermit2Proxy.Witness({to: recipient, validAfter: t - 60}); uint256 wrongKey = 0xdeadbeef; - bytes32 witnessHash = - keccak256(abi.encode(proxy.WITNESS_TYPEHASH(), witness.to, witness.facilitator, witness.validAfter)); + bytes32 witnessHash = keccak256(abi.encode(proxy.WITNESS_TYPEHASH(), witness.to, witness.validAfter)); bytes32 tokenHash = keccak256(abi.encode(TOKEN_PERMISSIONS_TYPEHASH, address(token), TRANSFER_AMOUNT)); bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, tokenHash, address(proxy), nonce, deadline, witnessHash)); @@ -163,8 +159,8 @@ contract X402ExactPermit2ProxyForkTest is Test { uint256 nonce = _nonce(4); uint256 deadline = t + 3600; - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402ExactPermit2Proxy.Witness memory witness = + x402ExactPermit2Proxy.Witness({to: recipient, validAfter: t - 60}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, witness); @@ -185,8 +181,8 @@ contract X402ExactPermit2ProxyForkTest is Test { uint256 nonce = _nonce(5); uint256 deadline = t - 60; // expired (Permit2's deadline enforces the upper bound) - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 120}); + x402ExactPermit2Proxy.Witness memory witness = + x402ExactPermit2Proxy.Witness({to: recipient, validAfter: t - 120}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, witness); @@ -207,8 +203,8 @@ contract X402ExactPermit2ProxyForkTest is Test { address attacker = makeAddr("attacker"); - x402BasePermit2Proxy.Witness memory signedWitness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402ExactPermit2Proxy.Witness memory signedWitness = + x402ExactPermit2Proxy.Witness({to: recipient, validAfter: t - 60}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, signedWitness); @@ -218,11 +214,8 @@ contract X402ExactPermit2ProxyForkTest is Test { deadline: deadline }); - x402BasePermit2Proxy.Witness memory tamperedWitness = x402BasePermit2Proxy.Witness({ - to: attacker, - facilitator: signedWitness.facilitator, - validAfter: signedWitness.validAfter - }); + x402ExactPermit2Proxy.Witness memory tamperedWitness = + x402ExactPermit2Proxy.Witness({to: attacker, validAfter: signedWitness.validAfter}); vm.expectRevert(); proxy.settle(permit, payer, tamperedWitness, sig); diff --git a/contracts/evm/test/x402ExactPermit2Proxy.t.sol b/contracts/evm/test/x402ExactPermit2Proxy.t.sol index 3e2e58e3db..5a6039663f 100644 --- a/contracts/evm/test/x402ExactPermit2Proxy.t.sol +++ b/contracts/evm/test/x402ExactPermit2Proxy.t.sol @@ -56,12 +56,8 @@ contract X402ExactPermit2ProxyTest is Test { }); } - function _witness( - address to, - address facilitator, - uint256 validAfter - ) internal pure returns (x402BasePermit2Proxy.Witness memory) { - return x402BasePermit2Proxy.Witness({to: to, facilitator: facilitator, validAfter: validAfter}); + function _witness(address to, uint256 validAfter) internal pure returns (x402ExactPermit2Proxy.Witness memory) { + return x402ExactPermit2Proxy.Witness({to: to, validAfter: validAfter}); } function _sig() internal pure returns (bytes memory) { @@ -84,35 +80,25 @@ contract X402ExactPermit2ProxyTest is Test { function test_settle_revertsOnZeroOwner() public { uint256 t = block.timestamp; vm.expectRevert(x402BasePermit2Proxy.InvalidOwner.selector); - proxy.settle( - _permit(TRANSFER_AMOUNT, 0, t + 3600), address(0), _witness(recipient, address(this), t - 60), _sig() - ); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), address(0), _witness(recipient, t - 60), _sig()); } function test_settle_revertsOnZeroDestination() public { uint256 t = block.timestamp; vm.expectRevert(x402BasePermit2Proxy.InvalidDestination.selector); - proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(address(0), address(this), t - 60), _sig()); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(address(0), t - 60), _sig()); } function test_settle_revertsBeforeValidAfter() public { uint256 t = block.timestamp; vm.expectRevert(x402BasePermit2Proxy.PaymentTooEarly.selector); - proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, address(this), t + 60), _sig()); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, t + 60), _sig()); } function test_settle_revertsOnZeroAmount() public { uint256 t = block.timestamp; vm.expectRevert(x402BasePermit2Proxy.InvalidAmount.selector); - proxy.settle(_permit(0, 0, t + 3600), payer, _witness(recipient, address(this), t - 60), _sig()); - } - - function test_settle_revertsOnUnauthorizedFacilitator() public { - uint256 t = block.timestamp; - address attacker = makeAddr("attacker"); - vm.prank(attacker); - vm.expectRevert(x402BasePermit2Proxy.UnauthorizedFacilitator.selector); - proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settle(_permit(0, 0, t + 3600), payer, _witness(recipient, t - 60), _sig()); } // Note: validBefore was removed - upper time bound is enforced by Permit2's deadline @@ -123,7 +109,7 @@ contract X402ExactPermit2ProxyTest is Test { uint256 t = block.timestamp; uint256 balanceBefore = token.balanceOf(recipient); - proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, t - 60), _sig()); assertEq(token.balanceOf(recipient) - balanceBefore, TRANSFER_AMOUNT); } @@ -134,12 +120,24 @@ contract X402ExactPermit2ProxyTest is Test { vm.expectEmit(false, false, false, false); emit Settled(); - proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, t - 60), _sig()); } function test_settle_atExactValidAfter() public { uint256 t = block.timestamp; - proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, address(this), t), _sig()); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, t), _sig()); + assertEq(token.balanceOf(recipient), TRANSFER_AMOUNT); + } + + // --- Security: Permissionless settlement --- + + function test_settle_anyoneCanSettle() public { + uint256 t = block.timestamp; + address anyone = makeAddr("anyone"); + + vm.prank(anyone); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, t - 60), _sig()); + assertEq(token.balanceOf(recipient), TRANSFER_AMOUNT); } @@ -161,7 +159,7 @@ contract X402ExactPermit2ProxyTest is Test { nonce: 0, deadline: t + 3600 }); - x402ExactPermit2Proxy.Witness memory witness = _witness(recipient, address(this), t - 60); + x402ExactPermit2Proxy.Witness memory witness = _witness(recipient, t - 60); maliciousPermit2.setAttemptReentry(true); maliciousPermit2.setAttackParams(permit, payer, witness, _sig()); @@ -174,7 +172,7 @@ contract X402ExactPermit2ProxyTest is Test { function test_settle_proxyNeverHoldsTokens() public { uint256 t = block.timestamp; - proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, t + 3600), payer, _witness(recipient, t - 60), _sig()); assertEq(token.balanceOf(address(proxy)), 0); } @@ -204,7 +202,7 @@ contract X402ExactPermit2ProxyTest is Test { vm.expectEmit(false, false, false, false); emit SettledWithPermit(); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); assertEq(permitToken.balanceOf(recipient), TRANSFER_AMOUNT); } @@ -232,7 +230,7 @@ contract X402ExactPermit2ProxyTest is Test { s: bytes32(uint256(2)) }); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); assertEq(permitToken.balanceOf(recipient), TRANSFER_AMOUNT); } @@ -260,7 +258,7 @@ contract X402ExactPermit2ProxyTest is Test { vm.expectEmit(true, true, false, true); emit EIP2612PermitFailedWithReason(address(permitToken), payer, "Permit failed"); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); } function test_settleWithPermit_emitsPermitFailedWithPanic() public { @@ -286,7 +284,7 @@ contract X402ExactPermit2ProxyTest is Test { vm.expectEmit(true, true, false, true); emit EIP2612PermitFailedWithPanic(address(permitToken), payer, 0x12); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); } function test_settleWithPermit_emitsPermitFailedWithData() public { @@ -312,7 +310,7 @@ contract X402ExactPermit2ProxyTest is Test { vm.expectEmit(true, true, false, false); emit EIP2612PermitFailedWithData(address(permitToken), payer, ""); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); } function test_settleWithPermit_doesNotEmitPermitFailedOnSuccess() public { @@ -336,7 +334,7 @@ contract X402ExactPermit2ProxyTest is Test { }); vm.recordLogs(); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); VmSafe.Log[] memory entries = vm.getRecordedLogs(); bytes32 reasonSig = keccak256("EIP2612PermitFailedWithReason(address,address,string)"); @@ -373,7 +371,7 @@ contract X402ExactPermit2ProxyTest is Test { }); vm.expectRevert(x402BasePermit2Proxy.InvalidAmount.selector); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); } function test_settleWithPermit_revertsWhenPermit2612ValueTooSmall() public { @@ -396,7 +394,7 @@ contract X402ExactPermit2ProxyTest is Test { }); vm.expectRevert(x402BasePermit2Proxy.Permit2612AmountMismatch.selector); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); } function test_settleWithPermit_revertsWhenPermit2612ValueTooLarge() public { @@ -419,7 +417,7 @@ contract X402ExactPermit2ProxyTest is Test { }); vm.expectRevert(x402BasePermit2Proxy.Permit2612AmountMismatch.selector); - proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settleWithPermit(permit2612, permit, payer, _witness(recipient, t - 60), _sig()); } // --- Fuzz: Time window --- @@ -430,12 +428,7 @@ contract X402ExactPermit2ProxyTest is Test { vm.warp(currentTime); - proxy.settle( - _permit(TRANSFER_AMOUNT, 0, currentTime + 3600), - payer, - _witness(recipient, address(this), validAfter), - _sig() - ); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, currentTime + 3600), payer, _witness(recipient, validAfter), _sig()); assertEq(token.balanceOf(recipient), TRANSFER_AMOUNT); } @@ -447,12 +440,7 @@ contract X402ExactPermit2ProxyTest is Test { vm.warp(currentTime); vm.expectRevert(); - proxy.settle( - _permit(TRANSFER_AMOUNT, 0, currentTime + 3600), - payer, - _witness(recipient, address(this), validAfter), - _sig() - ); + proxy.settle(_permit(TRANSFER_AMOUNT, 0, currentTime + 3600), payer, _witness(recipient, validAfter), _sig()); } // --- Fuzz: Amount (exact always transfers full permitted amount) --- @@ -464,7 +452,7 @@ contract X402ExactPermit2ProxyTest is Test { uint256 t = block.timestamp; - proxy.settle(_permit(permitted, 0, t + 3600), payer, _witness(recipient, address(this), t - 60), _sig()); + proxy.settle(_permit(permitted, 0, t + 3600), payer, _witness(recipient, t - 60), _sig()); assertEq(token.balanceOf(recipient), permitted); } diff --git a/contracts/evm/test/x402UptoPermit2Proxy.fork.t.sol b/contracts/evm/test/x402UptoPermit2Proxy.fork.t.sol index 44364e2fda..a065e19d2a 100644 --- a/contracts/evm/test/x402UptoPermit2Proxy.fork.t.sol +++ b/contracts/evm/test/x402UptoPermit2Proxy.fork.t.sol @@ -68,7 +68,7 @@ contract X402UptoPermit2ProxyForkTest is Test { uint256 amount, uint256 nonce, uint256 deadline, - x402BasePermit2Proxy.Witness memory witness + x402UptoPermit2Proxy.Witness memory witness ) internal view returns (bytes memory) { // Must match contract's witness hash computation order bytes32 witnessHash = @@ -90,8 +90,8 @@ contract X402UptoPermit2ProxyForkTest is Test { uint256 nonce = _nonce(1); uint256 deadline = t + 3600; - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402UptoPermit2Proxy.Witness memory witness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, witness); @@ -115,8 +115,8 @@ contract X402UptoPermit2ProxyForkTest is Test { uint256 t = block.timestamp; uint256 nonce = _nonce(2); - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402UptoPermit2Proxy.Witness memory witness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); ISignatureTransfer.PermitTransferFrom memory permit = ISignatureTransfer.PermitTransferFrom({ permitted: ISignatureTransfer.TokenPermissions({token: address(token), amount: TRANSFER_AMOUNT}), @@ -135,8 +135,8 @@ contract X402UptoPermit2ProxyForkTest is Test { uint256 nonce = _nonce(3); uint256 deadline = t + 3600; - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402UptoPermit2Proxy.Witness memory witness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); uint256 wrongKey = 0xdeadbeef; bytes32 witnessHash = @@ -163,8 +163,8 @@ contract X402UptoPermit2ProxyForkTest is Test { uint256 nonce = _nonce(4); uint256 deadline = t + 3600; - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402UptoPermit2Proxy.Witness memory witness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, witness); @@ -185,8 +185,8 @@ contract X402UptoPermit2ProxyForkTest is Test { uint256 nonce = _nonce(5); uint256 deadline = t - 60; // expired (Permit2's deadline enforces the upper bound) - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 120}); + x402UptoPermit2Proxy.Witness memory witness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 120}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, witness); @@ -207,8 +207,8 @@ contract X402UptoPermit2ProxyForkTest is Test { address attacker = makeAddr("attacker"); - x402BasePermit2Proxy.Witness memory signedWitness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402UptoPermit2Proxy.Witness memory signedWitness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); bytes memory sig = _sign(address(token), TRANSFER_AMOUNT, nonce, deadline, signedWitness); @@ -218,7 +218,7 @@ contract X402UptoPermit2ProxyForkTest is Test { deadline: deadline }); - x402BasePermit2Proxy.Witness memory tamperedWitness = x402BasePermit2Proxy.Witness({ + x402UptoPermit2Proxy.Witness memory tamperedWitness = x402UptoPermit2Proxy.Witness({ to: attacker, facilitator: signedWitness.facilitator, validAfter: signedWitness.validAfter @@ -235,8 +235,8 @@ contract X402UptoPermit2ProxyForkTest is Test { uint256 permitted = TRANSFER_AMOUNT; uint256 requested = permitted / 2; - x402BasePermit2Proxy.Witness memory witness = - x402BasePermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); + x402UptoPermit2Proxy.Witness memory witness = + x402UptoPermit2Proxy.Witness({to: recipient, facilitator: address(this), validAfter: t - 60}); bytes memory sig = _sign(address(token), permitted, nonce, deadline, witness); diff --git a/contracts/evm/test/x402UptoPermit2Proxy.t.sol b/contracts/evm/test/x402UptoPermit2Proxy.t.sol index c90a99d3b2..8d41928340 100644 --- a/contracts/evm/test/x402UptoPermit2Proxy.t.sol +++ b/contracts/evm/test/x402UptoPermit2Proxy.t.sol @@ -60,8 +60,8 @@ contract X402UptoPermit2ProxyTest is Test { address to, address facilitator, uint256 validAfter - ) internal pure returns (x402BasePermit2Proxy.Witness memory) { - return x402BasePermit2Proxy.Witness({to: to, facilitator: facilitator, validAfter: validAfter}); + ) internal pure returns (x402UptoPermit2Proxy.Witness memory) { + return x402UptoPermit2Proxy.Witness({to: to, facilitator: facilitator, validAfter: validAfter}); } function _sig() internal pure returns (bytes memory) { @@ -131,7 +131,7 @@ contract X402UptoPermit2ProxyTest is Test { uint256 t = block.timestamp; address attacker = makeAddr("attacker"); vm.prank(attacker); - vm.expectRevert(x402BasePermit2Proxy.UnauthorizedFacilitator.selector); + vm.expectRevert(x402UptoPermit2Proxy.UnauthorizedFacilitator.selector); proxy.settle( _permit(TRANSFER_AMOUNT, 0, t + 3600), TRANSFER_AMOUNT, diff --git a/contracts/evm/vanity-miner/src/main.rs b/contracts/evm/vanity-miner/src/main.rs index f5b37ae319..5fa6d053fb 100644 --- a/contracts/evm/vanity-miner/src/main.rs +++ b/contracts/evm/vanity-miner/src/main.rs @@ -17,10 +17,10 @@ const UPTO_SUFFIX: [u8; 2] = [0x00, 0x02]; // ...0002 // Run `forge script script/ComputeAddress.s.sol` to verify these match // x402ExactPermit2Proxy const EXACT_INIT_CODE_HASH: [u8; 32] = - hex_literal::hex!("61f007aac96be95995d250c70b750b0c239f3c8cbc28b7b0e89761f84bc0c2bb"); + hex_literal::hex!("e774d1d5a07218946ab54efe010b300481478b86861bb17d69c98a57f68a604c"); // x402UptoPermit2Proxy const UPTO_INIT_CODE_HASH: [u8; 32] = - hex_literal::hex!("6bc5ae76d294a4e82cf7857326e018e5d9cd6e306ccfd1ff1300c08697eed7b2"); + hex_literal::hex!("b956a3d1d040d7b587f0dc6e8145368a5501bac459a111e73a4954ada577673b"); fn compute_create2_address(salt: &[u8; 32], init_code_hash: &[u8; 32]) -> [u8; 20] { let mut hasher = Keccak::v256(); diff --git a/specs/schemes/exact/scheme_exact_evm.md b/specs/schemes/exact/scheme_exact_evm.md index 70ed5f715c..6f5e165384 100644 --- a/specs/schemes/exact/scheme_exact_evm.md +++ b/specs/schemes/exact/scheme_exact_evm.md @@ -144,7 +144,7 @@ The `payload` field must contain: "amount": "10000" }, "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", - "spender": "0x4020CD856C882D5fb903D99CE35316A085Bb0001", // Canonical x402ExactPermit2Proxy address + "spender": "0x402085c248EeA27D92E8b30b2C58ed07f9E20001", // Canonical x402ExactPermit2Proxy address "nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480", "deadline": "1740672154", "witness": { @@ -219,7 +219,7 @@ This contract acts as the authorized Spender. It validates the Witness data to e > **Requirement**: This contract will be deployed to the same address across all supported EVM chains using `CREATE2` to ensure consistent behavior and simpler integration. -**Canonical Address:** `0x4020CD856C882D5fb903D99CE35316A085Bb0001` +**Canonical Address:** `0x402085c248EeA27D92E8b30b2C58ed07f9E20001` ```solidity // SPDX-License-Identifier: MIT From f2bbb5cb25c6912afa5b90d30a002545737ec61c Mon Sep 17 00:00:00 2001 From: Alfred Tom <79275786+alftom@users.noreply.github.com> Date: Wed, 11 Mar 2026 22:20:36 -0700 Subject: [PATCH 059/129] feat(extensions): add optional signed Offer & Receipt extension (draft, addresses #496) (#935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add new folders and READMEs to spec folder to support future settlement types and extensions. * Add the EIP-3009/Signed Transfer spec. * Added initial draft of offer and receipt extension. * feat(extensions): Add client and server code to support signed offers and receipts. Server: - offerReceiptResourceServerExtension for signing offers/receipts - JWS and EIP-712 signature format support - Signer factories for both formats Client: - createOfferReceiptExtractor() callback for wrapFetchWithPayment - Extracts offers, acceptedOffer, receipt, and settlementResponse - Attaches metadata to response.offerReceipt - Generic user review attestation with receipt/offer fallback, with optional OMATrust implementation - Receipt-attestation client demonstrating full flow * Update PR based on feedback: - Add network field to receipt - Add optional transaction field to receipt - Move offers and receipt to extensions field - Add version - Removed settlement field from offer (refers to a future extension). * Move signed payload version from info into the signed offer/receipt payload. * Move version into signed payload. Replace issuedAt + maxTimeoutSeconds with validUntil. * Add acceptIndex to signed offers as unsigned envelope field - Add acceptIndex to offer envelope (not signed payload) - Update examples and JSON schemas * chore: remove outdated settlements folder * chore: reset core/http to main for hooks integration * feat(offer-receipt): implement v1.0 spec for signed offers and receipts Implements the offer-receipt extension per extension-offer-and-receipt.md v1.0 spec. Key changes from phdargen offer-receipt implementation: - Pass down schema to comply with extensions spec - Add more library functions for both servers and clients - Remove server-side offer extraction (offers flow serverβ†’client only) - Remove OMATrust integration code (deferred to future PR) - Client example uses raw flow, not wrapper which still needs extension hook integration - Add comprehensive test coverage (68 tests) * chore: fix linter errors and update pnpm-lock.yaml * chore: add lint/format config files to receipt-attestation example * Address PR feedback: improve offer-receipt documentation and minor code cleanup: - Rename .env.example to .env-local for consistency - Move verbose code comments to README (use cases, security, verification) - Add wrapFetchWithPayment example showing offer/receipt capture - Remove unused createOfferReceiptExtractor * refactor(offer-receipt): rename maxTimeoutSeconds to offerValiditySeconds * fix(offer-receipt): simplify extractResourceUrl and import HTTPRequestContext from core * feat(offer-receipt): rename Signer to Issuer and add server example - Rename OfferReceiptSigner to OfferReceiptIssuer (more accurate naming) - Rename signOffer/signReceipt to issueOffer/issueReceipt - Rename createJWSOfferReceiptSigner to createJWSOfferReceiptIssuer - Rename createEIP712OfferReceiptSigner to createEIP712OfferReceiptIssuer - Add offer-receipt server example in examples/typescript/servers/offer-receipt * fix(offer-receipt): make EIP-712 signing chain-agnostic - Hardcode chainId to 1 in EIP-712 domain - Change payTo type from address to string to support non-EVM networks - Update spec Β§3.2, Β§4.3, Β§4.5, Β§5.5 as well as code and tests * feat(offer-receipt): add signature verification and DID resolution - Add 4 verification functions to signing.ts (verifyOfferSignatureEIP712, verifyReceiptSignatureEIP712, verifyOfferSignatureJWS, verifyReceiptSignatureJWS) - Add @noble/curves and @scure/base dependencies for crypto operations - Add did.ts with extractPublicKeyFromKid supporting did:key, did:jwk, did:web - Modify clients/offer-receipt example demonstrating full verification flow - Change folder name of clients example to be more consistent - Update tests with verification coverage * Update examples/typescript/servers/offer-receipt/README.md Co-authored-by: phdargen * fix: produce valid JWS compact serialization in signJWS - Fixed signJWS to output proper base64url-encoded JWS compact serialization - Updated tests to actually verify JWS output, surfacing the broken serialization - Renamed misleading function names discovered during the fix * fix: enable local did:web verification - Change resolveDidWeb to use HTTP for localhost/127.0.0.1 (per did:web spec) - Server example now serves /.well-known/did.json with public key - SERVER_DOMAIN env var is now required, expects did:web identifier format - Added tests for localhost HTTP resolution * feat(examples): add EIP-712 signing support to offer-receipt server - Add eip712-signer.ts using viem privateKeyToAccount - Update jws-signer.ts to handle both PEM and DER base64 formats - Update README with signing format table and key generation commands - Update environment variables * refactor(offer-receipt): use transportContext from PR #1101 instead of enrichDeclaration * chore: update pnpm-lock.yaml for new dependencies * Address PR feedback: - Fix: use HTTPTransportContext instead of HTTPRequestContext - Remove extractResourceUrl helper, inline transportContext access - Remove specs/extensions/README.md - Add getPaymentSettleResponse logging to offer-receipt client example - Add changeset for @x402/extensions minor release * fix: regenerate examples lockfile for broken solana dependency entry --------- Co-authored-by: phdargen --- .gitignore | 1 + .../typescript/clients/fetch/package.json | 1 + .../clients/offer-receipt/.env-local | 13 + .../clients/offer-receipt/.prettierignore | 8 + .../clients/offer-receipt/.prettierrc | 11 + .../clients/offer-receipt/README.md | 109 + .../clients/offer-receipt/eslint.config.js | 72 + .../typescript/clients/offer-receipt/index.ts | 250 ++ .../clients/offer-receipt/package.json | 35 + .../clients/offer-receipt/tsconfig.json | 15 + examples/typescript/pnpm-lock.yaml | 313 ++- .../servers/offer-receipt/.env-local | 27 + .../servers/offer-receipt/.prettierignore | 8 + .../servers/offer-receipt/.prettierrc | 11 + .../servers/offer-receipt/README.md | 72 + .../servers/offer-receipt/eip712-signer.ts | 31 + .../servers/offer-receipt/eslint.config.js | 73 + .../typescript/servers/offer-receipt/index.ts | 163 ++ .../servers/offer-receipt/jws-signer.ts | 92 + .../servers/offer-receipt/package.json | 36 + .../servers/offer-receipt/tsconfig.json | 15 + .../extensions/extension-offer-and-receipt.md | 882 +++++++ .../.changeset/offer-receipt-extension.md | 5 + typescript/packages/extensions/package.json | 12 + typescript/packages/extensions/src/index.ts | 3 + .../extensions/src/offer-receipt/README.md | 218 ++ .../extensions/src/offer-receipt/client.ts | 193 ++ .../extensions/src/offer-receipt/did.ts | 252 ++ .../extensions/src/offer-receipt/index.ts | 96 + .../extensions/src/offer-receipt/server.ts | 323 +++ .../extensions/src/offer-receipt/signing.ts | 852 +++++++ .../extensions/src/offer-receipt/types.ts | 302 +++ .../test/offer-receipt-test-utils.ts | 135 ++ .../extensions/test/offer-receipt.test.ts | 2144 +++++++++++++++++ typescript/packages/extensions/tsup.config.ts | 1 + typescript/pnpm-lock.yaml | 6 + 36 files changed, 6779 insertions(+), 1 deletion(-) create mode 100644 examples/typescript/clients/offer-receipt/.env-local create mode 100644 examples/typescript/clients/offer-receipt/.prettierignore create mode 100644 examples/typescript/clients/offer-receipt/.prettierrc create mode 100644 examples/typescript/clients/offer-receipt/README.md create mode 100644 examples/typescript/clients/offer-receipt/eslint.config.js create mode 100644 examples/typescript/clients/offer-receipt/index.ts create mode 100644 examples/typescript/clients/offer-receipt/package.json create mode 100644 examples/typescript/clients/offer-receipt/tsconfig.json create mode 100644 examples/typescript/servers/offer-receipt/.env-local create mode 100644 examples/typescript/servers/offer-receipt/.prettierignore create mode 100644 examples/typescript/servers/offer-receipt/.prettierrc create mode 100644 examples/typescript/servers/offer-receipt/README.md create mode 100644 examples/typescript/servers/offer-receipt/eip712-signer.ts create mode 100644 examples/typescript/servers/offer-receipt/eslint.config.js create mode 100644 examples/typescript/servers/offer-receipt/index.ts create mode 100644 examples/typescript/servers/offer-receipt/jws-signer.ts create mode 100644 examples/typescript/servers/offer-receipt/package.json create mode 100644 examples/typescript/servers/offer-receipt/tsconfig.json create mode 100644 specs/extensions/extension-offer-and-receipt.md create mode 100644 typescript/.changeset/offer-receipt-extension.md create mode 100644 typescript/packages/extensions/src/offer-receipt/README.md create mode 100644 typescript/packages/extensions/src/offer-receipt/client.ts create mode 100644 typescript/packages/extensions/src/offer-receipt/did.ts create mode 100644 typescript/packages/extensions/src/offer-receipt/index.ts create mode 100644 typescript/packages/extensions/src/offer-receipt/server.ts create mode 100644 typescript/packages/extensions/src/offer-receipt/signing.ts create mode 100644 typescript/packages/extensions/src/offer-receipt/types.ts create mode 100644 typescript/packages/extensions/test/offer-receipt-test-utils.ts create mode 100644 typescript/packages/extensions/test/offer-receipt.test.ts diff --git a/.gitignore b/.gitignore index 52308c896f..3348b1b896 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .env +.env.local node_modules/ dist/ .turbo/ diff --git a/examples/typescript/clients/fetch/package.json b/examples/typescript/clients/fetch/package.json index dd487128e8..b7dc80299d 100644 --- a/examples/typescript/clients/fetch/package.json +++ b/examples/typescript/clients/fetch/package.json @@ -23,6 +23,7 @@ }, "devDependencies": { "@eslint/js": "^9.24.0", + "@types/node": "^20.0.0", "@typescript-eslint/eslint-plugin": "^8.29.1", "@typescript-eslint/parser": "^8.29.1", "eslint": "^9.24.0", diff --git a/examples/typescript/clients/offer-receipt/.env-local b/examples/typescript/clients/offer-receipt/.env-local new file mode 100644 index 0000000000..181329cc56 --- /dev/null +++ b/examples/typescript/clients/offer-receipt/.env-local @@ -0,0 +1,13 @@ +# x402 Receipt Attestation Example Configuration + +# EVM private key for making payments (required) +EVM_PRIVATE_KEY=0x_your_evm_private_key_here + +# SVM private key for Solana payments (required) +SVM_PRIVATE_KEY=your_solana_private_key_here + +# Resource server URL (optional, defaults to localhost:4021) +RESOURCE_SERVER_URL=http://localhost:4021 + +# Endpoint path (optional, defaults to /weather) +ENDPOINT_PATH=/weather diff --git a/examples/typescript/clients/offer-receipt/.prettierignore b/examples/typescript/clients/offer-receipt/.prettierignore new file mode 100644 index 0000000000..3049672b5c --- /dev/null +++ b/examples/typescript/clients/offer-receipt/.prettierignore @@ -0,0 +1,8 @@ +docs/ +dist/ +node_modules/ +coverage/ +.github/ +src/client +**/**/*.json +*.md diff --git a/examples/typescript/clients/offer-receipt/.prettierrc b/examples/typescript/clients/offer-receipt/.prettierrc new file mode 100644 index 0000000000..ffb416b74b --- /dev/null +++ b/examples/typescript/clients/offer-receipt/.prettierrc @@ -0,0 +1,11 @@ +{ + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "avoid", + "printWidth": 100, + "proseWrap": "never" +} diff --git a/examples/typescript/clients/offer-receipt/README.md b/examples/typescript/clients/offer-receipt/README.md new file mode 100644 index 0000000000..05eecfe6c3 --- /dev/null +++ b/examples/typescript/clients/offer-receipt/README.md @@ -0,0 +1,109 @@ +# Offer/Receipt Client Example + +Demonstrates how clients extract and verify signed offers and receipts from x402 payment flows. + +For background on why receipts matter, payload structure, and security considerations, see the [Offer/Receipt Extension README](../../../../typescript/packages/extensions/src/offer-receipt/README.md). + +## Use Cases for Signed Receipts/Offers + +- Verified user reviews ("Verified Purchase" badges) +- Audit trails and compliance records +- Dispute resolution evidence +- Agent memory (AI agents proving past interactions) + +## Quick Start + +1. Install dependencies from the typescript examples root: + +```bash +cd ../../ +pnpm install && pnpm build +cd clients/offer-receipt +``` + +2. Copy `.env-local` to `.env` and configure: + +```bash +cp .env-local .env +``` + +Required environment variables: +- `EVM_PRIVATE_KEY` - Private key for EVM payments +- `SVM_PRIVATE_KEY` - Private key for Solana payments (base58) +- `RESOURCE_SERVER_URL` - Server URL (default: `http://localhost:4021`) +- `ENDPOINT_PATH` - Endpoint path (default: `/weather`) + +3. Run the example: + +```bash +pnpm start +``` + +## What This Example Shows + +The example uses the raw flow (not the wrapper) for visibility into each step: + +1. Make initial request β†’ receive 402 with signed offers +2. Extract and decode offers to inspect payment options +3. Verify offer signatures and select a verified offer +4. Find matching `accepts[]` entry for selected offer +5. Create payment and retry the request +6. Extract signed receipt from success response +7. Verify receipt signature +8. Verify receipt payload matches the offer + +See [index.ts](./index.ts) for the full implementation with detailed comments. + +## Signature Verification + +The extraction functions (`extractReceiptPayload`, `extractOfferPayload`) decode payloads without verifying signatures. To verify that offers and receipts are authentic, use the verification functions from `@x402/extensions/offer-receipt`: + +- `verifyOfferSignatureJWS` / `verifyReceiptSignatureJWS` - For JWS signatures +- `verifyOfferSignatureEIP712` / `verifyReceiptSignatureEIP712` - For EIP-712 signatures + +See [index.ts](./index.ts) for usage examples. + +### Supported Key Types (JWS) + +- **Ed25519** - EdDSA signatures +- **secp256k1** - ES256K signatures (Ethereum-compatible) +- **secp256r1** - ES256 signatures (NIST P-256) + +### Supported DID Methods (JWS) + +The `kid` header identifies the signing key. These DID methods support automatic key extraction: + +| Method | Description | Example | +|------------|------------------------------------------|----------------------------------| +| `did:key` | Self-contained key in the DID | `did:key:z6Mk...` | +| `did:jwk` | Base64url-encoded JWK | `did:jwk:eyJrdH...` | +| `did:web` | Fetches key from `.well-known/did.json` | `did:web:api.example.com#key-1` | + +For other DID methods, provide the public key explicitly to the verification function. + +### EIP-712 Verification + +EIP-712 signatures don't use DIDs - the signer address is recovered directly from the signature. + +## Key-to-Domain Binding + +Signature verification proves the offer/receipt was signed by a specific key. To fully trust it, verify the key is authorized to sign for the resource's domain via: + +- `did:web` document at `https:///.well-known/did.json` +- DNS TXT record binding the DID to the domain +- On-chain attestation (e.g., OMATrust key binding attestation) + +See: [Extension Specification Β§4.5.1](../../../../specs/extensions/extension-offer-and-receipt.md) + +## Security Considerations + +1. **Private Key Management**: Loading private keys from environment variables is for demonstration only. In production, use secure key management (HSM, KMS, hardware wallets). + +2. **Key Separation**: The payment signing key SHOULD be different from keys controlling wallets with significant funds. + +3. **Key-to-Domain Binding** (for servers): See [Extension Specification Β§4.5.1](../../../../specs/extensions/extension-offer-and-receipt.md) + +## Related + +- [Offer/Receipt Extension](../../../../typescript/packages/extensions/src/offer-receipt/) - Types, signing utilities, client functions +- [Extension Specification](../../../../specs/extensions/extension-offer-and-receipt.md) - Full protocol spec diff --git a/examples/typescript/clients/offer-receipt/eslint.config.js b/examples/typescript/clients/offer-receipt/eslint.config.js new file mode 100644 index 0000000000..ca28b5c47f --- /dev/null +++ b/examples/typescript/clients/offer-receipt/eslint.config.js @@ -0,0 +1,72 @@ +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", + 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/examples/typescript/clients/offer-receipt/index.ts b/examples/typescript/clients/offer-receipt/index.ts new file mode 100644 index 0000000000..be46cd1ce5 --- /dev/null +++ b/examples/typescript/clients/offer-receipt/index.ts @@ -0,0 +1,250 @@ +/** + * x402 Receipt Attestation Client Example + * + * Demonstrates extracting signed offers and receipts from x402 payment flows. + * Uses the raw flow for visibility into what's happening at each step. + */ + +import { config } from "dotenv"; +import { x402Client, x402HTTPClient, type PaymentRequired } from "@x402/fetch"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { registerExactSvmScheme } from "@x402/svm/exact/client"; +import { privateKeyToAccount } from "viem/accounts"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; +import { + extractOffersFromPaymentRequired, + decodeSignedOffers, + findAcceptsObjectFromSignedOffer, + extractReceiptFromResponse, + extractReceiptPayload, + verifyReceiptMatchesOffer, + verifyOfferSignatureJWS, + verifyOfferSignatureEIP712, + verifyReceiptSignatureJWS, + verifyReceiptSignatureEIP712, + isJWSSignedOffer, + isJWSSignedReceipt, +} from "@x402/extensions/offer-receipt"; + +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 entry point demonstrating x402 payment flow with offer-receipt extension + * + * @returns - Promise that resolves when the example completes + */ +async function main(): Promise { + // Set up payment client + const evmSigner = privateKeyToAccount(evmPrivateKey); + const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + + const client = new x402Client(); + registerExactEvmScheme(client, { signer: evmSigner }); + registerExactSvmScheme(client, { signer: svmSigner }); + + const httpClient = new x402HTTPClient(client); + + // ========================================================================= + // Step 1: Initial request (expect 402) + // ========================================================================= + console.log(`Requesting: ${url}`); + const initialResponse = await fetch(url, { method: "GET" }); + + if (initialResponse.status !== 402) { + const body = await initialResponse.json(); + console.log("Response:", body); + return; + } + + // ========================================================================= + // Step 2: Extract and decode signed offers from 402 response + // ========================================================================= + const paymentRequiredBody = (await initialResponse.json()) as PaymentRequired; + const getHeader = (name: string) => initialResponse.headers.get(name); + const paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, paymentRequiredBody); + + const signedOffers = extractOffersFromPaymentRequired(paymentRequired); + + if (signedOffers.length === 0) { + console.log("No signed offers (server may not have offer signing enabled)"); + return; + } + + // Decode all offers to inspect their payloads + const decodedOffers = decodeSignedOffers(signedOffers); + + console.log(`\nSigned Offers (${decodedOffers.length}):`); + decodedOffers.forEach((d, i) => { + console.log(` [${i}] ${d.scheme} on ${d.network}: ${d.amount} to ${d.payTo}`); + }); + + // ========================================================================= + // Step 3: Verify offer signatures and select a verified offer + // ========================================================================= + // Only consider offers that pass signature verification + console.log("\nVerifying offer signatures..."); + + let selected = null; + for (const decoded of decodedOffers) { + try { + if (isJWSSignedOffer(decoded.signedOffer)) { + await verifyOfferSignatureJWS(decoded.signedOffer); + console.log(` [${decoded.acceptIndex}] JWS: βœ“ Valid`); + } else { + const { signer } = await verifyOfferSignatureEIP712(decoded.signedOffer); + console.log(` [${decoded.acceptIndex}] EIP-712: βœ“ Valid (signer: ${signer})`); + } + selected = decoded; + break; + } catch (err) { + console.log( + ` [${decoded.acceptIndex}] βœ— FAILED - ${err instanceof Error ? err.message : err}`, + ); + } + } + + if (!selected) { + console.log("\nNo offers passed signature verification"); + return; + } + + // ========================================================================= + // Step 4: Find matching accepts entry for selected offer + // ========================================================================= + const matchingAccept = findAcceptsObjectFromSignedOffer(selected, paymentRequired.accepts); + + if (!matchingAccept) { + console.log("\nNo matching accepts[] entry for signed offer"); + return; + } + + console.log(`\nSelected: ${selected.scheme} on ${selected.network}`); + + // ========================================================================= + // Step 5: Create payment and retry + // ========================================================================= + console.log("Making payment..."); + + const paymentPayload = await client.createPaymentPayload(paymentRequired); + const paymentHeaders = httpClient.encodePaymentSignatureHeader(paymentPayload); + + const paidResponse = await fetch(url, { + method: "GET", + headers: paymentHeaders, + }); + + if (!paidResponse.ok) { + console.error(`Payment failed: ${paidResponse.status}`); + return; + } + + const responseBody = await paidResponse.json(); + console.log("Response:", responseBody); + + const paymentResponse = httpClient.getPaymentSettleResponse(name => + paidResponse.headers.get(name), + ); + console.log("\nPayment response:", JSON.stringify(paymentResponse, null, 2)); + + // ========================================================================= + // Step 6: Extract signed receipt from success response + // ========================================================================= + const signedReceipt = extractReceiptFromResponse(paidResponse); + + if (signedReceipt) { + const receiptPayload = extractReceiptPayload(signedReceipt); + console.log(`\nSigned Receipt:`); + console.log(` format: ${signedReceipt.format}`); + console.log(` resourceUrl: ${receiptPayload.resourceUrl}`); + console.log(` payer: ${receiptPayload.payer}`); + console.log(` network: ${receiptPayload.network}`); + console.log(` issuedAt: ${new Date(receiptPayload.issuedAt * 1000).toISOString()}`); + if (receiptPayload.transaction) { + console.log(` transaction: ${receiptPayload.transaction}`); + } + } else { + console.log("\nNo signed receipt (server may not have receipt signing enabled)"); + } + + // ========================================================================= + // Step 7: Verify receipt signature + // ========================================================================= + if (signedReceipt) { + console.log("\nReceipt Signature Verification:"); + try { + if (isJWSSignedReceipt(signedReceipt)) { + const verifiedPayload = await verifyReceiptSignatureJWS(signedReceipt); + console.log(` JWS: βœ“ Valid - payer: ${verifiedPayload.payer}`); + } else { + const { signer } = await verifyReceiptSignatureEIP712(signedReceipt); + console.log(` EIP-712: βœ“ Valid - signer: ${signer}`); + } + } catch (err) { + console.log(` βœ— FAILED - ${err instanceof Error ? err.message : err}`); + } + } + + // ========================================================================= + // Step 8: Verify receipt matches offer (payload field verification) + // ========================================================================= + + if (signedReceipt) { + const payerAddresses = [evmSigner.address, svmSigner.address]; + const verified = verifyReceiptMatchesOffer(signedReceipt, selected, payerAddresses); + + console.log(`\nPayload Verification: ${verified ? "βœ“ PASSED" : "βœ— FAILED"}`); + + if (!verified) { + const receiptPayload = extractReceiptPayload(signedReceipt); + console.log( + ` resourceUrl: ${receiptPayload.resourceUrl === selected.resourceUrl ? "βœ“" : "βœ—"}`, + ); + console.log(` network: ${receiptPayload.network === selected.network ? "βœ“" : "βœ—"}`); + const payerMatch = payerAddresses.some( + addr => receiptPayload.payer.toLowerCase() === addr.toLowerCase(), + ); + console.log(` payer: ${payerMatch ? "βœ“" : "βœ—"}`); + const issuedRecently = Math.floor(Date.now() / 1000) - receiptPayload.issuedAt < 3600; + console.log(` recent: ${issuedRecently ? "βœ“" : "βœ—"}`); + } + } + + // ========================================================================= + // Step 9: Summary - Proofs available for downstream use + // ========================================================================= + console.log("\n--- Proofs Available ---"); + if (signedReceipt) { + console.log("βœ“ x402-receipt (proves payment received AND service delivered)"); + } + if (selected) { + console.log("βœ“ x402-offer (proves server committed to payment terms)"); + } + + // ------------------------------------------------------------------------- + // Integration Point: Trust Systems (OMATrust, PEAC, etc.) + // ------------------------------------------------------------------------- + // + // This is where integration with downstream systems like OMATrust and PEAC + // can reside. These systems are planning to support x402 signed receipts + // and offers for use cases like: + // + // - Verified user reviews ("Verified Purchase" badges) + // - Audit trails and compliance records + // - Dispute resolution evidence + // - Agent memory proofs + // + // Integration examples will be added in a future update. + // ------------------------------------------------------------------------- +} + +main().catch(error => { + console.error(error?.response?.data?.error ?? error); + process.exit(1); +}); diff --git a/examples/typescript/clients/offer-receipt/package.json b/examples/typescript/clients/offer-receipt/package.json new file mode 100644 index 0000000000..f523c4e2b5 --- /dev/null +++ b/examples/typescript/clients/offer-receipt/package.json @@ -0,0 +1,35 @@ +{ + "name": "@x402/offer-receipt-example", + "private": true, + "type": "module", + "scripts": { + "start": "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/evm": "workspace:*", + "@x402/extensions": "workspace:*", + "@x402/fetch": "workspace:*", + "@x402/svm": "workspace:*", + "dotenv": "^16.4.7", + "viem": "^2.39.0" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@types/node": "^20.0.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/offer-receipt/tsconfig.json b/examples/typescript/clients/offer-receipt/tsconfig.json new file mode 100644 index 0000000000..78f9479b1b --- /dev/null +++ b/examples/typescript/clients/offer-receipt/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/pnpm-lock.yaml b/examples/typescript/pnpm-lock.yaml index 3a80de4c92..eec18decf0 100644 --- a/examples/typescript/pnpm-lock.yaml +++ b/examples/typescript/pnpm-lock.yaml @@ -72,6 +72,9 @@ importers: ../../typescript/packages/extensions: dependencies: + '@noble/curves': + specifier: ^1.9.0 + version: 1.9.7 '@scure/base': specifier: ^1.2.6 version: 1.2.6 @@ -81,6 +84,9 @@ importers: ajv: specifier: ^8.17.1 version: 8.17.1 + jose: + specifier: ^5.9.6 + version: 5.10.0 siwe: specifier: ^2.3.2 version: 2.3.2(ethers@6.15.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -1522,6 +1528,9 @@ importers: '@eslint/js': specifier: ^9.24.0 version: 9.33.0 + '@types/node': + specifier: ^20.0.0 + version: 20.19.11 '@typescript-eslint/eslint-plugin': specifier: ^8.29.1 version: 8.40.0(@typescript-eslint/parser@8.40.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) @@ -1660,6 +1669,67 @@ importers: specifier: ^5.9.2 version: 5.9.2 + clients/offer-receipt: + 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.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@x402/evm': + specifier: workspace:* + version: link:../../../../typescript/packages/mechanisms/evm + '@x402/extensions': + specifier: workspace:* + version: link:../../../../typescript/packages/extensions + '@x402/fetch': + specifier: workspace:* + version: link:../../../../typescript/packages/http/fetch + '@x402/svm': + specifier: workspace:* + version: link:../../../../typescript/packages/mechanisms/svm + dotenv: + specifier: ^16.4.7 + version: 16.6.1 + viem: + specifier: ^2.39.0 + version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.33.0 + '@types/node': + specifier: ^20.0.0 + version: 20.19.11 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.24.0 + version: 9.33.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.4 + typescript: + specifier: ^5.3.0 + version: 5.9.2 + clients/payment-identifier: dependencies: '@x402/evm': @@ -3291,6 +3361,70 @@ importers: specifier: ^5.9.2 version: 5.9.2 + servers/offer-receipt: + 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.4.7 + version: 16.6.1 + express: + specifier: ^4.18.2 + version: 4.21.2 + viem: + specifier: ^2.21.54 + version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + devDependencies: + '@eslint/js': + specifier: ^9.24.0 + version: 9.33.0 + '@types/express': + specifier: ^5.0.1 + version: 5.0.3 + '@types/node': + specifier: ^22.0.0 + version: 22.17.2 + '@typescript-eslint/eslint-plugin': + specifier: ^8.29.1 + version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + '@typescript-eslint/parser': + specifier: ^8.29.1 + version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) + eslint: + specifier: ^9.24.0 + version: 9.33.0(jiti@2.6.1) + eslint-plugin-import: + specifier: ^2.31.0 + version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-jsdoc: + specifier: ^50.6.9 + version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) + eslint-plugin-prettier: + specifier: ^5.2.6 + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) + prettier: + specifier: 3.5.2 + version: 3.5.2 + tsx: + specifier: ^4.7.0 + version: 4.20.4 + typescript: + specifier: ^5.3.0 + version: 5.9.2 + servers/payment-identifier: dependencies: '@x402/core': @@ -6330,6 +6464,12 @@ packages: 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'} @@ -6599,6 +6739,12 @@ packages: peerDependencies: typescript: '>=5' + '@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'} @@ -6829,6 +6975,12 @@ packages: typescript: optional: true + '@solana/kit@2.3.0': + resolution: {integrity: sha512-sb6PgwoW2LjE5oTFu4lhlS/cGt/NB3YrShEyx7JgWFWysfgLdJnhwWThgwy/4HjNsmtMrQGWVls0yVBHcMvlMQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/kit@3.0.3': resolution: {integrity: sha512-CEEhCDmkvztd1zbgADsEQhmj9GyWOOGeW1hZD+gtwbBSF5YN1uofS/pex5MIh/VIqKRj+A2UnYWI1V+9+q/lyQ==} engines: {node: '>=20.18.0'} @@ -6909,6 +7061,12 @@ packages: peerDependencies: typescript: '>=5' + '@solana/options@2.3.0': + resolution: {integrity: sha512-PPnnZBRCWWoZQ11exPxf//DRzN2C6AoFsDI/u2AsQfYih434/7Kp4XLpfOMT/XESi+gdBMFNNfbES5zg3wAIkw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/options@3.0.3': resolution: {integrity: sha512-jarsmnQ63RN0JPC5j9sgUat07NrL9PC71XU7pUItd6LOHtu4+wJMio3l5mT0DHVfkfbFLL6iI6+QmXSVhTNF3g==} engines: {node: '>=20.18.0'} @@ -6963,6 +7121,12 @@ packages: typescript: optional: true + '@solana/programs@2.3.0': + resolution: {integrity: sha512-UXKujV71VCI5uPs+cFdwxybtHZAIZyQkqDiDnmK+DawtOO9mBn4Nimdb/6RjR2CXT78mzO9ZCZ3qfyX+ydcB7w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/programs@3.0.3': resolution: {integrity: sha512-JZlVE3/AeSNDuH3aEzCZoDu8GTXkMpGXxf93zXLzbxfxhiQ/kHrReN4XE/JWZ/uGWbaFZGR5B3UtdN2QsoZL7w==} engines: {node: '>=20.18.0'} @@ -7426,6 +7590,12 @@ packages: typescript: optional: true + '@solana/signers@2.3.0': + resolution: {integrity: sha512-OSv6fGr/MFRx6J+ZChQMRqKNPGGmdjkqarKkRzkwmv7v8quWsIRnJT5EV8tBy3LI4DLO/A8vKiNSPzvm1TdaiQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/signers@3.0.3': resolution: {integrity: sha512-UwCd/uPYTZiwd283JKVyOWLLN5sIgMBqGDyUmNU3vo9hcmXKv5ZGm/9TvwMY2z35sXWuIOcj7etxJ8OoWc/ObQ==} engines: {node: '>=20.18.0'} @@ -7504,6 +7674,12 @@ packages: typescript: optional: true + '@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'} @@ -18834,6 +19010,18 @@ snapshots: dependencies: '@solana/kit': 5.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/accounts@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec': 2.3.0(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/accounts@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) @@ -19153,6 +19341,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/codecs@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-data-structures': 2.3.0(typescript@5.9.2) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/options': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/codecs@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: '@solana/codecs-core': 3.0.3(typescript@5.9.2) @@ -19409,6 +19608,31 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/instructions': 2.3.0(typescript@5.9.2) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/programs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-parsed-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/signers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) @@ -19607,6 +19831,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/options@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/codecs-data-structures': 2.3.0(typescript@5.9.2) + '@solana/codecs-numbers': 2.3.0(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/options@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: '@solana/codecs-core': 3.0.3(typescript@5.9.2) @@ -19686,6 +19921,14 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/programs@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/programs@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) @@ -19971,6 +20214,15 @@ snapshots: typescript: 5.9.2 ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.2) + '@solana/subscribable': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@solana/rpc-subscriptions-channel-websocket@3.0.3(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 3.0.3(typescript@5.9.2) @@ -20080,6 +20332,24 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/fast-stable-stringify': 2.3.0(typescript@5.9.2) + '@solana/functional': 2.3.0(typescript@5.9.2) + '@solana/promises': 2.3.0(typescript@5.9.2) + '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) + '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.2) + '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/subscribable': 2.3.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/rpc-subscriptions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 3.0.3(typescript@5.9.2) @@ -20234,7 +20504,7 @@ snapshots: '@solana/rpc-spec': 2.3.0(typescript@5.9.2) '@solana/rpc-spec-types': 2.3.0(typescript@5.9.2) typescript: 5.9.2 - undici-types: 7.16.0 + undici-types: 7.22.0 '@solana/rpc-transport-http@3.0.3(typescript@5.9.2)': dependencies: @@ -20406,6 +20676,20 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/signers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-core': 2.3.0(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/instructions': 2.3.0(typescript@5.9.2) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/nominal-types': 2.3.0(typescript@5.9.2) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/signers@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) @@ -20522,6 +20806,16 @@ snapshots: optionalDependencies: typescript: 5.9.2 + '@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': + dependencies: + '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/sysvars@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)': dependencies: '@solana/accounts': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) @@ -20580,6 +20874,23 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + dependencies: + '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/errors': 2.3.0(typescript@5.9.2) + '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/promises': 2.3.0(typescript@5.9.2) + '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2) diff --git a/examples/typescript/servers/offer-receipt/.env-local b/examples/typescript/servers/offer-receipt/.env-local new file mode 100644 index 0000000000..c4f6b7e1c6 --- /dev/null +++ b/examples/typescript/servers/offer-receipt/.env-local @@ -0,0 +1,27 @@ +# Facilitator URL for payment verification and settlement +FACILITATOR_URL=https://x402.org/facilitator + +# EVM address to receive payments +EVM_ADDRESS=0x1234567890123456789012345678901234567890 + +# Solana address to receive payments +SVM_ADDRESS=FV6JPj6Fy12HG8SYStyHdcecXYmV1oeWERAokrh4GQ1n + +# Signing format: "jws" (default) or "eip712" +# - JWS: Base64-encoded PKCS#8 private key (P-256, secp256k1, or Ed25519) +# - EIP-712: Hex-encoded secp256k1 private key (Ethereum's curve) +SIGNING_FORMAT=jws + +# Private key for signing offers/receipts (format depends on SIGNING_FORMAT above) +# +# For JWS with ES256 (P-256): +# openssl ecparam -genkey -name prime256v1 -noout | openssl pkcs8 -topk8 -nocrypt | base64 | tr -d '\n' +# +# For EIP-712 (secp256k1 hex): +# openssl ecparam -genkey -name secp256k1 -noout | openssl ec -text -noout 2>/dev/null | grep -A3 'priv:' | tail -3 | tr -d ' :\n' +SIGNING_PRIVATE_KEY= + +# Server domain for DID (only required for JWS format) +# Used to construct the key identifier: did:web:#key-1 +# For localhost with port, use percent-encoding: localhost%3A4021 +SERVER_DOMAIN=localhost%3A4021 diff --git a/examples/typescript/servers/offer-receipt/.prettierignore b/examples/typescript/servers/offer-receipt/.prettierignore new file mode 100644 index 0000000000..3049672b5c --- /dev/null +++ b/examples/typescript/servers/offer-receipt/.prettierignore @@ -0,0 +1,8 @@ +docs/ +dist/ +node_modules/ +coverage/ +.github/ +src/client +**/**/*.json +*.md diff --git a/examples/typescript/servers/offer-receipt/.prettierrc b/examples/typescript/servers/offer-receipt/.prettierrc new file mode 100644 index 0000000000..ffb416b74b --- /dev/null +++ b/examples/typescript/servers/offer-receipt/.prettierrc @@ -0,0 +1,11 @@ +{ + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "avoid", + "printWidth": 100, + "proseWrap": "never" +} diff --git a/examples/typescript/servers/offer-receipt/README.md b/examples/typescript/servers/offer-receipt/README.md new file mode 100644 index 0000000000..07d8b7036f --- /dev/null +++ b/examples/typescript/servers/offer-receipt/README.md @@ -0,0 +1,72 @@ +# Offer-Receipt Extension Server Example + +Express.js server demonstrating the offer-receipt extension for x402. This extension adds signed offers and receipts to payment flows, enabling: + +- **Signed offers** β€” cryptographic proof of payment terms from the server +- **Signed receipts** β€” proof of service delivery after payment + +## Signing Formats + +The server supports two signing formats: + +| Format | Key Type | Verification | +| ----------------- | -------------------------- | ----------------------------------- | +| **JWS** (default) | P-256, secp256k1, Ed25519 | Resolve `did:web` to get public key | +| **EIP-712** | secp256k1 only | Recover address from signature | + +## Setup + +1. Copy `.env-local` to `.env`: + +```bash +cp .env-local .env +``` + +2. Generate a signing key: + +**For JWS (ES256/P-256):** +```bash +openssl ecparam -genkey -name prime256v1 -noout | openssl pkcs8 -topk8 -nocrypt | base64 | tr -d '\n' +``` + +**For EIP-712 (secp256k1 hex):** +```bash +openssl ecparam -genkey -name secp256k1 -noout | openssl ec -text -noout 2>/dev/null | grep -A3 'priv:' | tail -3 | tr -d ' :\n' +``` + +3. Configure `.env`: + - `SIGNING_FORMAT` β€” `jws` or `eip712` + - `SIGNING_PRIVATE_KEY` β€” Key in the appropriate format + - `SERVER_DOMAIN` β€” Required for JWS (e.g., `localhost%3A4021`) + - `FACILITATOR_URL`, `EVM_ADDRESS`, `SVM_ADDRESS` + +4. Install and run: + +```bash +cd ../../ +pnpm install && pnpm build +cd servers/offer-receipt +pnpm dev +``` + +## DID Document (JWS only) + +For JWS signing, the server exposes `/.well-known/did.json` for signature verification: + +```bash +curl http://localhost:4021/.well-known/did.json +``` + +The library's `resolveDidWeb` automatically uses HTTP for `localhost` and `127.0.0.1`. + +## Configuration Options + +`declareOfferReceiptExtension()` accepts: + +- `includeTxHash` β€” Include transaction hash in receipt (default: `false` for privacy) +- `offerValiditySeconds` β€” How long offers remain valid (default: 300) + +## Related + +- [Extension Specification](../../../../typescript/packages/extensions/src/offer-receipt/README.md) +- [Offer/Receipt Client Example](../../clients/offer-receipt/) diff --git a/examples/typescript/servers/offer-receipt/eip712-signer.ts b/examples/typescript/servers/offer-receipt/eip712-signer.ts new file mode 100644 index 0000000000..f757ce9a4f --- /dev/null +++ b/examples/typescript/servers/offer-receipt/eip712-signer.ts @@ -0,0 +1,31 @@ +import { privateKeyToAccount } from "viem/accounts"; +import type { SignTypedDataFn } from "@x402/extensions/offer-receipt"; + +export interface EIP712SignerResult { + signTypedData: SignTypedDataFn; + address: `0x${string}`; +} + +/** + * Create an EIP-712 signer from a hex private key + * + * For production, use a proper key management solution (HSM, KMS, etc.) + * This is a simple implementation for demonstration purposes. + * + * @param privateKeyHex - Hex-encoded secp256k1 private key (with or without 0x prefix). + * EIP-712 only supports secp256k1 keys (Ethereum's curve). + * @returns EIP712SignerResult containing the signTypedData function and address + */ +export function createEIP712SignerFromPrivateKey(privateKeyHex: string): EIP712SignerResult { + // Ensure 0x prefix + const normalizedKey = privateKeyHex.startsWith("0x") + ? (privateKeyHex as `0x${string}`) + : (`0x${privateKeyHex}` as `0x${string}`); + + const account = privateKeyToAccount(normalizedKey); + + return { + signTypedData: account.signTypedData.bind(account) as SignTypedDataFn, + address: account.address, + }; +} diff --git a/examples/typescript/servers/offer-receipt/eslint.config.js b/examples/typescript/servers/offer-receipt/eslint.config.js new file mode 100644 index 0000000000..e2fde7b3b8 --- /dev/null +++ b/examples/typescript/servers/offer-receipt/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/examples/typescript/servers/offer-receipt/index.ts b/examples/typescript/servers/offer-receipt/index.ts new file mode 100644 index 0000000000..71f18b1532 --- /dev/null +++ b/examples/typescript/servers/offer-receipt/index.ts @@ -0,0 +1,163 @@ +import { config } from "dotenv"; +import express from "express"; +import { paymentMiddleware, x402ResourceServer } from "@x402/express"; +import { ExactEvmScheme } from "@x402/evm/exact/server"; +import { ExactSvmScheme } from "@x402/svm/exact/server"; +import { HTTPFacilitatorClient } from "@x402/core/server"; +import { + createOfferReceiptExtension, + createJWSOfferReceiptIssuer, + createEIP712OfferReceiptIssuer, + declareOfferReceiptExtension, +} from "@x402/extensions/offer-receipt"; +import { createJWSSignerFromPrivateKey } from "./jws-signer"; +import { createEIP712SignerFromPrivateKey } from "./eip712-signer"; +config(); + +const evmAddress = process.env.EVM_ADDRESS as `0x${string}`; +const svmAddress = process.env.SVM_ADDRESS; +if (!evmAddress || !svmAddress) { + console.error("Missing EVM_ADDRESS or SVM_ADDRESS environment variable"); + process.exit(1); +} + +const facilitatorUrl = process.env.FACILITATOR_URL; +if (!facilitatorUrl) { + console.error("❌ FACILITATOR_URL environment variable is required"); + process.exit(1); +} + +// For production, use a proper key management solution (HSM, KMS, etc.) +// This example uses a simple private key for demonstration +const signingPrivateKey = process.env.SIGNING_PRIVATE_KEY; +if (!signingPrivateKey) { + console.error("❌ SIGNING_PRIVATE_KEY environment variable is required"); + process.exit(1); +} + +// Signing format: "jws" (default) or "eip712" +const signingFormat = (process.env.SIGNING_FORMAT || "jws").toLowerCase(); +if (signingFormat !== "jws" && signingFormat !== "eip712") { + console.error('❌ SIGNING_FORMAT must be "jws" or "eip712"'); + process.exit(1); +} + +const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); + +// Create the appropriate issuer based on signing format +let offerReceiptIssuer; +let kid: string; +let didDocument: object | null = null; + +if (signingFormat === "eip712") { + // EIP-712 signing using Ethereum private key + const { signTypedData, address } = createEIP712SignerFromPrivateKey(signingPrivateKey); + + // Use did:pkh for EIP-712 (identifies the Ethereum address) + // Format: did:pkh:eip155::

    + // Using chainId 1 (mainnet) as the canonical identifier + kid = `did:pkh:eip155:1:${address}#key-1`; + offerReceiptIssuer = createEIP712OfferReceiptIssuer(kid, signTypedData); + + console.log(`Using EIP-712 signing with address: ${address}`); +} else { + // JWS signing using PKCS#8 private key + const serverDomain = process.env.SERVER_DOMAIN; + if (!serverDomain) { + console.error( + "❌ SERVER_DOMAIN environment variable is required for JWS signing (e.g., localhost%3A4021)", + ); + process.exit(1); + } + + const did = `did:web:${serverDomain}`; + kid = `${did}#key-1`; + const { signer: jwsSigner, publicKeyJwk } = createJWSSignerFromPrivateKey(signingPrivateKey, kid); + offerReceiptIssuer = createJWSOfferReceiptIssuer(kid, jwsSigner); + + // Build DID document for /.well-known/did.json (only needed for JWS) + didDocument = { + "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1"], + id: did, + verificationMethod: [ + { + id: kid, + type: "JsonWebKey2020", + controller: did, + publicKeyJwk, + }, + ], + assertionMethod: [kid], + }; + + console.log(`Using JWS signing with did:web: ${did}`); +} + +const app = express(); + +// Create the resource server with the offer-receipt extension registered +const resourceServer = new x402ResourceServer(facilitatorClient) + .register("eip155:84532", new ExactEvmScheme()) + .register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme()) + .registerExtension(createOfferReceiptExtension(offerReceiptIssuer)); + +app.use( + paymentMiddleware( + { + "GET /weather": { + accepts: [ + { + scheme: "exact", + // Note: "price" is SDK syntactic sugar that converts to "amount" in atomic units + // The wire protocol uses "amount" per the x402 spec + price: "$0.001", + network: "eip155:84532", + payTo: evmAddress, + }, + { + scheme: "exact", + price: "$0.001", + network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + payTo: svmAddress, + }, + ], + description: "Weather data", + mimeType: "application/json", + extensions: { + // Declare the offer-receipt extension for this route + // includeTxHash: false (default) for privacy, true for verifiability + ...declareOfferReceiptExtension({ includeTxHash: false }), + }, + }, + }, + resourceServer, + ), +); + +app.get("/weather", (req, res) => { + res.send({ + report: { + weather: "sunny", + temperature: 70, + }, + }); +}); + +// Serve DID document for JWS verification (only needed for JWS format) +// did:web resolves to /.well-known/did.json +if (didDocument) { + app.get("/.well-known/did.json", (req, res) => { + res.setHeader("Content-Type", "application/did+json"); + res.json(didDocument); + }); +} + +app.listen(4021, () => { + console.log(`Server listening at http://localhost:${4021}`); + console.log("Offer-receipt extension enabled - responses will include signed offers/receipts"); + console.log(`Signing format: ${signingFormat.toUpperCase()}`); + console.log(`Key ID: ${kid}`); + if (didDocument) { + console.log(`DID document available at http://localhost:4021/.well-known/did.json`); + } +}); diff --git a/examples/typescript/servers/offer-receipt/jws-signer.ts b/examples/typescript/servers/offer-receipt/jws-signer.ts new file mode 100644 index 0000000000..49c6fb481f --- /dev/null +++ b/examples/typescript/servers/offer-receipt/jws-signer.ts @@ -0,0 +1,92 @@ +import * as crypto from "crypto"; +import type { JWSSigner } from "@x402/extensions/offer-receipt"; + +export interface SignerWithPublicKey { + signer: JWSSigner; + publicKeyJwk: JsonWebKey; +} + +/** + * Create a JWS signer from a base64-encoded PKCS#8 private key + * + * For production, use a proper key management solution (HSM, KMS, etc.) + * This is a simple implementation for demonstration purposes. + * + * @param privateKeyBase64 - Base64-encoded PKCS#8 private key + * @param kid - Key identifier DID URL + * @returns SignerWithPublicKey containing the signer and public key JWK + */ +export function createJWSSignerFromPrivateKey( + privateKeyBase64: string, + kid: string, +): SignerWithPublicKey { + // Decode base64 and check if it's PEM or DER format + const decoded = Buffer.from(privateKeyBase64, "base64").toString("utf8"); + const isPem = decoded.includes("-----BEGIN"); + + let privateKeyPem: string; + if (isPem) { + // Already PEM format (base64-encoded PEM) + privateKeyPem = decoded; + } else { + // Raw DER format, wrap in PEM headers + privateKeyPem = `-----BEGIN PRIVATE KEY-----\n${privateKeyBase64}\n-----END PRIVATE KEY-----`; + } + + const keyObject = crypto.createPrivateKey(privateKeyPem); + const publicKeyJwk = keyObject.export({ format: "jwk" }) as JsonWebKey; + // Remove private key component + delete (publicKeyJwk as Record).d; + + const signer: JWSSigner = { + kid, + format: "jws", + algorithm: "ES256", + async sign(payload: Uint8Array): Promise { + const sign = crypto.createSign("SHA256"); + sign.update(payload); + const signature = sign.sign(privateKeyPem); + // Convert DER signature to raw r||s format for JWS + const rawSignature = derToRaw(signature); + return Buffer.from(rawSignature).toString("base64url"); + }, + }; + + return { signer, publicKeyJwk }; +} + +/** + * Convert DER-encoded ECDSA signature to raw r||s format + * + * @param derSignature - DER-encoded signature buffer + * @returns Raw signature as Uint8Array (64 bytes for P-256) + */ +function derToRaw(derSignature: Buffer): Uint8Array { + // DER format: 0x30 [total-length] 0x02 [r-length] [r] 0x02 [s-length] [s] + let offset = 2; // Skip 0x30 and total length + + // Read r + if (derSignature[offset] !== 0x02) throw new Error("Invalid DER signature"); + offset++; + const rLength = derSignature[offset]; + offset++; + let r = derSignature.subarray(offset, offset + rLength); + offset += rLength; + + // Read s + if (derSignature[offset] !== 0x02) throw new Error("Invalid DER signature"); + offset++; + const sLength = derSignature[offset]; + offset++; + let s = derSignature.subarray(offset, offset + sLength); + + // Remove leading zeros and pad to 32 bytes + if (r.length > 32) r = r.subarray(r.length - 32); + if (s.length > 32) s = s.subarray(s.length - 32); + + const raw = new Uint8Array(64); + raw.set(r, 32 - r.length); + raw.set(s, 64 - s.length); + + return raw; +} diff --git a/examples/typescript/servers/offer-receipt/package.json b/examples/typescript/servers/offer-receipt/package.json new file mode 100644 index 0000000000..2ecb0909e6 --- /dev/null +++ b/examples/typescript/servers/offer-receipt/package.json @@ -0,0 +1,36 @@ +{ + "name": "@x402/offer-receipt-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": { + "dotenv": "^16.4.7", + "express": "^4.18.2", + "viem": "^2.21.54", + "@x402/core": "workspace:*", + "@x402/express": "workspace:*", + "@x402/evm": "workspace:*", + "@x402/svm": "workspace:*", + "@x402/extensions": "workspace:*" + }, + "devDependencies": { + "@eslint/js": "^9.24.0", + "@types/express": "^5.0.1", + "@types/node": "^22.0.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/servers/offer-receipt/tsconfig.json b/examples/typescript/servers/offer-receipt/tsconfig.json new file mode 100644 index 0000000000..828d934ed6 --- /dev/null +++ b/examples/typescript/servers/offer-receipt/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", "jws-signer.ts"] +} diff --git a/specs/extensions/extension-offer-and-receipt.md b/specs/extensions/extension-offer-and-receipt.md new file mode 100644 index 0000000000..bb9fd12754 --- /dev/null +++ b/specs/extensions/extension-offer-and-receipt.md @@ -0,0 +1,882 @@ +# Offer and Receipt Extension + +**1. Overview** + +The Offer and Receipt Extension adds **server-side signatures** to x402, enabling: + +1. **Signed offers**: the resource server can cryptographically commit to the payment terms it presents in `accepts[]`. +2. **Signed receipts**: after successful payment and service delivery, the resource server can return a signed receipt confirming the transaction. + +This extension supports downstream use cases including: + +- dispute evidence and auditability, +- user-review attestations (e.g., "I paid and received service"), +- verifiable proof of commercial interactions for reputation systems. + +The signed offer and receipt payloads are **x402 version-agnostic** and work identically for both x402 v1 and v2. + +**2. Status, Evolution, and Forward Compatibility** + +This extension is specified as an optional, composable addition to x402. The x402 ecosystem may introduce additional extensions over time. + +Accordingly: + +- **Wire shape and field placement are not considered stable** and may change to align with x402 canonical extension architecture once standardized. +- **Behavioral requirements are stable**: the payload structures, signature formats, and verification rules in this document are normative and MUST be implemented as written, independent of serialization details. +- Implementers SHOULD design with forward compatibility in mind and SHOULD treat unknown extension-specific fields as unsupported rather than attempting best-effort interpretation. + +**3. Signed Artifact Structure** + +This extension defines exactly two signed artifacts: + +1. **Offer** β€” placed in the `extensions` field, corresponding to `accepts[]` entries +2. **Receipt** β€” returned only on success + +Both artifacts use the same top-level structure, differing only in their payload fields. + +**3.1 Common Object Shape** + +Both `offer` and `receipt` objects MUST have the following structure: + +| Field | Type | Required | Description | +| ------------ | ------- | ------------ | -------------------------------------------------------- | +| `format` | string | Yes | `"eip712"` or `"jws"` | +| `payload` | object | EIP-712 only | The canonical payload fields (omit for JWS) | +| `signature` | string | Yes | The signature (format-specific encoding) | +| `acceptIndex`| integer | No | Index into `accepts[]` (offers only) | + +See Β§4.1.1 for `acceptIndex` usage and verification requirements. + +**3.1.1 Format-Specific Rules** + +**When `format = "eip712"`:** +- `payload` is REQUIRED and contains the canonical payload fields +- `signature` is a hex-encoded ECDSA signature (`0x`-prefixed, 65 bytes: r+s+v) +- `network` MUST be `eip155:` and `payTo` MUST be a valid EVM address + +**When `format = "jws"`:** +- `payload` MUST be omitted (the JWS compact string already contains the payload) +- `signature` is a JWS Compact Serialization string (`header.payload.signature`) + +The `payload` field is omitted for JWS to avoid duplication and ambiguity β€” the payload is already encoded inside the JWS compact string. + +**3.2 EIP-712 Domain** + +All EIP-712 signatures in this extension use the following domain structure: + +```javascript +{ + name: "", + version: "1", + chainId: 1 +} +``` + +Where `name` is: +- `"x402 offer"` for signed offers +- `"x402 receipt"` for receipts + +The `chainId` is hardcoded to `1` (Ethereum mainnet) for all EIP-712 signatures in this extension. This is intentional: EIP-712 is used here purely as an off-chain signing format, not for on-chain transaction submission. The payment network is already identified by the `network` field in the payload. Using a constant `chainId` ensures EIP-712 signing works uniformly regardless of the payment network (including non-EVM networks like Solana). + +> **Versioning note:** EIP-712 artifacts have two distinct version fields: +> - **Domain `version`** (string `"1"`): Indicates the EIP-712 schema version. Changing the canonical `types` or `primaryType` requires bumping this version. +> - **Payload `version`** (integer `1`): Indicates the offer/receipt semantic version. This field is part of the signed payload and travels with the artifact for use outside x402. + +**3.2.1 EIP-712 Schema Is Normative and Not Transmitted** + +For `format = "eip712"`, the signing digest is computed using the EIP-712 domain, the message (the artifact payload), and the canonical `types` and `primaryType` defined in this specification. + +- The canonical `types` and `primaryType` definitions MUST NOT be included in transmitted x402 messages (offers/receipts). +- Signers MUST use the canonical `types` and `primaryType` definitions from this specification when producing EIP-712 signatures. +- Verifiers MUST obtain and use the same canonical `types` and `primaryType` definitions from this specification when verifying EIP-712 signatures. +- Because EIP-712 hashes the schema into the signature, any change to the canonical `types` or `primaryType` constitutes a breaking change and MUST be accompanied by explicit versioning (e.g., bumping the EIP-712 domain `version` or publishing a new spec version). + +> **Non-normative note:** Conceptually, EIP-712 maps to JWS as follows: `domain` β‰ˆ signing context (like a header), `message` β‰ˆ payload, `signature` β‰ˆ signature. The EIP-712 schema (`types` and `primaryType`) is "implicit" only in the sense that it is not transmitted on the wire β€” it is not optional. + +> **Interoperability note:** Some ecosystems represent EIP-712 signatures as `{ domain, message, signature }`. This extension transmits EIP-712 artifacts as `{ format, payload, signature }`, where `payload` corresponds to the EIP-712 `message`. Implementations may wrap or translate these fields for use in external proof or attestation formats. + +**3.3 JWS Header Requirements** + +For JWS format, the header MUST include: + +| Field | Type | Required | Description | +| ----- | ------ | -------- | ------------------------------------------- | +| `alg` | string | Yes | Signing algorithm (e.g., `ES256K`, `EdDSA`) | +| `kid` | string | Yes | Key identifier (DID URL) for key lookup | + + +**4. Signed Offer** + +A signed offer is a cryptographic commitment by the resource server to the payment terms presented in an `accepts[]` entry. + +**4.1 Placement** + +Signed offers are placed in the `extensions` field of the payment requirements response, following the v2 extension structure: + +``` +extensions["offer-receipt"].info.offers[] +``` + +Each offer in the `info.offers` array corresponds to an entry in `accepts[]`. Servers SHOULD maintain the same ordering between `offers[]` and `accepts[]` as a convenience, but clients MUST match offers to `accepts[]` entries by comparing payload fields (`network`, `asset`, `payTo`, `amount`, etc.) rather than relying on array index ordering. For JWS format, clients extract the payload by base64url-decoding the JWS payload component. + +See Β§6.1 for complete examples. + +**4.1.1 acceptIndex Handling** + +Servers SHOULD include `acceptIndex` as an unsigned convenience field to help clients match offers to `accepts[]` entries. It is NOT part of the signed payload and MUST NOT be relied upon for integrity or binding. + +**Within the x402 session (clients):** + +When `acceptIndex` is present, clients SHOULD: +- Check that `acceptIndex` is in-range for the `accepts[]` array +- Validate that `accepts[acceptIndex]` terms match the signed payload fields (`network`, `asset`, `payTo`, `amount`, etc.) + +Clients MUST NOT treat `acceptIndex` as authoritative β€” field matching against the signed payload is the source of truth. + +**Outside the x402 session (external verifiers):** + +When an offer is stored or transmitted outside the x402 negotiation context (e.g., in attestations or reputation systems), `acceptIndex` MAY be omitted without affecting signature verification. External verifiers SHOULD ignore `acceptIndex` since the corresponding `accepts[]` list is not available. + +**4.2 Offer Payload Fields** + +Each element of the offers[] array contains the following fields: + +| Field | Type | Required | Description | +| ------------- | ------ | -------- | ------------------------------------------------------------------ | +| `version` | number | Yes | Offer payload schema version (currently `1`) | +| `resourceUrl` | string | Yes | The paid resource URL | +| `scheme` | string | Yes | Payment scheme identifier (e.g., "exact") | +| `network` | string | Yes | Blockchain network identifier (CAIP-2 format, e.g., "eip155:8453") | +| `asset` | string | Yes | Token contract address or "native" | +| `payTo` | string | Yes | Recipient wallet address | +| `amount` | string | Yes | Required payment amount | +| `validUntil` | number | Optional | Unix timestamp (seconds) when the offer expires | + +**Note**: For x402 v1, servers copy `maxAmountRequired` to `amount` when constructing the offer payload. Servers MUST convert v1 network identifiers (e.g., "base-sepolia") to CAIP-2 format (e.g., "eip155:84532") in the offer payload. + +**4.3 EIP-712 Types for Offer (Normative Schema)** + +The following `types` and `primaryType` are the canonical EIP-712 schema for offers. Per Β§3.2.1, these definitions are used for signing and verification but MUST NOT be transmitted on the wire. + +```javascript +{ + "primaryType": "Offer", + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" } + ], + "Offer": [ + { "name": "version", "type": "uint256" }, + { "name": "resourceUrl", "type": "string" }, + { "name": "scheme", "type": "string" }, + { "name": "network", "type": "string" }, + { "name": "asset", "type": "string" }, + { "name": "payTo", "type": "string" }, + { "name": "amount", "type": "string" }, + { "name": "validUntil", "type": "uint256" } + ] + } +} +``` + +For the optional `validUntil` field, implementations MUST set unused fields to `0`. This rule applies only to EIP-712 signing, where fixed schemas require all fields to be present. Verifiers MUST treat zero-value optional fields as equivalent to absence. + +**4.4 Offer Examples** + +**EIP-712 format:** + +```json +{ + "format": "eip712", + "acceptIndex": 0, + "payload": { + "version": 1, + "resourceUrl": "https://api.example.com/premium-data", + "scheme": "exact", + "network": "eip155:8453", + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "amount": "10000", + "validUntil": 1703123516 + }, + "signature": "0x1234567890abcdef..." +} +``` + +**JWS format:** + +```json +{ + "format": "jws", + "acceptIndex": 0, + "signature": "eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6d2ViOmFwaS5leGFtcGxlLmNvbSNrZXktMSJ9.eyJ2ZXJzaW9uIjoxLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3ByZW1pdW0tZGF0YSIsInNjaGVtZSI6ImV4YWN0IiwibmV0d29yayI6ImVpcDE1NTo4NDUzIiwiYXNzZXQiOiIweDgzMzU4OWZDRDZlRGI2RTA4ZjRjN0MzMkQ0ZjcxYjU0YmRBMDI5MTMiLCJwYXlUbyI6IjB4MjA5NjkzQmM2YWZjMEM1MzI4YkEzNkZhRjAzQzUxNEVGMzEyMjg3QyIsImFtb3VudCI6IjEwMDAwIiwidmFsaWRVbnRpbCI6MTcwMzEyMzUxNn0.sig" +} +``` + +**4.5 Offer Verification** + +**For EIP-712:** +1. Extract `offer.payload` and `offer.signature` +2. Check `payload.version` to select the appropriate EIP-712 types (currently only version `1` is defined; see Β§4.3) +3. Construct the EIP-712 typed data hash using the domain (`name: "x402 offer"`, `version: "1"`, `chainId: 1`) and the types for the payload version. The `offer.payload` object MUST be used exactly as transmitted; verifiers MUST NOT reconstruct or infer payload fields from surrounding x402 context. +4. Verify the signature and recover the signer address +5. Confirm the signer is authorized to sign for the service identified by `payload.resourceUrl` (see Β§4.5.1) + +**For JWS:** +1. Parse the JWS compact string from `offer.signature` +2. Extract `kid` from the JWS header; extract the payload by base64url-decoding the JWS payload component +3. Check the payload's `version` to determine how to interpret the remaining fields (currently only version `1` is defined) +4. Resolve `kid` to a public key +5. Verify the JWS signature over the complete payload +6. Confirm the key is authorized to sign for the service identified by the payload's `resourceUrl` (see Β§4.5.1) + +**4.5.1 Signer Authorization** + +Verifiers MUST confirm that the signing key is authorized to act on behalf of the service identified by `resourceUrl`. This specification does not mandate a specific authorization mechanism. Common approaches include: + +- **`payTo` address signing**: The simplest approach β€” the service signs with the private key corresponding to the `payTo` address. Verifiers accept the signature if the recovered signer matches `payTo`. +- **External key registry**: An external system (e.g., DID documents, on-chain attestations, or other key binding mechanisms) maps the signing key or `kid` to the service identity. + +**4.6 Offer Expiration** + +If `validUntil` is present and non-zero, the resource server MAY reject payment attempts where: + +``` +now > validUntil +``` + +This allows servers to limit how long they commit to specific pricing or terms. Clients SHOULD check expiration before paying to avoid rejected payments, but the enforcement decision rests with the resource server. + + +**5. Receipt** + +A receipt is a signed statement returned by the resource server **only on success**, confirming that payment was received and service was delivered. + +**5.1 Placement** + +On success, the `SettlementResponse` MAY include a receipt in the `extensions` field, following the v2 extension structure: + +``` +extensions["offer-receipt"].info.receipt +``` + +This placement is the same for both x402 v1 and v2. + +See Β§6.2 and Β§6.3 for complete examples. + +**5.2 Receipt Payload Fields** + +The canonical receipt payload contains the following fields: + +| Field | Type | Required | Description | +| ------------- | ------ | -------- | ------------------------------------------------------------------ | +| `version` | number | Yes | Receipt payload schema version (currently `1`) | +| `network` | string | Yes | Blockchain network identifier (CAIP-2 format, e.g., "eip155:8453") | +| `resourceUrl` | string | Yes | The paid resource URL | +| `payer` | string | Yes | Payer identifier (commonly a wallet address) | +| `issuedAt` | number | Yes | Unix timestamp (seconds) when receipt was issued | +| `transaction` | string | Optional | Blockchain transaction hash | + +The receipt is **privacy-minimal** by default and intentionally omits transaction references to reduce correlation risk. Servers MAY include the optional `transaction` field when stronger verifiability is preferred over privacy. If `transaction` is included, verifiers can look up the payment amount on-chain. + +**Note**: Servers MUST convert v1 network identifiers (e.g., "base-sepolia") to CAIP-2 format (e.g., "eip155:84532") in the receipt payload. + +**5.3 EIP-712 Types for Receipt (Normative Schema)** + +The following `types` and `primaryType` are the canonical EIP-712 schema for receipts. Per Β§3.2.1, these definitions are used for signing and verification but MUST NOT be transmitted on the wire. + +```javascript +{ + "primaryType": "Receipt", + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" } + ], + "Receipt": [ + { "name": "version", "type": "uint256" }, + { "name": "network", "type": "string" }, + { "name": "resourceUrl", "type": "string" }, + { "name": "payer", "type": "string" }, + { "name": "issuedAt", "type": "uint256" }, + { "name": "transaction", "type": "string" } + ] + } +} +``` + +For the optional `transaction` field, implementations MUST set unused fields to empty string `""`. This rule applies only to EIP-712 signing, where fixed schemas require all fields to be present. Verifiers MUST treat empty-string optional fields as equivalent to absence. + +**5.4 Receipt Examples** + +**EIP-712 format (privacy-minimal):** + +```json +{ + "format": "eip712", + "payload": { + "version": 1, + "network": "eip155:8453", + "resourceUrl": "https://api.example.com/premium-data", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "issuedAt": 1703123456, + "transaction": "" + }, + "signature": "0x1234567890abcdef..." +} +``` + +**EIP-712 format (with transaction for verifiability):** + +```json +{ + "format": "eip712", + "payload": { + "version": 1, + "network": "eip155:8453", + "resourceUrl": "https://api.example.com/premium-data", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "issuedAt": 1703123456, + "transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" + }, + "signature": "0x1234567890abcdef..." +} +``` + +**JWS format:** + +```json +{ + "format": "jws", + "signature": "eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6d2ViOmFwaS5leGFtcGxlLmNvbSNrZXktMSJ9.eyJ2ZXJzaW9uIjoxLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3ByZW1pdW0tZGF0YSIsInBheWVyIjoiMHg4NTdiMDY1MTlFOTFlM0E1NDUzOGI5MWJEYmIwRTIyMzczZTM2YjY2IiwiaXNzdWVkQXQiOjE3MDMxMjM0NTZ9.sig" +} +``` + +**5.5 Receipt Verification** + +**For EIP-712:** +1. Extract `receipt.payload` and `receipt.signature` +2. Check `payload.version` to select the appropriate EIP-712 types (currently only version `1` is defined; see Β§5.3) +3. Construct the EIP-712 typed data hash using the domain (`name: "x402 receipt"`, `version: "1"`, `chainId: 1`) and the types for the payload version. The `receipt.payload` object MUST be used exactly as transmitted; verifiers MUST NOT reconstruct or infer payload fields from surrounding x402 context. +4. Verify the signature and recover the signer address +5. Confirm the signer is authorized to sign for the service identified by `payload.resourceUrl` (see Β§4.5.1) +6. Confirm `issuedAt` is within acceptable verifier policy +7. If `transaction` is present and non-empty, verifiers MAY check the blockchain to confirm the transaction exists and matches expected parameters + +**For JWS:** +1. Parse the JWS compact string from `receipt.signature` +2. Extract `kid` from the JWS header; extract the payload by base64url-decoding the JWS payload component +3. Check the payload's `version` to determine how to interpret the remaining fields (currently only version `1` is defined) +4. Resolve `kid` to a public key +5. Verify the JWS signature over the complete payload +6. Confirm the key is authorized to sign for the service identified by the payload's `resourceUrl` (see Β§4.5.1) +7. Confirm `issuedAt` (from the payload) is within acceptable verifier policy +8. If `transaction` is present, verifiers MAY check the blockchain to confirm the transaction exists + + +**6. Protocol Integration Examples** + +This section provides complete examples showing how signed offers and receipts integrate with x402 protocol messages. A server would typically use one signature format consistently (EIP-712 or JWS), so examples are shown separately. + +Note: x402 v1 uses human-readable network identifiers (e.g., "base") in the protocol messages, but the offer and receipt payloads MUST use CAIP-2 format (e.g., "eip155:8453") for portability and EIP-712 domain construction. + +**6.1 Payment Requirements with Signed Offers (EIP-712, x402 v2)** + +```json +{ + "x402Version": 2, + "resource": { + "url": "https://api.example.com/premium-data", + "description": "Access to premium market data", + "mimeType": "application/json" + }, + "accepts": [ + { + "scheme": "exact", + "network": "eip155:8453", + "amount": "10000", + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "maxTimeoutSeconds": 60 + } + ], + "extensions": { + "offer-receipt": { + "info": { + "offers": [ + { + "format": "eip712", + "acceptIndex": 0, + "payload": { + "version": 1, + "resourceUrl": "https://api.example.com/premium-data", + "scheme": "exact", + "network": "eip155:8453", + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "amount": "10000", + "validUntil": 1703123516 + }, + "signature": "0x1234567890abcdef..." + } + ] + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "offers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "eip712" }, + "acceptIndex": { "type": "integer" }, + "payload": { + "type": "object", + "properties": { + "version": { "type": "integer" }, + "resourceUrl": { "type": "string" }, + "scheme": { "type": "string" }, + "network": { "type": "string" }, + "asset": { "type": "string" }, + "payTo": { "type": "string" }, + "amount": { "type": "string" }, + "validUntil": { "type": "integer" } + }, + "required": ["version", "resourceUrl", "scheme", "network", "asset", "payTo", "amount"] + }, + "signature": { "type": "string" } + }, + "required": ["format", "payload", "signature"] + } + } + }, + "required": ["offers"] + } + } + } +} +``` + +**6.2 Payment Requirements with Signed Offers (EIP-712, x402 v1)** + +```json +{ + "x402Version": 1, + "accepts": [ + { + "scheme": "exact", + "network": "base", + "maxAmountRequired": "10000", + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "resource": "https://api.example.com/premium-data", + "description": "Access to premium market data", + "mimeType": "application/json", + "maxTimeoutSeconds": 60 + } + ], + "extensions": { + "offer-receipt": { + "info": { + "offers": [ + { + "format": "eip712", + "acceptIndex": 0, + "payload": { + "version": 1, + "resourceUrl": "https://api.example.com/premium-data", + "scheme": "exact", + "network": "eip155:8453", + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "amount": "10000", + "validUntil": 1703123516 + }, + "signature": "0x1234567890abcdef..." + } + ] + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "offers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "eip712" }, + "acceptIndex": { "type": "integer" }, + "payload": { + "type": "object", + "properties": { + "version": { "type": "integer" }, + "resourceUrl": { "type": "string" }, + "scheme": { "type": "string" }, + "network": { "type": "string" }, + "asset": { "type": "string" }, + "payTo": { "type": "string" }, + "amount": { "type": "string" }, + "validUntil": { "type": "integer" } + }, + "required": ["version", "resourceUrl", "scheme", "network", "asset", "payTo", "amount"] + }, + "signature": { "type": "string" } + }, + "required": ["format", "payload", "signature"] + } + } + }, + "required": ["offers"] + } + } + } +} +``` + +**6.3 Payment Requirements with Signed Offers (JWS, x402 v2)** + +```json +{ + "x402Version": 2, + "resource": { + "url": "https://api.example.com/premium-data", + "description": "Access to premium market data", + "mimeType": "application/json" + }, + "accepts": [ + { + "scheme": "exact", + "network": "eip155:8453", + "amount": "10000", + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "maxTimeoutSeconds": 60 + } + ], + "extensions": { + "offer-receipt": { + "info": { + "offers": [ + { + "format": "jws", + "acceptIndex": 0, + "signature": "eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6d2ViOmFwaS5leGFtcGxlLmNvbSNrZXktMSJ9.eyJ2ZXJzaW9uIjoxLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3ByZW1pdW0tZGF0YSIsInNjaGVtZSI6ImV4YWN0IiwibmV0d29yayI6ImVpcDE1NTo4NDUzIiwiYXNzZXQiOiIweDgzMzU4OWZDRDZlRGI2RTA4ZjRjN0MzMkQ0ZjcxYjU0YmRBMDI5MTMiLCJwYXlUbyI6IjB4MjA5NjkzQmM2YWZjMEM1MzI4YkEzNkZhRjAzQzUxNEVGMzEyMjg3QyIsImFtb3VudCI6IjEwMDAwIiwidmFsaWRVbnRpbCI6MTcwMzEyMzUxNn0.sig" + } + ] + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "offers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "jws" }, + "acceptIndex": { "type": "integer" }, + "signature": { "type": "string", "description": "JWS compact serialization containing the offer payload" } + }, + "required": ["format", "signature"] + } + } + }, + "required": ["offers"] + } + } + } +} +``` + +**6.4 Payment Requirements with Signed Offers (JWS, x402 v1)** + +```json +{ + "x402Version": 1, + "accepts": [ + { + "scheme": "exact", + "network": "base", + "maxAmountRequired": "10000", + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "resource": "https://api.example.com/premium-data", + "description": "Access to premium market data", + "mimeType": "application/json", + "maxTimeoutSeconds": 60 + } + ], + "extensions": { + "offer-receipt": { + "info": { + "offers": [ + { + "format": "jws", + "acceptIndex": 0, + "signature": "eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6d2ViOmFwaS5leGFtcGxlLmNvbSNrZXktMSJ9.eyJ2ZXJzaW9uIjoxLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3ByZW1pdW0tZGF0YSIsInNjaGVtZSI6ImV4YWN0IiwibmV0d29yayI6ImVpcDE1NTo4NDUzIiwiYXNzZXQiOiIweDgzMzU4OWZDRDZlRGI2RTA4ZjRjN0MzMkQ0ZjcxYjU0YmRBMDI5MTMiLCJwYXlUbyI6IjB4MjA5NjkzQmM2YWZjMEM1MzI4YkEzNkZhRjAzQzUxNEVGMzEyMjg3QyIsImFtb3VudCI6IjEwMDAwIiwidmFsaWRVbnRpbCI6MTcwMzEyMzUxNn0.sig" + } + ] + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "offers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "jws" }, + "acceptIndex": { "type": "integer" }, + "signature": { "type": "string", "description": "JWS compact serialization containing the offer payload" } + }, + "required": ["format", "signature"] + } + } + }, + "required": ["offers"] + } + } + } +} +``` + +**6.5 Success Response with Receipt (EIP-712, x402 v2)** + +```json +{ + "success": true, + "transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "network": "eip155:8453", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "extensions": { + "offer-receipt": { + "info": { + "receipt": { + "format": "eip712", + "payload": { + "version": 1, + "network": "eip155:8453", + "resourceUrl": "https://api.example.com/premium-data", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "issuedAt": 1703123456, + "transaction": "" + }, + "signature": "0x1234567890abcdef..." + } + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "receipt": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "eip712" }, + "payload": { + "type": "object", + "properties": { + "version": { "type": "integer" }, + "network": { "type": "string" }, + "resourceUrl": { "type": "string" }, + "payer": { "type": "string" }, + "issuedAt": { "type": "integer" }, + "transaction": { "type": "string" } + }, + "required": ["version", "network", "resourceUrl", "payer", "issuedAt"] + }, + "signature": { "type": "string" } + }, + "required": ["format", "payload", "signature"] + } + }, + "required": ["receipt"] + } + } + } +} +``` + +**6.6 Success Response with Receipt (EIP-712, x402 v1)** + +```json +{ + "success": true, + "transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "network": "base", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "extensions": { + "offer-receipt": { + "info": { + "receipt": { + "format": "eip712", + "payload": { + "version": 1, + "network": "eip155:8453", + "resourceUrl": "https://api.example.com/premium-data", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "issuedAt": 1703123456, + "transaction": "" + }, + "signature": "0x1234567890abcdef..." + } + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "receipt": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "eip712" }, + "payload": { + "type": "object", + "properties": { + "version": { "type": "integer" }, + "network": { "type": "string" }, + "resourceUrl": { "type": "string" }, + "payer": { "type": "string" }, + "issuedAt": { "type": "integer" }, + "transaction": { "type": "string" } + }, + "required": ["version", "network", "resourceUrl", "payer", "issuedAt"] + }, + "signature": { "type": "string" } + }, + "required": ["format", "payload", "signature"] + } + }, + "required": ["receipt"] + } + } + } +} +``` + +**6.7 Success Response with Receipt (JWS, x402 v2)** + +```json +{ + "success": true, + "transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "network": "eip155:8453", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "extensions": { + "offer-receipt": { + "info": { + "receipt": { + "format": "jws", + "signature": "eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6d2ViOmFwaS5leGFtcGxlLmNvbSNrZXktMSJ9.eyJ2ZXJzaW9uIjoxLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3ByZW1pdW0tZGF0YSIsInBheWVyIjoiMHg4NTdiMDY1MTlFOTFlM0E1NDUzOGI5MWJEYmIwRTIyMzczZTM2YjY2IiwiaXNzdWVkQXQiOjE3MDMxMjM0NTYsInRyYW5zYWN0aW9uIjoiIn0.sig" + } + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "receipt": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "jws" }, + "signature": { "type": "string", "description": "JWS compact serialization containing the receipt payload" } + }, + "required": ["format", "signature"] + } + }, + "required": ["receipt"] + } + } + } +} +``` + +**6.8 Success Response with Receipt (JWS, x402 v1)** + +```json +{ + "success": true, + "transaction": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "network": "base", + "payer": "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "extensions": { + "offer-receipt": { + "info": { + "receipt": { + "format": "jws", + "signature": "eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6d2ViOmFwaS5leGFtcGxlLmNvbSNrZXktMSJ9.eyJ2ZXJzaW9uIjoxLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMiLCJyZXNvdXJjZVVybCI6Imh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3ByZW1pdW0tZGF0YSIsInBheWVyIjoiMHg4NTdiMDY1MTlFOTFlM0E1NDUzOGI5MWJEYmIwRTIyMzczZTM2YjY2IiwiaXNzdWVkQXQiOjE3MDMxMjM0NTYsInRyYW5zYWN0aW9uIjoiIn0.sig" + } + }, + "schema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "receipt": { + "type": "object", + "properties": { + "format": { "type": "string", "const": "jws" }, + "signature": { "type": "string", "description": "JWS compact serialization containing the receipt payload" } + }, + "required": ["format", "signature"] + } + }, + "required": ["receipt"] + } + } + } +} +``` + +**7. Key Discovery and Trust** + +This extension does not mandate a specific trust system for mapping the server's signing key to an identity. See Β§4.5.1 for signer authorization options. + +For EIP-712 signatures, the signer address is recovered from the signature. The simplest deployment uses the `payTo` address as the signing key. + +For JWS signatures, the `kid` header field provides the key identifier for lookup. + +**8. Use Cases (Non-Normative)** + +This extension defines signed offers and signed receipts that can be carried alongside x402 flows. These artifacts are designed to be portable and independently verifiable, enabling optional trust and audit layers without changing payment execution or settlement semantics. + +- **Attestation-backed discovery and trust for paid endpoints**: Signed offers and receipts can be embedded as evidence in attestations (e.g., user reviews). Those attestations can support discovery, filtering, and reputation scoring for paid API/service endpoints β€” an area that typically lacks the trust provided by user reviews in app stores and ecommerce sites. + +- **Auditability and dispute/feedback evidence**: Signed artifacts provide verifiable evidence of what terms were presented and, when applicable, that service was delivered. This supports auditing, customer support, and dispute workflows, including scenarios involving automated purchasers (agents) and enterprise procurement. + +- **Agent-to-agent commerce**: Autonomous agents making purchasing decisions need machine-verifiable proof of terms and delivery. Signed offers let an agent's principal (human or system) audit what deals the agent accepted; receipts prove the agent received the promised service. + +- **Why offers matter even without receipts**: A signed offer can be used as evidence even when no receipt is available (e.g., the user did not complete payment, the service did not return a receipt, or the user wants to provide feedback about pricing/terms). Offers prove the server's stated terms at a point in time; receipts prove successful service delivery. + +**9. Integration with Proof Systems** + +The `offer` and `receipt` objects defined in this extension are designed to be usable as proof artifacts in attestation systems. These objects are intentionally self-contained so they can be lifted verbatim into external proof or attestation formats without reconstruction. + +**10. Security Considerations** + +- Implementations MUST ensure canonicalization rules are applied consistently (JCS for JWS payloads, EIP-712 rules for EIP-712). +- Servers MUST NOT include the `signature` field in the payload being signed to avoid circularity. +- Servers should consider replay implications of long-lived signed offers; including `validUntil` can reduce risk. +- Receipts and offers are transferable artifacts; possession of a valid server signature is sufficient for verification. Transport-layer security (HTTPS) is essential. + +**11. Privacy Considerations** + +- Receipts are minimal by default β€” they omit transaction references to reduce correlation risk. +- Servers MAY include the optional `transaction` field when verifiability is more important than privacy for their use case. +- Offers reveal economic terms (amount, asset, payTo address). +- Attestations MAY include either offers, receipts, or both. +- Implementations SHOULD consider privacy implications when deciding which artifacts to include in public attestations. + +**12. Version History** + +| Version | Date | Changes | Author | +| ------- | ---------- | -------------------------------------------------------------- | ---------- | +| 0.6 | 2026-02-04 | Make EIP-712 chain-agnostic: chainId=1, payTo type=string. | Alfred Tom | +| 0.5 | 2026-01-29 | First approved release. | Alfred Tom | +| 0.4 | 2026-01-26 | Add acceptIndex as unsigned envelope field. | Alfred Tom | +| 0.3 | 2026-01-22 | Add validUntil for offer expiration. Move version to payload. | Alfred Tom | +| 0.2 | 2026-01-20 | Move offers/receipt to extensions. Add network to receipt. | Alfred Tom | +| 0.1 | 2025-12-22 | Initial extension draft. | Alfred Tom | diff --git a/typescript/.changeset/offer-receipt-extension.md b/typescript/.changeset/offer-receipt-extension.md new file mode 100644 index 0000000000..851ab4bb1a --- /dev/null +++ b/typescript/.changeset/offer-receipt-extension.md @@ -0,0 +1,5 @@ +--- +'@x402/extensions': minor +--- + +Added offer-receipt extension to enable signed offers and receipts in x402 payment flows diff --git a/typescript/packages/extensions/package.json b/typescript/packages/extensions/package.json index d602427dbb..e7377d126f 100644 --- a/typescript/packages/extensions/package.json +++ b/typescript/packages/extensions/package.json @@ -43,9 +43,11 @@ "vitest": "^3.0.5" }, "dependencies": { + "@noble/curves": "^1.9.0", "@scure/base": "^1.2.6", "@x402/core": "workspace:~", "ajv": "^8.17.1", + "jose": "^5.9.6", "siwe": "^2.3.2", "tweetnacl": "^1.0.3", "viem": "^2.43.5", @@ -82,6 +84,16 @@ "default": "./dist/cjs/sign-in-with-x/index.js" } }, + "./offer-receipt": { + "import": { + "types": "./dist/esm/offer-receipt/index.d.mts", + "default": "./dist/esm/offer-receipt/index.mjs" + }, + "require": { + "types": "./dist/cjs/offer-receipt/index.d.ts", + "default": "./dist/cjs/offer-receipt/index.js" + } + }, "./payment-identifier": { "import": { "types": "./dist/esm/payment-identifier/index.d.mts", diff --git a/typescript/packages/extensions/src/index.ts b/typescript/packages/extensions/src/index.ts index dbb00e5359..a8e18bfd60 100644 --- a/typescript/packages/extensions/src/index.ts +++ b/typescript/packages/extensions/src/index.ts @@ -8,6 +8,9 @@ export { bazaarResourceServerExtension } from "./bazaar/server"; // Sign-in-with-x extension export * from "./sign-in-with-x"; +// Offer/Receipt extension +export * from "./offer-receipt"; + // Payment-identifier extension export * from "./payment-identifier"; export { paymentIdentifierResourceServerExtension } from "./payment-identifier/resourceServer"; diff --git a/typescript/packages/extensions/src/offer-receipt/README.md b/typescript/packages/extensions/src/offer-receipt/README.md new file mode 100644 index 0000000000..d1e785ac63 --- /dev/null +++ b/typescript/packages/extensions/src/offer-receipt/README.md @@ -0,0 +1,218 @@ +# x402 Offer/Receipt Extension + +Enables signed offers and receipts for the x402 payment protocol (v1.0). + +## Overview + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Client β”‚ β”‚ Resource Server β”‚ β”‚ Facilitator β”‚ +β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ β”‚ + β”‚ GET /resource β”‚ β”‚ + β”‚ ──────────────────────────────────►│ β”‚ + β”‚ β”‚ β”‚ + β”‚ 402 + PaymentRequirements β”‚ β”‚ + β”‚ + SignedOffer(s) β”‚ β”‚ + β”‚ ◄──────────────────────────────────│ β”‚ + β”‚ β”‚ β”‚ + β”‚ GET /resource + Payment Header β”‚ β”‚ + β”‚ ──────────────────────────────────►│ β”‚ + β”‚ β”‚ β”‚ + β”‚ β”‚ Verify + Settle β”‚ + β”‚ β”‚ ────────────────────────────────────►│ + β”‚ β”‚ β”‚ + β”‚ β”‚ Settlement Response β”‚ + β”‚ β”‚ ◄────────────────────────────────────│ + β”‚ β”‚ β”‚ + β”‚ 200 + Resource + SignedReceipt β”‚ β”‚ + β”‚ ◄──────────────────────────────────│ β”‚ + β”‚ β”‚ β”‚ +``` + +The **Offer** is signed by the resource server and included in the 402 response. Each `accepts[]` entry has a corresponding signed offer, proving those specific payment requirements are authentic. + +The **Receipt** is signed by the resource server after successful payment and included in the success response. It proves service was delivered. + +## Why Receipts? + +Receipts are **portable proofs of paid service**. They enable: + +- **Verified user reviews**: Like a "Verified Purchase" badge +- **Audit trails**: Cryptographic proof of service delivery +- **Dispute resolution**: Evidence that service was delivered after payment +- **Agent memory**: AI agents can prove past interactions with services + +## Why Offers? + +Signed offers: +- Give clients a fallback for proof of interaction if a signed receipt is not sent +- Prove the offer came from the resource server +- Prevent clients from creating their own offer and claiming it came from a server + +## Installation + +```bash +npm install @x402/extensions +``` + +## Server Usage + +To enable offer/receipt signing on your resource server: + +```typescript +import { x402ResourceServer } from "@x402/core/server"; +import { + createOfferReceiptExtension, + createJWSOfferReceiptIssuer, + declareOfferReceipt, +} from "@x402/extensions/offer-receipt"; + +// Create an issuer (JWS or EIP-712) +const issuer = createJWSOfferReceiptIssuer("did:web:api.example.com#key-1", jwsSigner); + +// Register the extension +const server = new x402ResourceServer(facilitator) + .registerExtension(createOfferReceiptExtension(issuer)); + +// Declare in route config +const routes = { + "GET /api/data": { + accepts: { payTo, scheme: "exact", price: "$0.01", network: "eip155:8453" }, + extensions: { + ...declareOfferReceipt({ includeTxHash: false }) + } + } +}; +``` + +### Signature Formats + +Two formats are supported: + +- **JWS** - Best for server-side signing with managed keys (HSM, KMS, etc.) +- **EIP-712** - Best for wallet-based signing (MetaMask, WalletConnect, etc.) + +## Client Usage + +### Using wrapFetchWithPayment + +The `wrapFetchWithPayment` wrapper can be used with offers and receipts by capturing offers in the `onPaymentRequired` hook and extracting the receipt from the response. Note that this approach does not control which `accepts[]` entry is selected - the client's selector/policies determine that independently. + +```typescript +import { wrapFetchWithPayment, x402Client, x402HTTPClient } from "@x402/fetch"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { registerExactSvmScheme } from "@x402/svm/exact/client"; +import { privateKeyToAccount } from "viem/accounts"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; +import { + extractOffersFromPaymentRequired, + decodeSignedOffers, + extractReceiptFromResponse, + type DecodedOffer, +} from "@x402/extensions/offer-receipt"; + +// Set up signers +const evmSigner = privateKeyToAccount(evmPrivateKey); +const svmSigner = await createKeyPairSignerFromBytes(base58.decode(svmPrivateKey)); + +// Configure x402 client +const client = new x402Client(); +registerExactEvmScheme(client, { signer: evmSigner }); +registerExactSvmScheme(client, { signer: svmSigner }); + +const httpClient = new x402HTTPClient(client); + +// Store offers for later matching with receipt +let capturedOffers: DecodedOffer[] = []; + +// Capture offers in onPaymentRequired hook +httpClient.onPaymentRequired(async ({ paymentRequired }) => { + const offers = extractOffersFromPaymentRequired(paymentRequired); + capturedOffers = decodeSignedOffers(offers); +}); + +// Create payment-enabled fetch +const fetchWithPay = wrapFetchWithPayment(fetch, httpClient); + +// Make request (payment handled automatically) +const response = await fetchWithPay(url); + +// Extract receipt from response headers +const receipt = extractReceiptFromResponse(response); + +// Match receipt to captured offer using receipt payload fields +// (receipt contains network, amount, etc. to identify which offer was accepted) +``` + +### Raw Flow + +For full control over offer selection, use the raw flow. See the [Offer/Receipt Example](../../../../../examples/typescript/clients/offer-receipt/) for a complete working implementation. + +The example demonstrates: +1. Making a request and receiving a 402 with signed offers +2. Extracting and decoding offers to inspect payment options +3. Selecting an offer and finding the matching `accepts[]` entry +4. Making payment and receiving a signed receipt +5. Verifying the receipt payload + +### Future: wrapFetchWithPaymentExtended + +We may add a `wrapFetchWithPaymentExtended` wrapper that selects payment options based on signed offers rather than the `accepts[]` array directly. This would guarantee that the selected payment option has a corresponding signed offer, which is the correct approach when attestation proofs are important. + +## Using Receipts as Proofs + +Signed receipts serve as cryptographic proofs of commercial transactions. These proofs can be submitted to downstream trust and reputation platforms: + +- **[OMATrust](https://github.com/oma3dao/omatrust-docs)** - Decentralized reputation system for verified user reviews and service attestations +- **[PEAC Protocol](https://github.com/peacprotocol/peac)** - Payment Evidence and Attestation Chain for commercial transaction proofs + +Integration libraries for these platforms will be added in future releases. + +## Payload Structure + +For detailed payload field definitions, see the [Extension Specification](../../../../../specs/extensions/extension-offer-and-receipt.md): +- Β§4.2 Offer Payload Fields +- Β§5.2 Receipt Payload Fields + +## Security Considerations + +The `extractPayload()` functions extract payloads without verifying the signature or checking signer authorization. This is by design β€” signer authorization requires resolving key bindings (did:web documents, attestations, etc.) which varies by deployment and is outside the scope of x402 client utilities. + +For production use, downstream trust systems verify: +1. The signature is valid (EIP-712 or JWS) +2. The signing key is authorized for the resource domain + +### Key-to-Domain Binding + +To establish trust, bind the signing key's DID to the resource domain using: + +1. **`did:web` DID Document** - Serve at `https://example.com/.well-known/did.json` +2. **DNS TXT Record** - Add a TXT record binding a DID to the domain +3. **Key Binding Attestation** - Create an attestation specifying the key's purpose and authorized domain + +### Key Management + +For production deployments: + +- **JWS signing**: Use HSM or KMS-backed keys. The `kid` in the JWS header should be a DID URL that resolves to the public key. +- **EIP-712 signing**: The signing wallet should be the `payTo` address, or have an on-chain/off-chain authorization linking it to the service. +- **Key rotation**: Update DID documents or attestations when rotating keys. Old receipts remain valid if the key was authorized at issuance time. + +## Files + +| File | Description | +|------|-------------| +| [types.ts](./types.ts) | Type definitions for offers, receipts, and signers | +| [signing.ts](./signing.ts) | Signing utilities and offer/receipt creation | +| [server.ts](./server.ts) | Server extension and signer factories | +| [client.ts](./client.ts) | Client-side extraction utilities | + +## Examples + +- [Offer/Receipt Client Example](../../../../../examples/typescript/clients/offer-receipt/) - Complete example showing offer/receipt extraction + +## Related + +- [Extension Specification](../../../../../specs/extensions/extension-offer-and-receipt.md) diff --git a/typescript/packages/extensions/src/offer-receipt/client.ts b/typescript/packages/extensions/src/offer-receipt/client.ts new file mode 100644 index 0000000000..0ad22adf5f --- /dev/null +++ b/typescript/packages/extensions/src/offer-receipt/client.ts @@ -0,0 +1,193 @@ +/** + * Client-side utilities for extracting offers and receipts from x402 responses + * + * Provides utilities for clients who want to access signed offers and receipts + * from x402 payment flows. Useful for verified reviews, audit trails, and dispute resolution. + * + * @see README.md for usage examples (raw and wrapper flows) + * @see examples/typescript/clients/offer-receipt/ for complete example + */ + +import { decodePaymentResponseHeader } from "@x402/core/http"; +import type { PaymentRequired, PaymentRequirements, SettleResponse } from "@x402/core/types"; +import { OFFER_RECEIPT, type OfferPayload, type SignedOffer, type SignedReceipt } from "./types"; +import { extractOfferPayload, extractReceiptPayload } from "./signing"; + +/** + * A signed offer with its decoded payload fields at the top level. + * Combines the signed offer metadata with the decoded payload for easy access. + */ +export interface DecodedOffer extends OfferPayload { + /** The original signed offer (for passing to other functions or downstream systems) */ + signedOffer: SignedOffer; + /** The signature format used */ + format: "jws" | "eip712"; + /** Index into accepts[] array (hint for matching), may be undefined */ + acceptIndex?: number; +} + +/** + * Structure of offer-receipt extension data in PaymentRequired.extensions + */ +interface OfferReceiptExtensionInfo { + info?: { + offers?: SignedOffer[]; + receipt?: SignedReceipt; + }; +} + +// ============================================================================ +// Exported Functions +// ============================================================================ + +/** + * Verify that a receipt's payload matches the offer and payer. + * + * This performs basic payload field verification: + * - resourceUrl matches the offer + * - network matches the offer + * - payer matches one of the client's wallet addresses + * - issuedAt is recent (within maxAgeSeconds) + * + * NOTE: This does NOT verify the signature or key binding. See the comment + * in the offer-receipt example for guidance on full verification. + * + * @param receipt - The signed receipt from the server + * @param offer - The decoded offer that was accepted + * @param payerAddresses - Array of the client's wallet addresses (EVM, SVM, etc.) + * @param maxAgeSeconds - Maximum age of receipt in seconds (default: 3600 = 1 hour) + * @returns true if all checks pass, false otherwise + */ +export function verifyReceiptMatchesOffer( + receipt: SignedReceipt, + offer: DecodedOffer, + payerAddresses: string[], + maxAgeSeconds: number = 3600, +): boolean { + const payload = extractReceiptPayload(receipt); + + const resourceUrlMatch = payload.resourceUrl === offer.resourceUrl; + const networkMatch = payload.network === offer.network; + const payerMatch = payerAddresses.some( + addr => payload.payer.toLowerCase() === addr.toLowerCase(), + ); + const issuedRecently = Math.floor(Date.now() / 1000) - payload.issuedAt < maxAgeSeconds; + + return resourceUrlMatch && networkMatch && payerMatch && issuedRecently; +} + +/** + * Extract signed offers from a PaymentRequired response. + * + * Call this immediately after receiving a 402 response to save the offers. + * If the settlement response doesn't include a receipt, you'll still have + * the offers for attestation purposes. + * + * @param paymentRequired - The PaymentRequired object from the 402 response + * @returns Array of signed offers, or empty array if none present + */ +export function extractOffersFromPaymentRequired(paymentRequired: PaymentRequired): SignedOffer[] { + const extData = paymentRequired.extensions?.[OFFER_RECEIPT] as + | OfferReceiptExtensionInfo + | undefined; + return extData?.info?.offers ?? []; +} + +/** + * Decode all signed offers and return them with payload fields at the top level. + * + * Use this to inspect offer details (network, amount, etc.) for selection. + * JWS decoding is cheap (base64 decode, no crypto), so decoding all offers + * upfront is fine even with multiple offers. + * + * @param offers - Array of signed offers from extractOffersFromPaymentRequired + * @returns Array of decoded offers with payload fields at top level + */ +export function decodeSignedOffers(offers: SignedOffer[]): DecodedOffer[] { + return offers.map(offer => { + const payload = extractOfferPayload(offer); + return { + // Spread payload fields at top level + ...payload, + // Include metadata + signedOffer: offer, + format: offer.format, + acceptIndex: offer.acceptIndex, + }; + }); +} + +/** + * Find the accepts[] entry that matches a signed or decoded offer. + * + * Use this after selecting an offer to get the PaymentRequirements + * object needed for createPaymentPayload. + * + * Uses the offer's acceptIndex as a hint for faster lookup, but verifies + * the payload matches in case indices got out of sync. + * + * @param offer - A DecodedOffer (from decodeSignedOffers) or SignedOffer + * @param accepts - Array of payment requirements from paymentRequired.accepts + * @returns The matching PaymentRequirements, or undefined if not found + */ +export function findAcceptsObjectFromSignedOffer( + offer: DecodedOffer | SignedOffer, + accepts: PaymentRequirements[], +): PaymentRequirements | undefined { + // Check if it's a DecodedOffer (has signedOffer property) or SignedOffer + const isDecoded = "signedOffer" in offer; + const payload = isDecoded ? offer : extractOfferPayload(offer); + const acceptIndex = isDecoded ? offer.acceptIndex : offer.acceptIndex; + + // Use acceptIndex as a hint - check that index first + if (acceptIndex !== undefined && acceptIndex < accepts.length) { + const hinted = accepts[acceptIndex]; + if ( + hinted.network === payload.network && + hinted.scheme === payload.scheme && + hinted.asset === payload.asset && + hinted.payTo === payload.payTo && + hinted.amount === payload.amount + ) { + return hinted; + } + } + + // Fall back to searching all accepts + return accepts.find( + req => + req.network === payload.network && + req.scheme === payload.scheme && + req.asset === payload.asset && + req.payTo === payload.payTo && + req.amount === payload.amount, + ); +} + +/** + * Extract signed receipt from a successful payment response. + * + * Call this after a successful payment to get the server's signed receipt. + * The receipt proves the service was delivered after payment. + * + * @param response - The Response object from the successful request + * @returns The signed receipt, or undefined if not present + */ +export function extractReceiptFromResponse(response: Response): SignedReceipt | undefined { + const paymentResponseHeader = + response.headers.get("PAYMENT-RESPONSE") || response.headers.get("X-PAYMENT-RESPONSE"); + + if (!paymentResponseHeader) { + return undefined; + } + + try { + const settlementResponse = decodePaymentResponseHeader(paymentResponseHeader) as SettleResponse; + const receiptExtData = settlementResponse.extensions?.[OFFER_RECEIPT] as + | OfferReceiptExtensionInfo + | undefined; + return receiptExtData?.info?.receipt; + } catch { + return undefined; + } +} diff --git a/typescript/packages/extensions/src/offer-receipt/did.ts b/typescript/packages/extensions/src/offer-receipt/did.ts new file mode 100644 index 0000000000..3984417dca --- /dev/null +++ b/typescript/packages/extensions/src/offer-receipt/did.ts @@ -0,0 +1,252 @@ +/** + * DID Resolution Utilities + * + * Extracts public keys from DID key identifiers. Supports did:key, did:jwk, did:web. + * Uses @noble/curves and @scure/base for cryptographic operations. + */ + +import * as jose from "jose"; +import { base58 } from "@scure/base"; +import { secp256k1 } from "@noble/curves/secp256k1"; +import { p256 } from "@noble/curves/nist"; + +// Multicodec prefixes for supported key types +const MULTICODEC_ED25519_PUB = 0xed; +const MULTICODEC_SECP256K1_PUB = 0xe7; +const MULTICODEC_P256_PUB = 0x1200; + +/** + * Extract a public key from a DID key identifier (kid). + * Supports did:key, did:jwk, did:web. + * + * @param kid - The key identifier (DID URL, e.g., did:key:z6Mk..., did:web:example.com#key-1) + * @returns The extracted public key + */ +export async function extractPublicKeyFromKid(kid: string): Promise { + const [didPart, fragment] = kid.split("#"); + const parts = didPart.split(":"); + + if (parts.length < 3 || parts[0] !== "did") { + throw new Error(`Invalid DID format: ${kid}`); + } + + const method = parts[1]; + const identifier = parts.slice(2).join(":"); + + switch (method) { + case "key": + return extractKeyFromDidKey(identifier); + case "jwk": + return extractKeyFromDidJwk(identifier); + case "web": + return resolveDidWeb(identifier, fragment); + default: + throw new Error( + `Unsupported DID method "${method}". Supported: did:key, did:jwk, did:web. ` + + `Provide the public key directly for other methods.`, + ); + } +} + +/** + * Extract public key from did:key identifier (multibase-encoded) + * + * @param identifier - The did:key identifier (without the "did:key:" prefix) + * @returns The extracted public key + */ +async function extractKeyFromDidKey(identifier: string): Promise { + if (!identifier.startsWith("z")) { + throw new Error(`Unsupported multibase encoding. Expected 'z' (base58-btc).`); + } + + const decoded = base58.decode(identifier.slice(1)); + const { codec, keyBytes } = readMulticodec(decoded); + + switch (codec) { + case MULTICODEC_ED25519_PUB: + return importAsymmetricJWK({ + kty: "OKP", + crv: "Ed25519", + x: jose.base64url.encode(keyBytes), + }); + + case MULTICODEC_SECP256K1_PUB: { + const point = secp256k1.Point.fromHex(keyBytes); + const uncompressed = point.toBytes(false); + return importAsymmetricJWK({ + kty: "EC", + crv: "secp256k1", + x: jose.base64url.encode(uncompressed.slice(1, 33)), + y: jose.base64url.encode(uncompressed.slice(33, 65)), + }); + } + + case MULTICODEC_P256_PUB: { + const point = p256.Point.fromHex(keyBytes); + const uncompressed = point.toBytes(false); + return importAsymmetricJWK({ + kty: "EC", + crv: "P-256", + x: jose.base64url.encode(uncompressed.slice(1, 33)), + y: jose.base64url.encode(uncompressed.slice(33, 65)), + }); + } + + default: + throw new Error( + `Unsupported key type in did:key (multicodec: 0x${codec.toString(16)}). ` + + `Supported: Ed25519, secp256k1, P-256.`, + ); + } +} + +/** + * Extract public key from did:jwk identifier (base64url-encoded JWK) + * + * @param identifier - The did:jwk identifier (without the "did:jwk:" prefix) + * @returns The extracted public key + */ +async function extractKeyFromDidJwk(identifier: string): Promise { + const jwkJson = new TextDecoder().decode(jose.base64url.decode(identifier)); + const jwk = JSON.parse(jwkJson) as jose.JWK; + return importAsymmetricJWK(jwk); +} + +/** + * Resolve did:web by fetching DID document from .well-known/did.json + * + * @param identifier - The did:web identifier (without the "did:web:" prefix) + * @param fragment - Optional fragment to identify specific key + * @returns The extracted public key + */ +async function resolveDidWeb(identifier: string, fragment?: string): Promise { + const parts = identifier.split(":"); + const domain = decodeURIComponent(parts[0]); + const path = parts.slice(1).map(decodeURIComponent).join("/"); + + // did:web spec allows HTTP for localhost (https://w3c-ccg.github.io/did-method-web/#read-resolve) + const host = domain.split(":")[0]; + const scheme = host === "localhost" || host === "127.0.0.1" ? "http" : "https"; + + const url = path + ? `${scheme}://${domain}/${path}/did.json` + : `${scheme}://${domain}/.well-known/did.json`; + + let didDocument: DIDDocument; + try { + const response = await fetch(url, { + headers: { Accept: "application/did+json, application/json" }, + }); + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + didDocument = (await response.json()) as DIDDocument; + } catch (error) { + throw new Error( + `Failed to resolve did:web:${identifier}: ${error instanceof Error ? error.message : error}`, + ); + } + + const fullDid = `did:web:${identifier}`; + const keyId = fragment ? `${fullDid}#${fragment}` : undefined; + const method = findVerificationMethod(didDocument, keyId); + + if (!method) { + throw new Error(`No verification method found for ${keyId || fullDid}`); + } + + if (method.publicKeyJwk) { + return importAsymmetricJWK(method.publicKeyJwk); + } + if (method.publicKeyMultibase) { + return extractKeyFromDidKey(method.publicKeyMultibase); + } + + throw new Error(`Verification method ${method.id} has no supported key format`); +} + +/** + * Read multicodec varint prefix from bytes + * + * @param bytes - The encoded bytes + * @returns The codec identifier and remaining key bytes + */ +function readMulticodec(bytes: Uint8Array): { codec: number; keyBytes: Uint8Array } { + let codec = 0; + let shift = 0; + let offset = 0; + + for (const byte of bytes) { + codec |= (byte & 0x7f) << shift; + offset++; + if ((byte & 0x80) === 0) break; + shift += 7; + } + + return { codec, keyBytes: bytes.slice(offset) }; +} + +/** + * Import an asymmetric JWK as a KeyLike + * + * @param jwk - The JWK to import + * @returns The imported key + */ +async function importAsymmetricJWK(jwk: jose.JWK): Promise { + const key = await jose.importJWK(jwk); + if (key instanceof Uint8Array) { + throw new Error("Symmetric keys are not supported"); + } + return key; +} + +interface DIDDocument { + id: string; + verificationMethod?: VerificationMethod[]; + assertionMethod?: (string | VerificationMethod)[]; + authentication?: (string | VerificationMethod)[]; +} + +interface VerificationMethod { + id: string; + type: string; + controller: string; + publicKeyJwk?: jose.JWK; + publicKeyMultibase?: string; +} + +/** + * Find a verification method in a DID document + * + * @param doc - The DID document + * @param keyId - Optional specific key ID to find + * @returns The verification method or undefined + */ +function findVerificationMethod(doc: DIDDocument, keyId?: string): VerificationMethod | undefined { + const methods = doc.verificationMethod || []; + + if (keyId) { + return methods.find(m => m.id === keyId); + } + + // Prefer assertionMethod, then authentication, then any + for (const ref of doc.assertionMethod || []) { + if (typeof ref === "string") { + const m = methods.find(m => m.id === ref); + if (m) return m; + } else { + return ref; + } + } + + for (const ref of doc.authentication || []) { + if (typeof ref === "string") { + const m = methods.find(m => m.id === ref); + if (m) return m; + } else { + return ref; + } + } + + return methods[0]; +} diff --git a/typescript/packages/extensions/src/offer-receipt/index.ts b/typescript/packages/extensions/src/offer-receipt/index.ts new file mode 100644 index 0000000000..47af659004 --- /dev/null +++ b/typescript/packages/extensions/src/offer-receipt/index.ts @@ -0,0 +1,96 @@ +/** + * x402 Offer/Receipt Extension + */ + +// Types +export { + OFFER_RECEIPT, + type SignatureFormat, + type Signer, + type JWSSigner, + type EIP712Signer, + type OfferPayload, + type SignedOffer, + type JWSSignedOffer, + type EIP712SignedOffer, + type ReceiptPayload, + type SignedReceipt, + type JWSSignedReceipt, + type EIP712SignedReceipt, + type OfferReceiptDeclaration, + type OfferReceiptIssuer, + type OfferInput, + type ReceiptInput, + isJWSSignedOffer, + isEIP712SignedOffer, + isJWSSignedReceipt, + isEIP712SignedReceipt, + isJWSSigner, + isEIP712Signer, +} from "./types"; + +// Signing utilities and offer/receipt creation +export { + // Canonicalization + canonicalize, + hashCanonical, + getCanonicalBytes, + // JWS + createJWS, + extractJWSHeader, + extractJWSPayload, + // EIP-712 + createOfferDomain, + createReceiptDomain, + OFFER_TYPES, + RECEIPT_TYPES, + prepareOfferForEIP712, + prepareReceiptForEIP712, + hashOfferTypedData, + hashReceiptTypedData, + signOfferEIP712, + signReceiptEIP712, + type SignTypedDataFn, + // Network utilities + extractEIP155ChainId, + convertNetworkStringToCAIP2, + extractChainIdFromCAIP2, + // Offer creation + createOfferJWS, + createOfferEIP712, + extractOfferPayload, + // Receipt creation + createReceiptJWS, + createReceiptEIP712, + extractReceiptPayload, +} from "./signing"; + +// Server extension and factory functions +export { + createOfferReceiptExtension, + declareOfferReceiptExtension, + createJWSOfferReceiptIssuer, + createEIP712OfferReceiptIssuer, +} from "./server"; + +// Client utilities for extracting offers/receipts +export { + decodeSignedOffers, + extractOffersFromPaymentRequired, + extractReceiptFromResponse, + findAcceptsObjectFromSignedOffer, + verifyReceiptMatchesOffer, + type DecodedOffer, +} from "./client"; + +// Verification utilities (exported from signing.ts) +export { + verifyOfferSignatureEIP712, + verifyReceiptSignatureEIP712, + verifyOfferSignatureJWS, + verifyReceiptSignatureJWS, + type EIP712VerificationResult, +} from "./signing"; + +// DID resolution utilities +export { extractPublicKeyFromKid } from "./did"; diff --git a/typescript/packages/extensions/src/offer-receipt/server.ts b/typescript/packages/extensions/src/offer-receipt/server.ts new file mode 100644 index 0000000000..7f954a07d4 --- /dev/null +++ b/typescript/packages/extensions/src/offer-receipt/server.ts @@ -0,0 +1,323 @@ +/** + * Offer-Receipt Extension for x402ResourceServer + * + * This module provides the ResourceServerExtension implementation that uses + * the extension hooks (enrichPaymentRequiredResponse, enrichSettlementResponse) + * to add signed offers and receipts to x402 payment flows. + * + * Based on: x402/specs/extensions/extension-offer-and-receipt.md (v1.0) + */ + +import type { + ResourceServerExtension, + PaymentRequiredContext, + SettleResultContext, +} from "@x402/core/types"; +import type { PaymentRequirements } from "@x402/core/types"; +import type { HTTPTransportContext } from "@x402/core/http"; +import { + OFFER_RECEIPT, + type OfferReceiptIssuer, + type OfferReceiptDeclaration, + type OfferInput, + type SignedOffer, + type SignedReceipt, + type JWSSigner, +} from "./types"; +import { + createOfferJWS, + createOfferEIP712, + createReceiptJWS, + createReceiptEIP712, + type SignTypedDataFn, +} from "./signing"; + +// ============================================================================ +// JSON Schemas for Extension Responses +// ============================================================================ + +/** + * JSON Schema for offer extension data (Β§6.1) + */ +const OFFER_SCHEMA = { + $schema: "https://json-schema.org/draft/2020-12/schema", + type: "object", + properties: { + offers: { + type: "array", + items: { + type: "object", + properties: { + format: { type: "string" }, + acceptIndex: { type: "integer" }, + payload: { + type: "object", + properties: { + version: { type: "integer" }, + resourceUrl: { type: "string" }, + scheme: { type: "string" }, + network: { type: "string" }, + asset: { type: "string" }, + payTo: { type: "string" }, + amount: { type: "string" }, + validUntil: { type: "integer" }, + }, + required: ["version", "resourceUrl", "scheme", "network", "asset", "payTo", "amount"], + }, + signature: { type: "string" }, + }, + required: ["format", "signature"], + }, + }, + }, + required: ["offers"], +}; + +/** + * JSON Schema for receipt extension data (Β§6.5) + */ +const RECEIPT_SCHEMA = { + $schema: "https://json-schema.org/draft/2020-12/schema", + type: "object", + properties: { + receipt: { + type: "object", + properties: { + format: { type: "string" }, + payload: { + type: "object", + properties: { + version: { type: "integer" }, + network: { type: "string" }, + resourceUrl: { type: "string" }, + payer: { type: "string" }, + issuedAt: { type: "integer" }, + transaction: { type: "string" }, + }, + required: ["version", "network", "resourceUrl", "payer", "issuedAt"], + }, + signature: { type: "string" }, + }, + required: ["format", "signature"], + }, + }, + required: ["receipt"], +}; + +// ============================================================================ +// Extension Factory +// ============================================================================ + +/** + * Convert PaymentRequirements to OfferInput + * + * @param requirements - The payment requirements + * @param acceptIndex - Index into accepts[] array + * @param offerValiditySeconds - Optional validity duration override + * @returns The offer input object + */ +function requirementsToOfferInput( + requirements: PaymentRequirements, + acceptIndex: number, + offerValiditySeconds?: number, +): OfferInput { + return { + acceptIndex, + scheme: requirements.scheme, + network: requirements.network, + asset: requirements.asset, + payTo: requirements.payTo, + amount: requirements.amount, + offerValiditySeconds: offerValiditySeconds ?? requirements.maxTimeoutSeconds, + }; +} + +/** + * Creates an offer-receipt extension for use with x402ResourceServer. + * + * The extension uses the hook system to: + * 1. Add signed offers to each PaymentRequirements in 402 responses + * 2. Add signed receipts to settlement responses after successful payment + * + * @param issuer - The issuer to use for creating and signing offers and receipts + * @returns ResourceServerExtension that can be registered with x402ResourceServer + */ +export function createOfferReceiptExtension(issuer: OfferReceiptIssuer): ResourceServerExtension { + return { + key: OFFER_RECEIPT, + + // Add signed offers to 402 PaymentRequired response + enrichPaymentRequiredResponse: async ( + declaration: unknown, + context: PaymentRequiredContext, + ): Promise => { + const config = declaration as OfferReceiptDeclaration | undefined; + + // Get resource URL from transport context or payment required response + const resourceUrl = + context.paymentRequiredResponse.resource?.url || + (context.transportContext as HTTPTransportContext)?.request?.adapter?.getUrl?.(); + + if (!resourceUrl) { + console.warn("[offer-receipt] No resource URL available for signing offers"); + return undefined; + } + + // Sign offers for each payment requirement + const offers: SignedOffer[] = []; + + for (let i = 0; i < context.requirements.length; i++) { + const requirement = context.requirements[i]; + try { + const offerInput = requirementsToOfferInput(requirement, i, config?.offerValiditySeconds); + const signedOffer = await issuer.issueOffer(resourceUrl, offerInput); + offers.push(signedOffer); + } catch (error) { + console.error(`[offer-receipt] Failed to sign offer for requirement ${i}:`, error); + } + } + + if (offers.length === 0) { + return undefined; + } + + // Return extension data per spec structure + return { + info: { + offers, + }, + schema: OFFER_SCHEMA, + }; + }, + + // Add signed receipt to settlement response + enrichSettlementResponse: async ( + declaration: unknown, + context: SettleResultContext, + ): Promise => { + const config = declaration as OfferReceiptDeclaration | undefined; + + // Skip if settlement failed + if (!context.result.success) { + return undefined; + } + + // Get payer from settlement result + const payer = context.result.payer; + if (!payer) { + console.warn("[offer-receipt] No payer available for signing receipt"); + return undefined; + } + + // Get network and transaction from settlement result + const network = context.result.network; + if (!network) { + console.warn("[offer-receipt] No network available for signing receipt"); + return undefined; + } + const transaction = context.result.transaction; + + // Get resource URL from transport context + const resourceUrl = ( + context.transportContext as HTTPTransportContext + )?.request?.adapter?.getUrl?.(); + + if (!resourceUrl) { + console.warn("[offer-receipt] No resource URL available for signing receipt"); + return undefined; + } + + // Determine whether to include transaction hash (default: false for privacy) + const includeTxHash = config?.includeTxHash === true; + + try { + const signedReceipt: SignedReceipt = await issuer.issueReceipt( + resourceUrl, + payer, + network, + includeTxHash ? transaction || undefined : undefined, + ); + // Return extension data per spec structure + return { + info: { + receipt: signedReceipt, + }, + schema: RECEIPT_SCHEMA, + }; + } catch (error) { + console.error("[offer-receipt] Failed to sign receipt:", error); + return undefined; + } + }, + }; +} + +/** + * Declare offer-receipt extension for a route + * + * Use this in route configuration to enable offer-receipt for a specific endpoint. + * + * @param config - Optional configuration for the extension + * @returns Extension declaration object to spread into route config + */ +export function declareOfferReceiptExtension( + config?: OfferReceiptDeclaration, +): Record { + return { + [OFFER_RECEIPT]: { + includeTxHash: config?.includeTxHash, + offerValiditySeconds: config?.offerValiditySeconds, + }, + }; +} + +// ============================================================================ +// Issuer Factory Functions +// ============================================================================ + +/** + * Create an OfferReceiptIssuer that uses JWS format + * + * @param kid - Key identifier DID (e.g., did:web:api.example.com#key-1) + * @param jwsSigner - JWS signer with sign() function and algorithm + * @returns OfferReceiptIssuer for use with createOfferReceiptExtension + */ +export function createJWSOfferReceiptIssuer(kid: string, jwsSigner: JWSSigner): OfferReceiptIssuer { + return { + kid, + format: "jws", + + async issueOffer(resourceUrl: string, input: OfferInput) { + return createOfferJWS(resourceUrl, input, jwsSigner); + }, + + async issueReceipt(resourceUrl: string, payer: string, network: string, transaction?: string) { + return createReceiptJWS({ resourceUrl, payer, network, transaction }, jwsSigner); + }, + }; +} + +/** + * Create an OfferReceiptIssuer that uses EIP-712 format + * + * @param kid - Key identifier DID (e.g., did:pkh:eip155:1:0x...) + * @param signTypedData - Function to sign EIP-712 typed data + * @returns OfferReceiptIssuer for use with createOfferReceiptExtension + */ +export function createEIP712OfferReceiptIssuer( + kid: string, + signTypedData: SignTypedDataFn, +): OfferReceiptIssuer { + return { + kid, + format: "eip712", + + async issueOffer(resourceUrl: string, input: OfferInput) { + return createOfferEIP712(resourceUrl, input, signTypedData); + }, + + async issueReceipt(resourceUrl: string, payer: string, network: string, transaction?: string) { + return createReceiptEIP712({ resourceUrl, payer, network, transaction }, signTypedData); + }, + }; +} diff --git a/typescript/packages/extensions/src/offer-receipt/signing.ts b/typescript/packages/extensions/src/offer-receipt/signing.ts new file mode 100644 index 0000000000..54d3864a4c --- /dev/null +++ b/typescript/packages/extensions/src/offer-receipt/signing.ts @@ -0,0 +1,852 @@ +/** + * Signing utilities for x402 Offer/Receipt Extension + * + * This module provides: + * - JCS (JSON Canonicalization Scheme) per RFC 8785 + * - JWS (JSON Web Signature) signing and extraction + * - EIP-712 typed data signing + * - Offer/Receipt creation utilities + * - Signature verification utilities + * + * Based on: x402/specs/extensions/extension-offer-and-receipt.md (v1.0) Β§3 + */ + +import * as jose from "jose"; +import { hashTypedData, recoverTypedDataAddress, type Hex, type TypedDataDomain } from "viem"; +import type { + JWSSigner, + OfferPayload, + ReceiptPayload, + SignedOffer, + SignedReceipt, + OfferInput, + ReceiptInput, +} from "./types"; +import { + isJWSSignedOffer, + isEIP712SignedOffer, + isJWSSignedReceipt, + isEIP712SignedReceipt, + type JWSSignedOffer, + type EIP712SignedOffer, + type JWSSignedReceipt, + type EIP712SignedReceipt, +} from "./types"; +import { extractPublicKeyFromKid } from "./did"; + +// ============================================================================ +// JCS Canonicalization (RFC 8785) +// ============================================================================ + +/** + * Canonicalize a JSON object using JCS (RFC 8785) + * + * Rules: + * 1. Object keys are sorted lexicographically by UTF-16 code units + * 2. No whitespace between tokens + * 3. Numbers use shortest representation (no trailing zeros) + * 4. Strings use minimal escaping + * 5. null, true, false are lowercase literals + * + * @param value - The object to canonicalize + * @returns The canonicalized JSON string + */ +export function canonicalize(value: unknown): string { + return serializeValue(value); +} + +/** + * Serialize a value to canonical JSON + * + * @param value - The value to serialize + * @returns The serialized string + */ +function serializeValue(value: unknown): string { + if (value === null) return "null"; + if (value === undefined) return "null"; + + const type = typeof value; + if (type === "boolean") return value ? "true" : "false"; + if (type === "number") return serializeNumber(value as number); + if (type === "string") return serializeString(value as string); + if (Array.isArray(value)) return serializeArray(value); + if (type === "object") return serializeObject(value as Record); + + throw new Error(`Cannot canonicalize value of type ${type}`); +} + +/** + * Serialize a number to canonical JSON + * + * @param num - The number to serialize + * @returns The serialized string + */ +function serializeNumber(num: number): string { + if (!Number.isFinite(num)) throw new Error("Cannot canonicalize Infinity or NaN"); + if (Object.is(num, -0)) return "0"; + return String(num); +} + +/** + * Serialize a string to canonical JSON + * + * @param str - The string to serialize + * @returns The serialized string with proper escaping + */ +function serializeString(str: string): string { + let result = '"'; + for (let i = 0; i < str.length; i++) { + const char = str[i]; + const code = str.charCodeAt(i); + if (code < 0x20) { + result += "\\u" + code.toString(16).padStart(4, "0"); + } else if (char === '"') { + result += '\\"'; + } else if (char === "\\") { + result += "\\\\"; + } else { + result += char; + } + } + return result + '"'; +} + +/** + * Serialize an array to canonical JSON + * + * @param arr - The array to serialize + * @returns The serialized string + */ +function serializeArray(arr: unknown[]): string { + return "[" + arr.map(serializeValue).join(",") + "]"; +} + +/** + * Serialize an object to canonical JSON with sorted keys + * + * @param obj - The object to serialize + * @returns The serialized string with sorted keys + */ +function serializeObject(obj: Record): string { + const keys = Object.keys(obj).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)); + const pairs: string[] = []; + for (const key of keys) { + const value = obj[key]; + if (value !== undefined) { + pairs.push(serializeString(key) + ":" + serializeValue(value)); + } + } + return "{" + pairs.join(",") + "}"; +} + +/** + * Hash a canonicalized object using SHA-256 + * + * @param obj - The object to hash + * @returns The SHA-256 hash as Uint8Array + */ +export async function hashCanonical(obj: unknown): Promise { + const canonical = canonicalize(obj); + const data = new TextEncoder().encode(canonical); + const hashBuffer = await crypto.subtle.digest("SHA-256", data); + return new Uint8Array(hashBuffer); +} + +/** + * Get canonical bytes of an object (UTF-8 encoded) + * + * @param obj - The object to encode + * @returns The UTF-8 encoded canonical JSON + */ +export function getCanonicalBytes(obj: unknown): Uint8Array { + return new TextEncoder().encode(canonicalize(obj)); +} + +// ============================================================================ +// JWS Signing (Β§3.3) +// ============================================================================ + +/** + * Create a JWS Compact Serialization from a payload + * + * Assembles the full JWS structure (header.payload.signature) using the + * signer's algorithm and kid. The signer only needs to sign bytes and + * return the base64url-encoded signature. + * + * @param payload - The payload object to sign + * @param signer - The JWS signer + * @returns The JWS compact serialization string + */ +export async function createJWS(payload: T, signer: JWSSigner): Promise { + const headerObj = { alg: signer.algorithm, kid: signer.kid }; + const headerB64 = jose.base64url.encode(new TextEncoder().encode(JSON.stringify(headerObj))); + const canonical = canonicalize(payload); + const payloadB64 = jose.base64url.encode(new TextEncoder().encode(canonical)); + const signingInput = new TextEncoder().encode(`${headerB64}.${payloadB64}`); + const signatureB64 = await signer.sign(signingInput); + return `${headerB64}.${payloadB64}.${signatureB64}`; +} + +/** + * Extract JWS header without verification + * + * @param jws - The JWS compact serialization string + * @returns The decoded header object + */ +export function extractJWSHeader(jws: string): { alg: string; kid?: string } { + const parts = jws.split("."); + if (parts.length !== 3) throw new Error("Invalid JWS format"); + const headerJson = jose.base64url.decode(parts[0]); + return JSON.parse(new TextDecoder().decode(headerJson)); +} + +/** + * Extract JWS payload + * + * Note: This extracts the payload without verifying the signature or + * checking signer authorization. Signature verification requires resolving + * key bindings (did:web documents, attestations, etc.) which is outside + * the scope of x402 client utilities. + * + * @param jws - The JWS compact serialization string + * @returns The decoded payload + */ +export function extractJWSPayload(jws: string): T { + const parts = jws.split("."); + if (parts.length !== 3) throw new Error("Invalid JWS format"); + const payloadJson = jose.base64url.decode(parts[1]); + return JSON.parse(new TextDecoder().decode(payloadJson)); +} + +// ============================================================================ +// EIP-712 Domain Configuration (Β§3.2) +// ============================================================================ + +/** + * Create EIP-712 domain for offer signing + * + * @returns The EIP-712 domain object + */ +export function createOfferDomain(): TypedDataDomain { + return { name: "x402 offer", version: "1", chainId: 1 }; +} + +/** + * Create EIP-712 domain for receipt signing + * + * @returns The EIP-712 domain object + */ +export function createReceiptDomain(): TypedDataDomain { + return { name: "x402 receipt", version: "1", chainId: 1 }; +} + +/** + * EIP-712 types for Offer (Β§4.3) + */ +export const OFFER_TYPES = { + Offer: [ + { name: "version", type: "uint256" }, + { name: "resourceUrl", type: "string" }, + { name: "scheme", type: "string" }, + { name: "network", type: "string" }, + { name: "asset", type: "string" }, + { name: "payTo", type: "string" }, + { name: "amount", type: "string" }, + { name: "validUntil", type: "uint256" }, + ], +}; + +/** + * EIP-712 types for Receipt (Β§5.3) + */ +export const RECEIPT_TYPES = { + Receipt: [ + { name: "version", type: "uint256" }, + { name: "network", type: "string" }, + { name: "resourceUrl", type: "string" }, + { name: "payer", type: "string" }, + { name: "issuedAt", type: "uint256" }, + { name: "transaction", type: "string" }, + ], +}; + +// ============================================================================ +// EIP-712 Payload Preparation +// ============================================================================ + +/** + * Prepare offer payload for EIP-712 signing + * + * @param payload - The offer payload + * @returns The prepared message object for EIP-712 + */ +export function prepareOfferForEIP712(payload: OfferPayload): { + version: bigint; + resourceUrl: string; + scheme: string; + network: string; + asset: string; + payTo: string; + amount: string; + validUntil: bigint; +} { + return { + version: BigInt(payload.version), + resourceUrl: payload.resourceUrl, + scheme: payload.scheme, + network: payload.network, + asset: payload.asset, + payTo: payload.payTo, + amount: payload.amount, + validUntil: BigInt(payload.validUntil), + }; +} + +/** + * Prepare receipt payload for EIP-712 signing + * + * @param payload - The receipt payload + * @returns The prepared message object for EIP-712 + */ +export function prepareReceiptForEIP712(payload: ReceiptPayload): { + version: bigint; + network: string; + resourceUrl: string; + payer: string; + issuedAt: bigint; + transaction: string; +} { + return { + version: BigInt(payload.version), + network: payload.network, + resourceUrl: payload.resourceUrl, + payer: payload.payer, + issuedAt: BigInt(payload.issuedAt), + transaction: payload.transaction, + }; +} + +// ============================================================================ +// EIP-712 Hashing +// ============================================================================ + +/** + * Hash offer typed data for EIP-712 + * + * @param payload - The offer payload + * @returns The EIP-712 hash + */ +export function hashOfferTypedData(payload: OfferPayload): Hex { + return hashTypedData({ + domain: createOfferDomain(), + types: OFFER_TYPES, + primaryType: "Offer", + message: prepareOfferForEIP712(payload), + }); +} + +/** + * Hash receipt typed data for EIP-712 + * + * @param payload - The receipt payload + * @returns The EIP-712 hash + */ +export function hashReceiptTypedData(payload: ReceiptPayload): Hex { + return hashTypedData({ + domain: createReceiptDomain(), + types: RECEIPT_TYPES, + primaryType: "Receipt", + message: prepareReceiptForEIP712(payload), + }); +} + +// ============================================================================ +// EIP-712 Signing +// ============================================================================ + +/** + * Function type for signing EIP-712 typed data + */ +export type SignTypedDataFn = (params: { + domain: TypedDataDomain; + types: Record>; + primaryType: string; + message: Record; +}) => Promise; + +/** + * Sign an offer using EIP-712 + * + * @param payload - The offer payload + * @param signTypedData - The signing function + * @returns The signature hex string + */ +export async function signOfferEIP712( + payload: OfferPayload, + signTypedData: SignTypedDataFn, +): Promise { + return signTypedData({ + domain: createOfferDomain(), + types: OFFER_TYPES, + primaryType: "Offer", + message: prepareOfferForEIP712(payload) as unknown as Record, + }); +} + +/** + * Sign a receipt using EIP-712 + * + * @param payload - The receipt payload + * @param signTypedData - The signing function + * @returns The signature hex string + */ +export async function signReceiptEIP712( + payload: ReceiptPayload, + signTypedData: SignTypedDataFn, +): Promise { + return signTypedData({ + domain: createReceiptDomain(), + types: RECEIPT_TYPES, + primaryType: "Receipt", + message: prepareReceiptForEIP712(payload) as unknown as Record, + }); +} + +// ============================================================================ +// Network Utilities +// ============================================================================ + +/** + * Extract chain ID from an EIP-155 network string (strict format) + * + * @param network - The network string in "eip155:" format + * @returns The chain ID number + * @throws Error if network is not in "eip155:" format + */ +export function extractEIP155ChainId(network: string): number { + const match = network.match(/^eip155:(\d+)$/); + if (!match) { + throw new Error(`Invalid network format: ${network}. Expected "eip155:"`); + } + return parseInt(match[1], 10); +} + +/** + * V1 EVM network name to chain ID mapping + * Based on x402 v1 protocol network identifiers + */ +const V1_EVM_NETWORK_CHAIN_IDS: Record = { + ethereum: 1, + sepolia: 11155111, + abstract: 2741, + "abstract-testnet": 11124, + "base-sepolia": 84532, + base: 8453, + "avalanche-fuji": 43113, + avalanche: 43114, + iotex: 4689, + sei: 1329, + "sei-testnet": 1328, + polygon: 137, + "polygon-amoy": 80002, + peaq: 3338, + story: 1514, + educhain: 41923, + "skale-base-sepolia": 324705682, +}; + +/** + * V1 Solana network name to CAIP-2 mapping + */ +const V1_SOLANA_NETWORKS: Record = { + solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", + "solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + "solana-testnet": "solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z", +}; + +/** + * Convert a network string to CAIP-2 format + * + * Handles both CAIP-2 format and legacy x402 v1 network strings: + * - CAIP-2: "eip155:8453" β†’ "eip155:8453" (passed through) + * - V1 EVM: "base" β†’ "eip155:8453", "base-sepolia" β†’ "eip155:84532" + * - V1 Solana: "solana" β†’ "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" + * + * @param network - The network string to convert + * @returns The CAIP-2 formatted network string + * @throws Error if network is not a recognized v1 identifier or CAIP-2 format + */ +export function convertNetworkStringToCAIP2(network: string): string { + // Already CAIP-2 format + if (network.includes(":")) return network; + + // Check V1 EVM networks + const chainId = V1_EVM_NETWORK_CHAIN_IDS[network.toLowerCase()]; + if (chainId !== undefined) { + return `eip155:${chainId}`; + } + + // Check V1 Solana networks + const solanaNetwork = V1_SOLANA_NETWORKS[network.toLowerCase()]; + if (solanaNetwork) { + return solanaNetwork; + } + + throw new Error( + `Unknown network identifier: "${network}". Expected CAIP-2 format (e.g., "eip155:8453") or v1 name (e.g., "base", "solana").`, + ); +} + +/** + * Extract chain ID from a CAIP-2 network string (EVM only) + * + * @param network - The CAIP-2 network string + * @returns Chain ID number, or undefined for non-EVM networks + */ +export function extractChainIdFromCAIP2(network: string): number | undefined { + const [namespace, reference] = network.split(":"); + if (namespace === "eip155" && reference) { + const chainId = parseInt(reference, 10); + return isNaN(chainId) ? undefined : chainId; + } + return undefined; +} + +// ============================================================================ +// Offer Creation (Β§4) +// ============================================================================ + +/** Default offer validity in seconds (matches x402ResourceServer.ts) */ +const DEFAULT_MAX_TIMEOUT_SECONDS = 300; + +/** Current extension version */ +const EXTENSION_VERSION = 1; + +/** + * Create an offer payload from input + * + * @param resourceUrl - The resource URL being paid for + * @param input - The offer input parameters + * @returns The offer payload + */ +function createOfferPayload(resourceUrl: string, input: OfferInput): OfferPayload { + const now = Math.floor(Date.now() / 1000); + const offerValiditySeconds = input.offerValiditySeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS; + + return { + version: EXTENSION_VERSION, + resourceUrl, + scheme: input.scheme, + network: input.network, + asset: input.asset, + payTo: input.payTo, + amount: input.amount, + validUntil: now + offerValiditySeconds, + }; +} + +/** + * Create a signed offer using JWS + * + * @param resourceUrl - The resource URL being paid for + * @param input - The offer input parameters + * @param signer - The JWS signer + * @returns The signed offer with JWS format + */ +export async function createOfferJWS( + resourceUrl: string, + input: OfferInput, + signer: JWSSigner, +): Promise { + const payload = createOfferPayload(resourceUrl, input); + const jws = await createJWS(payload, signer); + return { + format: "jws", + acceptIndex: input.acceptIndex, + signature: jws, + }; +} + +/** + * Create a signed offer using EIP-712 + * + * @param resourceUrl - The resource URL being paid for + * @param input - The offer input parameters + * @param signTypedData - The signing function + * @returns The signed offer with EIP-712 format + */ +export async function createOfferEIP712( + resourceUrl: string, + input: OfferInput, + signTypedData: SignTypedDataFn, +): Promise { + const payload = createOfferPayload(resourceUrl, input); + const signature = await signOfferEIP712(payload, signTypedData); + return { + format: "eip712", + acceptIndex: input.acceptIndex, + payload, + signature, + }; +} + +/** + * Extract offer payload + * + * Note: This extracts the payload without verifying the signature or + * checking signer authorization. Signer authorization requires resolving + * key bindings (did:web documents, attestations, etc.) which is outside + * the scope of x402 client utilities. See spec Β§4.5.1. + * + * @param offer - The signed offer + * @returns The offer payload + */ +export function extractOfferPayload(offer: SignedOffer): OfferPayload { + if (isJWSSignedOffer(offer)) { + return extractJWSPayload(offer.signature); + } else if (isEIP712SignedOffer(offer)) { + return offer.payload; + } + throw new Error(`Unknown offer format: ${(offer as SignedOffer).format}`); +} + +// ============================================================================ +// Receipt Creation (Β§5) +// ============================================================================ + +/** + * Create a receipt payload for EIP-712 (requires all fields per spec Β§5.3) + * + * Per spec: "implementations MUST set unused fields to empty string" + * for EIP-712 signing where fixed schemas require all fields. + * + * @param input - The receipt input parameters + * @returns The receipt payload with all fields + */ +function createReceiptPayloadForEIP712(input: ReceiptInput): ReceiptPayload { + return { + version: EXTENSION_VERSION, + network: input.network, + resourceUrl: input.resourceUrl, + payer: input.payer, + issuedAt: Math.floor(Date.now() / 1000), + transaction: input.transaction ?? "", + }; +} + +/** + * Create a receipt payload for JWS (omits optional fields when not provided) + * + * Per spec Β§5.2: transaction is optional and should be omitted in JWS + * when not provided (privacy-minimal by default). + * + * @param input - The receipt input parameters + * @returns The receipt payload with optional fields omitted if not provided + */ +function createReceiptPayloadForJWS( + input: ReceiptInput, +): Omit & { transaction?: string } { + const payload: Omit & { transaction?: string } = { + version: EXTENSION_VERSION, + network: input.network, + resourceUrl: input.resourceUrl, + payer: input.payer, + issuedAt: Math.floor(Date.now() / 1000), + }; + if (input.transaction) { + payload.transaction = input.transaction; + } + return payload; +} + +/** + * Create a signed receipt using JWS + * + * @param input - The receipt input parameters + * @param signer - The JWS signer + * @returns The signed receipt with JWS format + */ +export async function createReceiptJWS( + input: ReceiptInput, + signer: JWSSigner, +): Promise { + const payload = createReceiptPayloadForJWS(input); + const jws = await createJWS(payload, signer); + return { format: "jws", signature: jws }; +} + +/** + * Create a signed receipt using EIP-712 + * + * @param input - The receipt input parameters + * @param signTypedData - The signing function + * @returns The signed receipt with EIP-712 format + */ +export async function createReceiptEIP712( + input: ReceiptInput, + signTypedData: SignTypedDataFn, +): Promise { + const payload = createReceiptPayloadForEIP712(input); + const signature = await signReceiptEIP712(payload, signTypedData); + return { format: "eip712", payload, signature }; +} + +/** + * Extract receipt payload + * + * Note: This extracts the payload without verifying the signature or + * checking signer authorization. Signer authorization requires resolving + * key bindings (did:web documents, attestations, etc.) which is outside + * the scope of x402 client utilities. See spec Β§5.5. + * + * @param receipt - The signed receipt + * @returns The receipt payload + */ +export function extractReceiptPayload(receipt: SignedReceipt): ReceiptPayload { + if (isJWSSignedReceipt(receipt)) { + return extractJWSPayload(receipt.signature); + } else if (isEIP712SignedReceipt(receipt)) { + return receipt.payload; + } + throw new Error(`Unknown receipt format: ${(receipt as SignedReceipt).format}`); +} + +// ============================================================================ +// Signature Verification +// ============================================================================ + +/** + * Result of EIP-712 signature verification + */ +export interface EIP712VerificationResult { + signer: Hex; + payload: T; +} + +/** + * Verify an EIP-712 signed offer and recover the signer address. + * Does NOT verify signer authorization for the resourceUrl - see spec Β§4.5.1. + * + * @param offer - The EIP-712 signed offer + * @returns The recovered signer address and payload + */ +export async function verifyOfferSignatureEIP712( + offer: EIP712SignedOffer, +): Promise> { + if (offer.format !== "eip712") { + throw new Error(`Expected eip712 format, got ${offer.format}`); + } + if (!offer.payload || !("scheme" in offer.payload)) { + throw new Error("Invalid offer: missing or malformed payload"); + } + + const signer = await recoverTypedDataAddress({ + domain: createOfferDomain(), + types: OFFER_TYPES, + primaryType: "Offer", + message: prepareOfferForEIP712(offer.payload), + signature: offer.signature as Hex, + }); + + return { signer, payload: offer.payload }; +} + +/** + * Verify an EIP-712 signed receipt and recover the signer address. + * Does NOT verify signer authorization for the resourceUrl - see spec Β§4.5.1. + * + * @param receipt - The EIP-712 signed receipt + * @returns The recovered signer address and payload + */ +export async function verifyReceiptSignatureEIP712( + receipt: EIP712SignedReceipt, +): Promise> { + if (receipt.format !== "eip712") { + throw new Error(`Expected eip712 format, got ${receipt.format}`); + } + if (!receipt.payload || !("payer" in receipt.payload)) { + throw new Error("Invalid receipt: missing or malformed payload"); + } + + const signer = await recoverTypedDataAddress({ + domain: createReceiptDomain(), + types: RECEIPT_TYPES, + primaryType: "Receipt", + message: prepareReceiptForEIP712(receipt.payload), + signature: receipt.signature as Hex, + }); + + return { signer, payload: receipt.payload }; +} + +/** + * Verify a JWS signed offer. + * Does NOT verify signer authorization for the resourceUrl - see spec Β§4.5.1. + * If no publicKey provided, extracts from kid (supports did:key, did:jwk, did:web). + * + * @param offer - The JWS signed offer + * @param publicKey - Optional public key (JWK or KeyLike). If not provided, extracted from kid. + * @returns The verified payload + */ +export async function verifyOfferSignatureJWS( + offer: JWSSignedOffer, + publicKey?: jose.KeyLike | jose.JWK, +): Promise { + if (offer.format !== "jws") { + throw new Error(`Expected jws format, got ${offer.format}`); + } + const key = await resolveVerificationKey(offer.signature, publicKey); + const { payload } = await jose.compactVerify(offer.signature, key); + return JSON.parse(new TextDecoder().decode(payload)) as OfferPayload; +} + +/** + * Verify a JWS signed receipt. + * Does NOT verify signer authorization for the resourceUrl - see spec Β§4.5.1. + * If no publicKey provided, extracts from kid (supports did:key, did:jwk, did:web). + * + * @param receipt - The JWS signed receipt + * @param publicKey - Optional public key (JWK or KeyLike). If not provided, extracted from kid. + * @returns The verified payload + */ +export async function verifyReceiptSignatureJWS( + receipt: JWSSignedReceipt, + publicKey?: jose.KeyLike | jose.JWK, +): Promise { + if (receipt.format !== "jws") { + throw new Error(`Expected jws format, got ${receipt.format}`); + } + const key = await resolveVerificationKey(receipt.signature, publicKey); + const { payload } = await jose.compactVerify(receipt.signature, key); + return JSON.parse(new TextDecoder().decode(payload)) as ReceiptPayload; +} + +/** + * Resolve the verification key for JWS verification + * + * @param jws - The JWS compact serialization string + * @param providedKey - Optional explicit public key + * @returns The resolved public key + */ +async function resolveVerificationKey( + jws: string, + providedKey?: jose.KeyLike | jose.JWK, +): Promise { + if (providedKey) { + if ("kty" in providedKey) { + const key = await jose.importJWK(providedKey); + if (key instanceof Uint8Array) { + throw new Error("Symmetric keys are not supported for JWS verification"); + } + return key; + } + return providedKey; + } + + const header = extractJWSHeader(jws); + if (!header.kid) { + throw new Error("No public key provided and JWS header missing kid"); + } + + return extractPublicKeyFromKid(header.kid); +} diff --git a/typescript/packages/extensions/src/offer-receipt/types.ts b/typescript/packages/extensions/src/offer-receipt/types.ts new file mode 100644 index 0000000000..546e8c0dae --- /dev/null +++ b/typescript/packages/extensions/src/offer-receipt/types.ts @@ -0,0 +1,302 @@ +/** + * Type definitions for the x402 Offer/Receipt Extension + * + * Based on: x402/specs/extensions/extension-offer-and-receipt.md (v1.0) + * + * Offers prove payment requirements originated from a resource server. + * Receipts prove service was delivered after payment. + */ + +/** + * Extension identifier constant + */ +export const OFFER_RECEIPT = "offer-receipt"; + +/** + * Supported signature formats (Β§3.1) + */ +export type SignatureFormat = "jws" | "eip712"; + +// ============================================================================ +// Low-Level Signer Interfaces +// ============================================================================ + +/** + * Base signer interface for pluggable signing backends + */ +export interface Signer { + /** Key identifier DID (e.g., did:web:api.example.com#key-1) */ + kid: string; + /** Sign payload and return signature string */ + sign: (payload: Uint8Array) => Promise; + /** Signature format */ + format: SignatureFormat; +} + +/** + * JWS-specific signer with algorithm info + */ +export interface JWSSigner extends Signer { + format: "jws"; + /** JWS algorithm (e.g., ES256K, EdDSA) */ + algorithm: string; +} + +/** + * EIP-712 specific signer + */ +export interface EIP712Signer extends Signer { + format: "eip712"; + /** Chain ID for EIP-712 domain */ + chainId: number; +} + +// ============================================================================ +// Offer Types (Β§4) +// ============================================================================ + +/** + * Offer payload fields (Β§4.2) + * + * Required: version, resourceUrl, scheme, network, asset, payTo, amount + * Optional: validUntil + */ +export interface OfferPayload { + /** Offer payload schema version (currently 1) */ + version: number; + /** The paid resource URL */ + resourceUrl: string; + /** Payment scheme identifier (e.g., "exact") */ + scheme: string; + /** Blockchain network identifier (CAIP-2 format, e.g., "eip155:8453") */ + network: string; + /** Token contract address or "native" */ + asset: string; + /** Recipient wallet address */ + payTo: string; + /** Required payment amount */ + amount: string; + /** Unix timestamp (seconds) when the offer expires (optional) */ + validUntil: number; +} + +/** + * Signed offer in JWS format (Β§3.1.1) + * + * "When format = 'jws': payload MUST be omitted" + */ +export interface JWSSignedOffer { + format: "jws"; + /** Index into accepts[] array (unsigned envelope field, Β§4.1.1) */ + acceptIndex?: number; + /** JWS Compact Serialization string (header.payload.signature) */ + signature: string; +} + +/** + * Signed offer in EIP-712 format (Β§3.1.1) + * + * "When format = 'eip712': payload is REQUIRED" + */ +export interface EIP712SignedOffer { + format: "eip712"; + /** Index into accepts[] array (unsigned envelope field, Β§4.1.1) */ + acceptIndex?: number; + /** The canonical payload fields */ + payload: OfferPayload; + /** Hex-encoded ECDSA signature (0x-prefixed, 65 bytes: r+s+v) */ + signature: string; +} + +/** + * Union type for signed offers + */ +export type SignedOffer = JWSSignedOffer | EIP712SignedOffer; + +// ============================================================================ +// Receipt Types (Β§5) +// ============================================================================ + +/** + * Receipt payload fields (Β§5.2) + * + * Required: version, network, resourceUrl, payer, issuedAt + * Optional: transaction (for verifiability over privacy) + */ +export interface ReceiptPayload { + /** Receipt payload schema version (currently 1) */ + version: number; + /** Blockchain network identifier (CAIP-2 format, e.g., "eip155:8453") */ + network: string; + /** The paid resource URL */ + resourceUrl: string; + /** Payer identifier (commonly a wallet address) */ + payer: string; + /** Unix timestamp (seconds) when receipt was issued */ + issuedAt: number; + /** Blockchain transaction hash (optional - for verifiability over privacy) */ + transaction: string; +} + +/** + * Signed receipt in JWS format (Β§3.1.1) + */ +export interface JWSSignedReceipt { + format: "jws"; + /** JWS Compact Serialization string */ + signature: string; +} + +/** + * Signed receipt in EIP-712 format (Β§3.1.1) + */ +export interface EIP712SignedReceipt { + format: "eip712"; + /** The receipt payload */ + payload: ReceiptPayload; + /** Hex-encoded ECDSA signature */ + signature: string; +} + +/** + * Union type for signed receipts + */ +export type SignedReceipt = JWSSignedReceipt | EIP712SignedReceipt; + +// ============================================================================ +// Extension Configuration Types +// ============================================================================ + +/** + * Declaration for the offer-receipt extension in route config + * Used by servers to declare that a route uses offer-receipt + */ +export interface OfferReceiptDeclaration { + /** Include transaction hash in receipt (default: false for privacy). Set to true for verifiability. */ + includeTxHash?: boolean; + /** Offer validity duration in seconds. Default: 300 (see x402ResourceServer.ts) */ + offerValiditySeconds?: number; +} + +/** + * Input for creating an offer (derived from PaymentRequirements) + */ +export interface OfferInput { + /** Index into accepts[] array this offer corresponds to (0-based) */ + acceptIndex: number; + /** Payment scheme identifier */ + scheme: string; + /** Blockchain network identifier (CAIP-2 format) */ + network: string; + /** Token contract address or "native" */ + asset: string; + /** Recipient wallet address */ + payTo: string; + /** Required payment amount */ + amount: string; + /** Offer validity duration in seconds. Default: 300 (see x402ResourceServer.ts) */ + offerValiditySeconds?: number; +} + +/** + * High-level issuer interface for the offer-receipt extension. + * Creates and signs offers and receipts. + * Used by createOfferReceiptExtension() + */ +export interface OfferReceiptIssuer { + /** Key identifier DID */ + kid: string; + /** Signature format */ + format: SignatureFormat; + /** Create and sign an offer for a resource */ + issueOffer(resourceUrl: string, input: OfferInput): Promise; + /** Create and sign a receipt for a completed payment */ + issueReceipt( + resourceUrl: string, + payer: string, + network: string, + transaction?: string, + ): Promise; +} + +// ============================================================================ +// Type Guards +// ============================================================================ + +/** + * Check if an offer is JWS format + * + * @param offer - The signed offer to check + * @returns True if the offer uses JWS format + */ +export function isJWSSignedOffer(offer: SignedOffer): offer is JWSSignedOffer { + return offer.format === "jws"; +} + +/** + * Check if an offer is EIP-712 format + * + * @param offer - The signed offer to check + * @returns True if the offer uses EIP-712 format + */ +export function isEIP712SignedOffer(offer: SignedOffer): offer is EIP712SignedOffer { + return offer.format === "eip712"; +} + +/** + * Check if a receipt is JWS format + * + * @param receipt - The signed receipt to check + * @returns True if the receipt uses JWS format + */ +export function isJWSSignedReceipt(receipt: SignedReceipt): receipt is JWSSignedReceipt { + return receipt.format === "jws"; +} + +/** + * Check if a receipt is EIP-712 format + * + * @param receipt - The signed receipt to check + * @returns True if the receipt uses EIP-712 format + */ +export function isEIP712SignedReceipt(receipt: SignedReceipt): receipt is EIP712SignedReceipt { + return receipt.format === "eip712"; +} + +/** + * Check if a signer is JWS format + * + * @param signer - The signer to check + * @returns True if the signer uses JWS format + */ +export function isJWSSigner(signer: Signer): signer is JWSSigner { + return signer.format === "jws"; +} + +/** + * Check if a signer is EIP-712 format + * + * @param signer - The signer to check + * @returns True if the signer uses EIP-712 format + */ +export function isEIP712Signer(signer: Signer): signer is EIP712Signer { + return signer.format === "eip712"; +} + +// ============================================================================ +// Receipt Input Type +// ============================================================================ + +/** + * Input for creating a receipt + */ +export interface ReceiptInput { + /** The resource URL that was paid for */ + resourceUrl: string; + /** The payer identifier (wallet address) */ + payer: string; + /** The blockchain network (CAIP-2 format) */ + network: string; + /** The transaction hash (optional, for verifiability) */ + transaction?: string; +} diff --git a/typescript/packages/extensions/test/offer-receipt-test-utils.ts b/typescript/packages/extensions/test/offer-receipt-test-utils.ts new file mode 100644 index 0000000000..b526c09726 --- /dev/null +++ b/typescript/packages/extensions/test/offer-receipt-test-utils.ts @@ -0,0 +1,135 @@ +/** + * Test utilities for x402 Offer/Receipt Extension + * + * These are convenience functions for testing only. + * Production implementations should use HSM, TPM, or secure key management. + */ + +import * as jose from "jose"; +import { secp256k1 } from "@noble/curves/secp256k1"; +import type { JWSSigner } from "../src/offer-receipt/types"; + +// ============================================================================ +// P-256 (ES256) Utilities - Clean Web Crypto implementation +// ============================================================================ + +/** + * Create an ES256 (P-256) JWS signer from a CryptoKey (FOR TESTING ONLY) + * + * The signer's sign() function returns ONLY the raw base64url-encoded signature. + * The library's createJWS function is responsible for assembling the + * full JWS compact serialization (header.payload.signature). + * + * @param privateKey - The CryptoKey private key (P-256) + * @param kid - The key identifier + * @returns A JWS signer + */ +export function createES256Signer(privateKey: CryptoKey, kid: string): JWSSigner { + return { + kid, + algorithm: "ES256", + format: "jws", + sign: async (signingInput: Uint8Array): Promise => { + const signature = await crypto.subtle.sign( + { name: "ECDSA", hash: "SHA-256" }, + privateKey, + signingInput, + ); + return jose.base64url.encode(new Uint8Array(signature)); + }, + }; +} + +/** + * Generate a P-256 (ES256) key pair for testing + * + * Returns both the CryptoKey (for signing) and JWK (for verification). + * + * @returns Promise resolving to privateKey CryptoKey and publicKey JWK + */ +export async function generateES256KeyPair(): Promise<{ + privateKey: CryptoKey; + publicKeyJWK: jose.JWK; +}> { + const keyPair = await crypto.subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, [ + "sign", + "verify", + ]); + + const publicKeyJWK = await crypto.subtle.exportKey("jwk", keyPair.publicKey); + + return { + privateKey: keyPair.privateKey, + publicKeyJWK, + }; +} + +// ============================================================================ +// secp256k1 (ES256K) Utilities - For EVM-compatible testing +// ============================================================================ + +/** + * SHA-256 hash using Web Crypto API + * + * @param data - The data to hash + * @returns The SHA-256 hash as Uint8Array + */ +async function sha256(data: Uint8Array): Promise { + const hashBuffer = await crypto.subtle.digest("SHA-256", data); + return new Uint8Array(hashBuffer); +} + +/** + * Create an ES256K (secp256k1) JWS signer from a JWK (FOR TESTING ONLY) + * + * @param jwk - The JWK private key + * @param kid - The key identifier + * @returns A JWS signer + */ +export async function createES256KSigner(jwk: jose.JWK, kid: string): Promise { + if (jwk.crv !== "secp256k1") { + throw new Error(`Unsupported curve: ${jwk.crv}. Use createJWSSigner for P-256.`); + } + if (!jwk.d) { + throw new Error("JWK must contain private key (d parameter)"); + } + + const privateKeyBytes = jose.base64url.decode(jwk.d); + + return { + kid, + algorithm: "ES256K", + format: "jws", + sign: async (signingInput: Uint8Array): Promise => { + const hash = await sha256(signingInput); + const signature = secp256k1.sign(hash, privateKeyBytes); + + // JWS uses concatenated r || s format (not DER) + const r = signature.r.toString(16).padStart(64, "0"); + const s = signature.s.toString(16).padStart(64, "0"); + const sigBytes = new Uint8Array(64); + for (let i = 0; i < 32; i++) { + sigBytes[i] = parseInt(r.slice(i * 2, i * 2 + 2), 16); + sigBytes[i + 32] = parseInt(s.slice(i * 2, i * 2 + 2), 16); + } + + return jose.base64url.encode(sigBytes); + }, + }; +} + +/** + * Generate an ES256K (secp256k1) key pair (FOR TESTING ONLY) + * + * @returns Promise resolving to an object with privateKey and publicKey JWKs + */ +export async function generateES256KKeyPair(): Promise<{ + privateKey: jose.JWK; + publicKey: jose.JWK; +}> { + const { privateKey, publicKey } = await jose.generateKeyPair("ES256K"); + return { + privateKey: await jose.exportJWK(privateKey), + publicKey: await jose.exportJWK(publicKey), + }; +} diff --git a/typescript/packages/extensions/test/offer-receipt.test.ts b/typescript/packages/extensions/test/offer-receipt.test.ts new file mode 100644 index 0000000000..504d98cfd7 --- /dev/null +++ b/typescript/packages/extensions/test/offer-receipt.test.ts @@ -0,0 +1,2144 @@ +/** + * Specification-driven tests for x402 Offer/Receipt Extension + */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { describe, it, expect, beforeAll, beforeEach, afterEach, vi } from "vitest"; +import * as jose from "jose"; +import { privateKeyToAccount } from "viem/accounts"; +import { recoverTypedDataAddress } from "viem"; +import type { Hex } from "viem"; + +import { + canonicalize, + hashCanonical, + getCanonicalBytes, + createJWS, + extractJWSHeader, + extractJWSPayload, + createOfferJWS, + createOfferEIP712, + extractOfferPayload, + createReceiptJWS, + createReceiptEIP712, + extractReceiptPayload, + createOfferDomain, + createReceiptDomain, + OFFER_TYPES, + RECEIPT_TYPES, + prepareOfferForEIP712, + prepareReceiptForEIP712, + hashOfferTypedData, + hashReceiptTypedData, + convertNetworkStringToCAIP2, + extractChainIdFromCAIP2, + extractEIP155ChainId, + extractOffersFromPaymentRequired, + decodeSignedOffers, + findAcceptsObjectFromSignedOffer, + extractReceiptFromResponse, + declareOfferReceiptExtension, + createJWSOfferReceiptIssuer, + createEIP712OfferReceiptIssuer, + verifyReceiptMatchesOffer, + verifyOfferSignatureEIP712, + verifyReceiptSignatureEIP712, + verifyOfferSignatureJWS, + verifyReceiptSignatureJWS, + extractPublicKeyFromKid, + OFFER_RECEIPT, + type JWSSigner, + type OfferPayload, + type ReceiptPayload, + type EIP712SignedOffer, + type EIP712SignedReceipt, + type JWSSignedOffer, +} from "../src/offer-receipt"; + +import { + createES256Signer, + generateES256KeyPair, + createES256KSigner, + generateES256KKeyPair, +} from "./offer-receipt-test-utils"; + +const TEST_PRIVATE_KEY = + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" as Hex; + +// ============================================================================ +// Core JWS Assembly Tests (Layer 1) +// These tests verify createJWS produces valid JWS compact serialization. +// Higher-level tests (createOfferJWS, createReceiptJWS) depend on this. +// ============================================================================ + +describe("createJWS (Core JWS Assembly)", () => { + let signer: JWSSigner; + let publicKeyJWK: jose.JWK; + + beforeAll(async () => { + const keyPair = await generateES256KeyPair(); + publicKeyJWK = keyPair.publicKeyJWK; + signer = createES256Signer(keyPair.privateKey, "did:web:example.com#key-1"); + }); + + it("produces valid JWS compact serialization (header.payload.signature)", async () => { + const payload = { test: "data", number: 42 }; + const jws = await createJWS(payload, signer); + + // Must be three dot-separated parts + const parts = jws.split("."); + expect(parts).toHaveLength(3); + expect(parts[0].length).toBeGreaterThan(0); // header + expect(parts[1].length).toBeGreaterThan(0); // payload + expect(parts[2].length).toBeGreaterThan(0); // signature + }); + + it("includes alg and kid in JWS header", async () => { + const payload = { test: "data" }; + const jws = await createJWS(payload, signer); + + const header = extractJWSHeader(jws); + expect(header.alg).toBe("ES256"); + expect(header.kid).toBe("did:web:example.com#key-1"); + }); + + it("encodes payload as canonicalized JSON", async () => { + // Keys in different order should produce same canonical form + const payload = { z: 1, a: 2 }; + const jws = await createJWS(payload, signer); + + const decoded = extractJWSPayload(jws); + expect(decoded).toEqual({ a: 2, z: 1 }); // Canonicalized order + }); + + it("produces signature verifiable with jose.compactVerify", async () => { + const payload = { resourceUrl: "https://example.com", amount: "1000" }; + const jws = await createJWS(payload, signer); + + const key = await jose.importJWK(publicKeyJWK); + const { payload: verifiedPayload } = await jose.compactVerify(jws, key); + const decoded = JSON.parse(new TextDecoder().decode(verifiedPayload)); + + expect(decoded.resourceUrl).toBe("https://example.com"); + expect(decoded.amount).toBe("1000"); + }); + + it("round-trips through extractJWSHeader and extractJWSPayload", async () => { + const payload = { version: 1, data: "test" }; + const jws = await createJWS(payload, signer); + + // Should be able to extract header and payload + const header = extractJWSHeader(jws); + const extractedPayload = extractJWSPayload(jws); + + expect(header.alg).toBe("ES256"); + expect(header.kid).toBe("did:web:example.com#key-1"); + expect(extractedPayload.version).toBe(1); + expect(extractedPayload.data).toBe("test"); + }); +}); + +describe("x402 Offer/Receipt Extension", () => { + describe("Β§3.1 Common Object Shape", () => { + describe("JWS format", () => { + let signer: JWSSigner; + beforeAll(async () => { + const keyPair = await generateES256KKeyPair(); + signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + }); + + it("JWS offer has format='jws', signature field, no payload field", async () => { + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + expect(offer.format).toBe("jws"); + expect(offer.signature).toMatch(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/); + expect(offer).not.toHaveProperty("payload"); + }); + }); + + describe("EIP-712 format", () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + it("EIP-712 offer has format='eip712', payload field, hex signature", async () => { + const offer = await createOfferEIP712( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + p => account.signTypedData(p), + ); + expect(offer.format).toBe("eip712"); + expect(offer).toHaveProperty("payload"); + expect(offer.signature).toMatch(/^0x[a-fA-F0-9]{130}$/); + }); + }); + }); + + describe("Β§3.2 EIP-712 Domain", () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + it("Offer domain: name='x402 offer', version='1', chainId=1 (canonical)", async () => { + await createOfferEIP712( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + p => { + expect(p.domain.name).toBe("x402 offer"); + expect(p.domain.version).toBe("1"); + expect(Number(p.domain.chainId)).toBe(1); + return account.signTypedData(p); + }, + ); + }); + + it("Receipt domain: name='x402 receipt', version='1', chainId=1 (canonical)", async () => { + await createReceiptEIP712( + { + resourceUrl: "https://api.example.com/resource", + payer: "0xabc123", + network: "eip155:8453", + }, + p => { + expect(p.domain.name).toBe("x402 receipt"); + expect(p.domain.version).toBe("1"); + expect(Number(p.domain.chainId)).toBe(1); + return account.signTypedData(p); + }, + ); + }); + + it("EIP-712 chainId is constant regardless of payment network", async () => { + // Even with different payment networks, chainId should always be 1 + await createOfferEIP712( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:137", // Polygon + asset: "native", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + p => { + expect(Number(p.domain.chainId)).toBe(1); // Still 1, not 137 + return account.signTypedData(p); + }, + ); + }); + }); + + describe("Β§3.3 JWS Header Requirements", () => { + it("JWS header MUST include alg and kid", async () => { + const keyPair = await generateES256KKeyPair(); + const expectedKid = "did:web:api.example.com#key-1"; + const signer = await createES256KSigner(keyPair.privateKey, expectedKid); + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + const header = JSON.parse( + new TextDecoder().decode(jose.base64url.decode(offer.signature.split(".")[0])), + ); + expect(header.alg).toBe("ES256K"); + expect(header.kid).toBe(expectedKid); + }); + }); + + describe("Β§4.2 Offer Payload Fields", () => { + it("Offer payload includes all required fields per spec v1.0", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const beforeCreate = Math.floor(Date.now() / 1000); + const offer = await createOfferJWS( + "https://api.example.com/premium", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + amount: "10000", + offerValiditySeconds: 60, + }, + signer, + ); + const payload = extractOfferPayload(offer); + // Required fields per spec Β§4.2 + expect(payload.version).toBe(1); + expect(payload.resourceUrl).toBe("https://api.example.com/premium"); + expect(payload.scheme).toBe("exact"); + expect(payload.network).toBe("eip155:8453"); + expect(payload.asset).toBe("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"); + expect(payload.payTo).toBe("0x209693Bc6afc0C5328bA36FaF03C514EF312287C"); + expect(payload.amount).toBe("10000"); + // validUntil should be approximately now + offerValiditySeconds + expect(payload.validUntil).toBeGreaterThanOrEqual(beforeCreate + 60); + expect(payload.validUntil).toBeLessThanOrEqual(beforeCreate + 62); // Allow 2s tolerance + }); + }); + + describe("Β§5.2 Receipt Payload Fields (Privacy-Minimal)", () => { + it("JWS receipt omits transaction when not provided (privacy-minimal)", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + signer, + ); + const payload = extractReceiptPayload(receipt); + // Required fields per spec Β§5.2 + expect(payload.version).toBe(1); + expect(payload.network).toBe("eip155:8453"); + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.payer).toBe("0x857b06519E91e3A54538791bDbb0E22373e36b66"); + expect(typeof payload.issuedAt).toBe("number"); + // Per spec: transaction is optional, should be omitted in JWS when not provided + expect(payload).not.toHaveProperty("transaction"); + }); + + it("JWS receipt includes transaction when provided", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + transaction: "0xabc123", + }, + signer, + ); + const payload = extractReceiptPayload(receipt); + expect(payload.transaction).toBe("0xabc123"); + }); + + it("EIP-712 receipt uses empty string for transaction when not provided", async () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + const receipt = await createReceiptEIP712( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + p => account.signTypedData(p), + ); + const payload = extractReceiptPayload(receipt); + // Per spec Β§5.3: EIP-712 MUST set unused optional fields to empty string + expect(payload.transaction).toBe(""); + }); + }); + + describe("JCS Canonicalization (RFC 8785)", () => { + it("sorts object keys lexicographically", () => { + expect(canonicalize({ z: 1, a: 2 })).toBe('{"a":2,"z":1}'); + }); + it("handles nested objects", () => { + expect(canonicalize({ b: { d: 1, c: 2 }, a: 3 })).toBe('{"a":3,"b":{"c":2,"d":1}}'); + }); + it("handles arrays (preserves order)", () => { + expect(canonicalize({ arr: [3, 1, 2] })).toBe('{"arr":[3,1,2]}'); + }); + it("handles -0 as 0", () => { + expect(canonicalize({ n: -0 })).toBe('{"n":0}'); + }); + }); + + describe("Cryptographic Verification", () => { + it("JWS signature verifies with jose.compactVerify", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const publicKey = await jose.importJWK(keyPair.publicKey); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const { payload } = await jose.compactVerify(offer.signature, publicKey); + const decoded = JSON.parse(new TextDecoder().decode(payload)); + expect(decoded.resourceUrl).toBe("https://api.example.com/resource"); + }); + + it("EIP-712 signature recovers correct signer", async () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + + const offer = await createOfferEIP712( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + p => account.signTypedData(p), + ); + + const recovered = await recoverTypedDataAddress({ + domain: createOfferDomain(), + types: OFFER_TYPES, + primaryType: "Offer", + message: prepareOfferForEIP712(offer.payload), + signature: offer.signature as Hex, + }); + + expect(recovered.toLowerCase()).toBe(account.address.toLowerCase()); + }); + }); +}); + +describe("Attestation Helper", () => { + describe("convertNetworkStringToCAIP2", () => { + it("passes through CAIP-2 format unchanged", () => { + expect(convertNetworkStringToCAIP2("eip155:8453")).toBe("eip155:8453"); + expect(convertNetworkStringToCAIP2("eip155:1")).toBe("eip155:1"); + expect(convertNetworkStringToCAIP2("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")).toBe( + "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", + ); + }); + + it("converts v1 Solana network names", () => { + expect(convertNetworkStringToCAIP2("solana")).toBe("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"); + expect(convertNetworkStringToCAIP2("Solana")).toBe("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"); + expect(convertNetworkStringToCAIP2("solana-devnet")).toBe( + "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", + ); + }); + + it("converts v1 EVM network names to CAIP-2", () => { + expect(convertNetworkStringToCAIP2("base")).toBe("eip155:8453"); + expect(convertNetworkStringToCAIP2("base-sepolia")).toBe("eip155:84532"); + expect(convertNetworkStringToCAIP2("ethereum")).toBe("eip155:1"); + expect(convertNetworkStringToCAIP2("polygon")).toBe("eip155:137"); + expect(convertNetworkStringToCAIP2("avalanche")).toBe("eip155:43114"); + }); + + it("throws for unknown network identifiers", () => { + expect(() => convertNetworkStringToCAIP2("unknown-network")).toThrow( + 'Unknown network identifier: "unknown-network"', + ); + expect(() => convertNetworkStringToCAIP2("foo")).toThrow('Unknown network identifier: "foo"'); + }); + }); + + describe("extractChainIdFromCAIP2", () => { + it("extracts chain ID from EVM networks", () => { + expect(extractChainIdFromCAIP2("eip155:8453")).toBe(8453); + expect(extractChainIdFromCAIP2("eip155:1")).toBe(1); + expect(extractChainIdFromCAIP2("eip155:137")).toBe(137); + }); + + it("returns undefined for non-EVM networks", () => { + expect(extractChainIdFromCAIP2("solana:mainnet")).toBeUndefined(); + expect(extractChainIdFromCAIP2("cosmos:cosmoshub-4")).toBeUndefined(); + }); + }); + + describe("extractReceiptPayload", () => { + it("extracts payload from JWS receipt", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + signer, + ); + + const payload = extractReceiptPayload(receipt); + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.payer).toBe("0x857b06519E91e3A54538791bDbb0E22373e36b66"); + expect(typeof payload.issuedAt).toBe("number"); + }); + + it("extracts payload from EIP-712 receipt", async () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + const receipt = await createReceiptEIP712( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + p => account.signTypedData(p), + ); + + const payload = extractReceiptPayload(receipt); + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.payer).toBe("0x857b06519E91e3A54538791bDbb0E22373e36b66"); + }); + }); +}); + +describe("Client Utilities", () => { + describe("extractOffersFromPaymentRequired", () => { + it("extracts offers from PaymentRequired extensions", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer1 = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const paymentRequired = { + accepts: [ + { + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + ], + extensions: { + [OFFER_RECEIPT]: { + info: { + offers: [offer1], + }, + }, + }, + }; + + const offers = extractOffersFromPaymentRequired(paymentRequired as any); + expect(offers).toHaveLength(1); + expect(offers[0].format).toBe("jws"); + }); + + it("returns empty array when no offers present", () => { + const paymentRequired = { + accepts: [], + extensions: {}, + }; + + const offers = extractOffersFromPaymentRequired(paymentRequired as any); + expect(offers).toEqual([]); + }); + + it("returns empty array when extensions is undefined", () => { + const paymentRequired = { + accepts: [], + }; + + const offers = extractOffersFromPaymentRequired(paymentRequired as any); + expect(offers).toEqual([]); + }); + }); + + describe("decodeSignedOffers", () => { + it("decodes JWS offers with payload fields at top level", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const decoded = decodeSignedOffers([offer]); + expect(decoded).toHaveLength(1); + expect(decoded[0].network).toBe("eip155:8453"); + expect(decoded[0].amount).toBe("10000"); + expect(decoded[0].format).toBe("jws"); + expect(decoded[0].acceptIndex).toBe(0); + expect(decoded[0].signedOffer).toBe(offer); + }); + + it("decodes EIP-712 offers", async () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + const offer = await createOfferEIP712( + "https://api.example.com/resource", + { + acceptIndex: 1, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "5000", + }, + p => account.signTypedData(p), + ); + + const decoded = decodeSignedOffers([offer]); + expect(decoded).toHaveLength(1); + expect(decoded[0].network).toBe("eip155:8453"); + expect(decoded[0].amount).toBe("5000"); + expect(decoded[0].format).toBe("eip712"); + expect(decoded[0].acceptIndex).toBe(1); + }); + + it("returns empty array for empty input", () => { + const decoded = decodeSignedOffers([]); + expect(decoded).toEqual([]); + }); + }); + + describe("findAcceptsObjectFromSignedOffer", () => { + it("finds matching accepts entry using acceptIndex hint", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const accepts = [ + { + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + maxAmountRequired: "10000", + }, + ]; + + const found = findAcceptsObjectFromSignedOffer(offer, accepts as any); + expect(found).toBeDefined(); + expect(found?.network).toBe("eip155:8453"); + }); + + it("finds matching accepts entry with DecodedOffer", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const decoded = decodeSignedOffers([offer])[0]; + const accepts = [ + { + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + maxAmountRequired: "10000", + }, + ]; + + const found = findAcceptsObjectFromSignedOffer(decoded, accepts as any); + expect(found).toBeDefined(); + expect(found?.network).toBe("eip155:8453"); + }); + + it("falls back to searching all accepts when hint misses", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 5, // Wrong index + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const accepts = [ + { + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + maxAmountRequired: "10000", + }, + ]; + + const found = findAcceptsObjectFromSignedOffer(offer, accepts as any); + expect(found).toBeDefined(); + expect(found?.network).toBe("eip155:8453"); + }); + + it("returns undefined when no match found", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const accepts = [ + { + scheme: "exact", + network: "eip155:1", // Different network + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + maxAmountRequired: "10000", + }, + ]; + + const found = findAcceptsObjectFromSignedOffer(offer, accepts as any); + expect(found).toBeUndefined(); + }); + }); + + describe("extractReceiptFromResponse", () => { + it("extracts receipt from PAYMENT-RESPONSE header", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + signer, + ); + + const settlementResponse = { + success: true, + extensions: { + [OFFER_RECEIPT]: { + info: { receipt }, + }, + }, + }; + + const headers = new Headers(); + headers.set("PAYMENT-RESPONSE", btoa(JSON.stringify(settlementResponse))); + + const response = new Response("OK", { headers }); + const extracted = extractReceiptFromResponse(response); + + expect(extracted).toBeDefined(); + expect(extracted?.format).toBe("jws"); + }); + + it("extracts receipt from X-PAYMENT-RESPONSE header", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + signer, + ); + + const settlementResponse = { + success: true, + extensions: { + [OFFER_RECEIPT]: { + info: { receipt }, + }, + }, + }; + + const headers = new Headers(); + headers.set("X-PAYMENT-RESPONSE", btoa(JSON.stringify(settlementResponse))); + + const response = new Response("OK", { headers }); + const extracted = extractReceiptFromResponse(response); + + expect(extracted).toBeDefined(); + expect(extracted?.format).toBe("jws"); + }); + + it("returns undefined when no header present", () => { + const response = new Response("OK"); + const extracted = extractReceiptFromResponse(response); + expect(extracted).toBeUndefined(); + }); + + it("returns undefined when header has no receipt", () => { + const settlementResponse = { + success: true, + extensions: {}, + }; + + const headers = new Headers(); + headers.set("PAYMENT-RESPONSE", btoa(JSON.stringify(settlementResponse))); + + const response = new Response("OK", { headers }); + const extracted = extractReceiptFromResponse(response); + expect(extracted).toBeUndefined(); + }); + }); + + describe("verifyReceiptMatchesOffer", () => { + it("returns true when receipt matches offer and payer", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const payerAddress = "0x857b06519E91e3A54538791bDbb0E22373e36b66"; + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: payerAddress, + network: "eip155:8453", + }, + signer, + ); + + const decoded = decodeSignedOffers([offer])[0]; + const result = verifyReceiptMatchesOffer(receipt, decoded, [payerAddress]); + expect(result).toBe(true); + }); + + it("returns true with case-insensitive payer address match", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + signer, + ); + + const decoded = decodeSignedOffers([offer])[0]; + // Uppercase payer address should still match + const result = verifyReceiptMatchesOffer(receipt, decoded, [ + "0x857B06519E91E3A54538791BDBB0E22373E36B66", + ]); + expect(result).toBe(true); + }); + + it("returns false when resourceUrl does not match", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const payerAddress = "0x857b06519E91e3A54538791bDbb0E22373e36b66"; + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/different-resource", + payer: payerAddress, + network: "eip155:8453", + }, + signer, + ); + + const decoded = decodeSignedOffers([offer])[0]; + const result = verifyReceiptMatchesOffer(receipt, decoded, [payerAddress]); + expect(result).toBe(false); + }); + + it("returns false when network does not match", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const payerAddress = "0x857b06519E91e3A54538791bDbb0E22373e36b66"; + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: payerAddress, + network: "eip155:1", // Different network + }, + signer, + ); + + const decoded = decodeSignedOffers([offer])[0]; + const result = verifyReceiptMatchesOffer(receipt, decoded, [payerAddress]); + expect(result).toBe(false); + }); + + it("returns false when payer does not match any address", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + signer, + ); + + const decoded = decodeSignedOffers([offer])[0]; + // Different payer address + const result = verifyReceiptMatchesOffer(receipt, decoded, [ + "0xDifferentAddress1234567890123456789012345", + ]); + expect(result).toBe(false); + }); + + it("returns true when payer matches one of multiple addresses", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + const payerAddress = "0x857b06519E91e3A54538791bDbb0E22373e36b66"; + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }, + signer, + ); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: payerAddress, + network: "eip155:8453", + }, + signer, + ); + + const decoded = decodeSignedOffers([offer])[0]; + // Multiple addresses, one matches + const result = verifyReceiptMatchesOffer(receipt, decoded, [ + "0xOtherAddress12345678901234567890123456789", + payerAddress, + "SolanaAddressHere", + ]); + expect(result).toBe(true); + }); + }); +}); + +describe("Utility Functions", () => { + describe("hashCanonical", () => { + it("returns SHA-256 hash of canonicalized object", async () => { + const hash = await hashCanonical({ b: 2, a: 1 }); + expect(hash).toBeInstanceOf(Uint8Array); + expect(hash.length).toBe(32); // SHA-256 produces 32 bytes + }); + + it("produces same hash for equivalent objects with different key order", async () => { + const hash1 = await hashCanonical({ z: 1, a: 2 }); + const hash2 = await hashCanonical({ a: 2, z: 1 }); + expect(hash1).toEqual(hash2); + }); + + it("produces different hashes for different objects", async () => { + const hash1 = await hashCanonical({ a: 1 }); + const hash2 = await hashCanonical({ a: 2 }); + expect(hash1).not.toEqual(hash2); + }); + }); + + describe("getCanonicalBytes", () => { + it("returns UTF-8 encoded canonical JSON", () => { + const bytes = getCanonicalBytes({ b: 2, a: 1 }); + expect(bytes).toBeInstanceOf(Uint8Array); + const decoded = new TextDecoder().decode(bytes); + expect(decoded).toBe('{"a":1,"b":2}'); + }); + + it("handles nested objects", () => { + const bytes = getCanonicalBytes({ outer: { z: 1, a: 2 } }); + const decoded = new TextDecoder().decode(bytes); + expect(decoded).toBe('{"outer":{"a":2,"z":1}}'); + }); + }); + + describe("hashOfferTypedData", () => { + it("returns EIP-712 hash for offer payload", () => { + const payload: OfferPayload = { + version: 1, + resourceUrl: "https://api.example.com/resource", + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + validUntil: 1700000000, + }; + const hash = hashOfferTypedData(payload); + expect(hash).toMatch(/^0x[a-fA-F0-9]{64}$/); + }); + }); + + describe("hashReceiptTypedData", () => { + it("returns EIP-712 hash for receipt payload", () => { + const payload: ReceiptPayload = { + version: 1, + network: "eip155:8453", + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + issuedAt: 1700000000, + transaction: "", + }; + const hash = hashReceiptTypedData(payload); + expect(hash).toMatch(/^0x[a-fA-F0-9]{64}$/); + }); + + it("produces different hashes for different payloads", () => { + const payload1: ReceiptPayload = { + version: 1, + network: "eip155:8453", + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + issuedAt: 1700000000, + transaction: "", + }; + const payload2: ReceiptPayload = { + ...payload1, + payer: "0x1234567890123456789012345678901234567890", + }; + const hash1 = hashReceiptTypedData(payload1); + const hash2 = hashReceiptTypedData(payload2); + expect(hash1).not.toBe(hash2); + }); + }); + + describe("extractEIP155ChainId", () => { + it("extracts chain ID from valid eip155 network string", () => { + expect(extractEIP155ChainId("eip155:8453")).toBe(8453); + expect(extractEIP155ChainId("eip155:1")).toBe(1); + expect(extractEIP155ChainId("eip155:137")).toBe(137); + }); + + it("throws for non-eip155 networks", () => { + expect(() => extractEIP155ChainId("solana:mainnet")).toThrow( + 'Invalid network format: solana:mainnet. Expected "eip155:"', + ); + }); + + it("throws for malformed eip155 strings", () => { + expect(() => extractEIP155ChainId("eip155:")).toThrow( + 'Invalid network format: eip155:. Expected "eip155:"', + ); + expect(() => extractEIP155ChainId("eip155:abc")).toThrow( + 'Invalid network format: eip155:abc. Expected "eip155:"', + ); + }); + + it("throws for strings without colon", () => { + expect(() => extractEIP155ChainId("base")).toThrow( + 'Invalid network format: base. Expected "eip155:"', + ); + }); + }); + + describe("createReceiptDomain", () => { + it("creates receipt domain with correct name, version, and canonical chainId", () => { + const domain = createReceiptDomain(); + expect(domain.name).toBe("x402 receipt"); + expect(domain.version).toBe("1"); + expect(domain.chainId).toBe(1); + }); + }); + + describe("prepareReceiptForEIP712", () => { + it("converts receipt payload to EIP-712 message format", () => { + const payload: ReceiptPayload = { + version: 1, + network: "eip155:8453", + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + issuedAt: 1700000000, + transaction: "0xabc123", + }; + const prepared = prepareReceiptForEIP712(payload); + expect(prepared.version).toBe(BigInt(1)); + expect(prepared.network).toBe("eip155:8453"); + expect(prepared.resourceUrl).toBe("https://api.example.com/resource"); + expect(prepared.payer).toBe("0x857b06519E91e3A54538791bDbb0E22373e36b66"); + expect(prepared.issuedAt).toBe(BigInt(1700000000)); + expect(prepared.transaction).toBe("0xabc123"); + }); + }); + + describe("RECEIPT_TYPES", () => { + it("has correct EIP-712 type definition", () => { + expect(RECEIPT_TYPES.Receipt).toBeDefined(); + expect(RECEIPT_TYPES.Receipt).toHaveLength(6); + const fieldNames = RECEIPT_TYPES.Receipt.map(f => f.name); + expect(fieldNames).toContain("version"); + expect(fieldNames).toContain("network"); + expect(fieldNames).toContain("resourceUrl"); + expect(fieldNames).toContain("payer"); + expect(fieldNames).toContain("issuedAt"); + expect(fieldNames).toContain("transaction"); + }); + }); +}); + +describe("Server Extension Utilities", () => { + describe("declareOfferReceiptExtension", () => { + it("returns extension declaration with default values", () => { + const declaration = declareOfferReceiptExtension(); + expect(declaration).toHaveProperty(OFFER_RECEIPT); + expect(declaration[OFFER_RECEIPT].includeTxHash).toBeUndefined(); + expect(declaration[OFFER_RECEIPT].offerValiditySeconds).toBeUndefined(); + }); + + it("returns extension declaration with custom config", () => { + const declaration = declareOfferReceiptExtension({ + includeTxHash: true, + offerValiditySeconds: 120, + }); + expect(declaration[OFFER_RECEIPT].includeTxHash).toBe(true); + expect(declaration[OFFER_RECEIPT].offerValiditySeconds).toBe(120); + }); + }); + + describe("createJWSOfferReceiptIssuer", () => { + it("creates issuer with correct properties", async () => { + const keyPair = await generateES256KKeyPair(); + const jwsSigner = await createES256KSigner( + keyPair.privateKey, + "did:web:api.example.com#key-1", + ); + + const issuer = createJWSOfferReceiptIssuer("did:web:api.example.com#key-1", jwsSigner); + + expect(issuer.kid).toBe("did:web:api.example.com#key-1"); + expect(issuer.format).toBe("jws"); + expect(typeof issuer.issueOffer).toBe("function"); + expect(typeof issuer.issueReceipt).toBe("function"); + }); + + it("issueOffer creates valid JWS offer", async () => { + const keyPair = await generateES256KKeyPair(); + const jwsSigner = await createES256KSigner( + keyPair.privateKey, + "did:web:api.example.com#key-1", + ); + const issuer = createJWSOfferReceiptIssuer("did:web:api.example.com#key-1", jwsSigner); + + const offer = await issuer.issueOffer("https://api.example.com/resource", { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }); + + expect(offer.format).toBe("jws"); + expect(offer.signature).toMatch(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/); + }); + + it("issueReceipt creates valid JWS receipt", async () => { + const keyPair = await generateES256KKeyPair(); + const jwsSigner = await createES256KSigner( + keyPair.privateKey, + "did:web:api.example.com#key-1", + ); + const issuer = createJWSOfferReceiptIssuer("did:web:api.example.com#key-1", jwsSigner); + + const receipt = await issuer.issueReceipt( + "https://api.example.com/resource", + "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "eip155:8453", + "0xabc123", + ); + + expect(receipt.format).toBe("jws"); + expect(receipt.signature).toMatch(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/); + }); + }); + + describe("createEIP712OfferReceiptIssuer", () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + + it("creates issuer with correct properties", () => { + const issuer = createEIP712OfferReceiptIssuer(`did:pkh:eip155:8453:${account.address}`, p => + account.signTypedData(p), + ); + + expect(issuer.kid).toBe(`did:pkh:eip155:8453:${account.address}`); + expect(issuer.format).toBe("eip712"); + expect(typeof issuer.issueOffer).toBe("function"); + expect(typeof issuer.issueReceipt).toBe("function"); + }); + + it("issueOffer creates valid EIP-712 offer", async () => { + const issuer = createEIP712OfferReceiptIssuer(`did:pkh:eip155:8453:${account.address}`, p => + account.signTypedData(p), + ); + + const offer = await issuer.issueOffer("https://api.example.com/resource", { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x1234567890123456789012345678901234567890", + amount: "10000", + }); + + expect(offer.format).toBe("eip712"); + expect(offer).toHaveProperty("payload"); + expect(offer.signature).toMatch(/^0x[a-fA-F0-9]{130}$/); + }); + + it("issueReceipt creates valid EIP-712 receipt", async () => { + const issuer = createEIP712OfferReceiptIssuer(`did:pkh:eip155:8453:${account.address}`, p => + account.signTypedData(p), + ); + + const receipt = await issuer.issueReceipt( + "https://api.example.com/resource", + "0x857b06519E91e3A54538791bDbb0E22373e36b66", + "eip155:8453", + "0xabc123", + ); + + expect(receipt.format).toBe("eip712"); + expect(receipt).toHaveProperty("payload"); + expect(receipt.signature).toMatch(/^0x[a-fA-F0-9]{130}$/); + }); + }); + + /** + * NOTE: createOfferReceiptExtension is not tested here because it requires + * a mock ResourceServer with PaymentRequiredContext and SettleResultContext. + * The extension hooks (enrichPaymentRequiredResponse, enrichSettlementResponse) + * depend on the full server context which would require significant mocking. + * The signer factories above test the core signing functionality. + */ +}); + +// ============================================================================ +// Signature Verification Tests +// ============================================================================ + +describe("Signature Verification", () => { + describe("EIP-712 Verification", () => { + describe("verifyOfferSignatureEIP712", () => { + it("should verify a valid EIP-712 signed offer and recover signer", async () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + + const offer = await createOfferEIP712( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + amount: "10000", + }, + p => account.signTypedData(p), + ); + + const result = await verifyOfferSignatureEIP712(offer); + + expect(result.signer.toLowerCase()).toBe(account.address.toLowerCase()); + expect(result.payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(result.payload.scheme).toBe("exact"); + expect(result.payload.network).toBe("eip155:8453"); + expect(result.payload.amount).toBe("10000"); + }); + + it("should throw for wrong format", async () => { + const invalidOffer = { + format: "jws", + signature: "test.jws.signature", + } as unknown as EIP712SignedOffer; + + await expect(verifyOfferSignatureEIP712(invalidOffer)).rejects.toThrow( + "Expected eip712 format", + ); + }); + + it("should throw for invalid offer payload", async () => { + const invalidOffer = { + format: "eip712", + payload: null, + signature: "0x1234", + } as unknown as EIP712SignedOffer; + + await expect(verifyOfferSignatureEIP712(invalidOffer)).rejects.toThrow( + "Invalid offer: missing or malformed payload", + ); + }); + + it("should recover different address for tampered signature", async () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + + const offer = await createOfferEIP712( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "native", + payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + amount: "10000", + }, + p => account.signTypedData(p), + ); + + // Tamper with the signature + const tamperedOffer = { + ...offer, + signature: offer.signature.slice(0, -4) + "0000", + }; + + // Should recover a different address (not throw) + const result = await verifyOfferSignatureEIP712(tamperedOffer); + expect(result.signer).toBeDefined(); + // The recovered address will likely be different + }); + }); + + describe("verifyReceiptSignatureEIP712", () => { + it("should verify a valid EIP-712 signed receipt and recover signer", async () => { + const account = privateKeyToAccount(TEST_PRIVATE_KEY); + + const receipt = await createReceiptEIP712( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + transaction: "0x1234567890abcdef", + }, + p => account.signTypedData(p), + ); + + const result = await verifyReceiptSignatureEIP712(receipt); + + expect(result.signer.toLowerCase()).toBe(account.address.toLowerCase()); + expect(result.payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(result.payload.payer).toBe("0x857b06519E91e3A54538791bDbb0E22373e36b66"); + expect(result.payload.network).toBe("eip155:8453"); + }); + + it("should throw for wrong format", async () => { + const invalidReceipt = { + format: "jws", + signature: "test.jws.signature", + } as unknown as EIP712SignedReceipt; + + await expect(verifyReceiptSignatureEIP712(invalidReceipt)).rejects.toThrow( + "Expected eip712 format", + ); + }); + + it("should throw for invalid receipt payload", async () => { + const invalidReceipt = { + format: "eip712", + payload: { version: 1 }, // missing payer + signature: "0x1234", + } as unknown as EIP712SignedReceipt; + + await expect(verifyReceiptSignatureEIP712(invalidReceipt)).rejects.toThrow( + "Invalid receipt: missing or malformed payload", + ); + }); + }); + }); + + describe("JWS Verification", () => { + describe("verifyOfferSignatureJWS", () => { + it("should verify a JWS signed offer with explicit public key", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + amount: "10000", + }, + signer, + ); + + // Pass JWK directly - function accepts both KeyLike and JWK + const payload = await verifyOfferSignatureJWS(offer, keyPair.publicKey); + + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.scheme).toBe("exact"); + expect(payload.amount).toBe("10000"); + }); + + it("should verify a JWS signed offer with JWK public key", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "native", + payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + amount: "5000", + }, + signer, + ); + + const payload = await verifyOfferSignatureJWS(offer, keyPair.publicKey); + + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.amount).toBe("5000"); + }); + + it("should verify a JWS signed offer by extracting key from did:jwk kid", async () => { + const keyPair = await generateES256KKeyPair(); + // Create signer with did:jwk kid (self-contained key) + const kid = `did:jwk:${jose.base64url.encode(JSON.stringify(keyPair.publicKey))}#0`; + const signer = await createES256KSigner(keyPair.privateKey, kid); + + const offer = await createOfferJWS( + "https://api.example.com/resource", + { + acceptIndex: 0, + scheme: "exact", + network: "eip155:8453", + asset: "native", + payTo: "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + amount: "7500", + }, + signer, + ); + + // No public key provided - should extract from kid + const payload = await verifyOfferSignatureJWS(offer); + + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.amount).toBe("7500"); + }); + + it("should throw for wrong format", async () => { + const invalidOffer = { + format: "eip712", + payload: {}, + signature: "0x1234", + } as unknown as JWSSignedOffer; + + await expect(verifyOfferSignatureJWS(invalidOffer)).rejects.toThrow("Expected jws format"); + }); + + it("should throw for invalid JWS signature", async () => { + const keyPair = await generateES256KKeyPair(); + + const invalidOffer: JWSSignedOffer = { + format: "jws", + signature: "invalid.jws.signature", + }; + + // Pass JWK directly + await expect(verifyOfferSignatureJWS(invalidOffer, keyPair.publicKey)).rejects.toThrow(); + }); + + it("should throw when no key provided and kid missing", async () => { + const { privateKey } = await jose.generateKeyPair("ES256K"); + const payload = JSON.stringify({ version: 1, resourceUrl: "test" }); + const jws = await new jose.CompactSign(new TextEncoder().encode(payload)) + .setProtectedHeader({ alg: "ES256K" }) // No kid + .sign(privateKey); + + const offer: JWSSignedOffer = { format: "jws", signature: jws }; + + await expect(verifyOfferSignatureJWS(offer)).rejects.toThrow( + "No public key provided and JWS header missing kid", + ); + }); + }); + + describe("verifyReceiptSignatureJWS", () => { + it("should verify a JWS signed receipt", async () => { + const keyPair = await generateES256KKeyPair(); + const signer = await createES256KSigner(keyPair.privateKey, "did:web:example.com"); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + }, + signer, + ); + + // Pass JWK directly + const payload = await verifyReceiptSignatureJWS(receipt, keyPair.publicKey); + + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.payer).toBe("0x857b06519E91e3A54538791bDbb0E22373e36b66"); + expect(payload.network).toBe("eip155:8453"); + }); + + it("should verify a JWS signed receipt by extracting key from did:jwk kid", async () => { + const keyPair = await generateES256KKeyPair(); + const kid = `did:jwk:${jose.base64url.encode(JSON.stringify(keyPair.publicKey))}#0`; + const signer = await createES256KSigner(keyPair.privateKey, kid); + + const receipt = await createReceiptJWS( + { + resourceUrl: "https://api.example.com/resource", + payer: "0x857b06519E91e3A54538791bDbb0E22373e36b66", + network: "eip155:8453", + transaction: "0xabcdef", + }, + signer, + ); + + // No public key provided - should extract from kid + const payload = await verifyReceiptSignatureJWS(receipt); + + expect(payload.resourceUrl).toBe("https://api.example.com/resource"); + expect(payload.transaction).toBe("0xabcdef"); + }); + }); + }); +}); + +// ============================================================================ +// DID Key Resolution Tests +// ============================================================================ + +describe("extractPublicKeyFromKid", () => { + describe("did:jwk", () => { + it("should extract key from did:jwk", async () => { + const { publicKey } = await jose.generateKeyPair("ES256K"); + const jwk = await jose.exportJWK(publicKey); + const kid = `did:jwk:${jose.base64url.encode(JSON.stringify(jwk))}`; + + const extractedKey = await extractPublicKeyFromKid(kid); + expect(extractedKey).toBeDefined(); + }); + + it("should handle did:jwk with fragment", async () => { + const { publicKey } = await jose.generateKeyPair("ES256"); + const jwk = await jose.exportJWK(publicKey); + const kid = `did:jwk:${jose.base64url.encode(JSON.stringify(jwk))}#key-1`; + + const extractedKey = await extractPublicKeyFromKid(kid); + expect(extractedKey).toBeDefined(); + }); + }); + + describe("did:key", () => { + it("should extract Ed25519 key from did:key", async () => { + // Known Ed25519 did:key (from did-key spec examples) + const kid = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"; + + const extractedKey = await extractPublicKeyFromKid(kid); + expect(extractedKey).toBeDefined(); + }); + }); + + describe("error cases", () => { + it("should throw for invalid DID format", async () => { + await expect(extractPublicKeyFromKid("not-a-did")).rejects.toThrow("Invalid DID format"); + }); + + it("should throw for unsupported DID method", async () => { + await expect(extractPublicKeyFromKid("did:unsupported:123")).rejects.toThrow( + 'Unsupported DID method "unsupported"', + ); + }); + + it("should throw for did:key with unsupported multibase", async () => { + await expect(extractPublicKeyFromKid("did:key:f1234")).rejects.toThrow( + "Unsupported multibase encoding", + ); + }); + }); + + describe("did:web", () => { + let originalFetch: typeof global.fetch; + + beforeEach(() => { + originalFetch = global.fetch; + }); + + afterEach(() => { + global.fetch = originalFetch; + }); + + it("should resolve did:web by fetching DID document", async () => { + const { publicKey } = await jose.generateKeyPair("ES256K"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:api.example.com", + verificationMethod: [ + { + id: "did:web:api.example.com#key-1", + type: "JsonWebKey2020", + controller: "did:web:api.example.com", + publicKeyJwk: jwk, + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:api.example.com#key-1"); + expect(extractedKey).toBeDefined(); + expect(global.fetch).toHaveBeenCalledWith( + "https://api.example.com/.well-known/did.json", + expect.any(Object), + ); + }); + + it("should resolve did:web with path", async () => { + const { publicKey } = await jose.generateKeyPair("ES256"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:example.com:users:alice", + verificationMethod: [ + { + id: "did:web:example.com:users:alice#key-1", + type: "JsonWebKey2020", + controller: "did:web:example.com:users:alice", + publicKeyJwk: jwk, + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:example.com:users:alice#key-1"); + expect(extractedKey).toBeDefined(); + expect(global.fetch).toHaveBeenCalledWith( + "https://example.com/users/alice/did.json", + expect.any(Object), + ); + }); + + it("should use http:// for did:web:localhost", async () => { + const { publicKey } = await jose.generateKeyPair("ES256"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:localhost%3A3000", + verificationMethod: [ + { + id: "did:web:localhost%3A3000#key-1", + type: "JsonWebKey2020", + controller: "did:web:localhost%3A3000", + publicKeyJwk: jwk, + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:localhost%3A3000#key-1"); + expect(extractedKey).toBeDefined(); + expect(global.fetch).toHaveBeenCalledWith( + "http://localhost:3000/.well-known/did.json", + expect.any(Object), + ); + }); + + it("should use http:// for did:web:127.0.0.1", async () => { + const { publicKey } = await jose.generateKeyPair("ES256"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:127.0.0.1%3A8080", + verificationMethod: [ + { + id: "did:web:127.0.0.1%3A8080#key-1", + type: "JsonWebKey2020", + controller: "did:web:127.0.0.1%3A8080", + publicKeyJwk: jwk, + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:127.0.0.1%3A8080#key-1"); + expect(extractedKey).toBeDefined(); + expect(global.fetch).toHaveBeenCalledWith( + "http://127.0.0.1:8080/.well-known/did.json", + expect.any(Object), + ); + }); + + it("should still use https:// for non-localhost domains", async () => { + const { publicKey } = await jose.generateKeyPair("ES256"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:example.com", + verificationMethod: [ + { + id: "did:web:example.com#key-1", + type: "JsonWebKey2020", + controller: "did:web:example.com", + publicKeyJwk: jwk, + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:example.com#key-1"); + expect(extractedKey).toBeDefined(); + expect(global.fetch).toHaveBeenCalledWith( + "https://example.com/.well-known/did.json", + expect.any(Object), + ); + }); + + it("should throw when did:web fetch fails", async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: false, + status: 404, + statusText: "Not Found", + }); + + await expect(extractPublicKeyFromKid("did:web:nonexistent.example.com")).rejects.toThrow( + "Failed to resolve did:web", + ); + }); + + it("should throw when verification method not found", async () => { + const didDocument = { + id: "did:web:api.example.com", + verificationMethod: [], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + await expect(extractPublicKeyFromKid("did:web:api.example.com#nonexistent")).rejects.toThrow( + "No verification method found", + ); + }); + + // Malformed DID Document Tests + + it("should throw when DID document has no verificationMethod array", async () => { + const didDocument = { id: "did:web:api.example.com" }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + await expect(extractPublicKeyFromKid("did:web:api.example.com#key-1")).rejects.toThrow( + "No verification method found", + ); + }); + + it("should throw when verification method has no key material", async () => { + const didDocument = { + id: "did:web:api.example.com", + verificationMethod: [ + { + id: "did:web:api.example.com#key-1", + type: "JsonWebKey2020", + controller: "did:web:api.example.com", + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + await expect(extractPublicKeyFromKid("did:web:api.example.com#key-1")).rejects.toThrow( + "has no supported key format", + ); + }); + + it("should throw when fetch returns invalid JSON", async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.reject(new Error("Invalid JSON")), + }); + + await expect(extractPublicKeyFromKid("did:web:api.example.com")).rejects.toThrow( + "Failed to resolve did:web", + ); + }); + + it("should throw when network error occurs", async () => { + global.fetch = vi.fn().mockRejectedValue(new Error("Network error")); + + await expect(extractPublicKeyFromKid("did:web:api.example.com")).rejects.toThrow( + "Failed to resolve did:web", + ); + }); + + // DID Document structure variations + + it("should resolve key from assertionMethod reference", async () => { + const { publicKey } = await jose.generateKeyPair("ES256K"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:api.example.com", + verificationMethod: [ + { + id: "did:web:api.example.com#key-1", + type: "JsonWebKey2020", + controller: "did:web:api.example.com", + publicKeyJwk: jwk, + }, + ], + assertionMethod: ["did:web:api.example.com#key-1"], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:api.example.com"); + expect(extractedKey).toBeDefined(); + }); + + it("should resolve key from authentication reference", async () => { + const { publicKey } = await jose.generateKeyPair("ES256K"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:api.example.com", + verificationMethod: [ + { + id: "did:web:api.example.com#auth-key", + type: "JsonWebKey2020", + controller: "did:web:api.example.com", + publicKeyJwk: jwk, + }, + ], + authentication: ["did:web:api.example.com#auth-key"], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:api.example.com"); + expect(extractedKey).toBeDefined(); + }); + + it("should resolve embedded verification method in assertionMethod", async () => { + const { publicKey } = await jose.generateKeyPair("ES256K"); + const jwk = await jose.exportJWK(publicKey); + + const didDocument = { + id: "did:web:api.example.com", + verificationMethod: [], + assertionMethod: [ + { + id: "did:web:api.example.com#embedded-key", + type: "JsonWebKey2020", + controller: "did:web:api.example.com", + publicKeyJwk: jwk, + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:api.example.com"); + expect(extractedKey).toBeDefined(); + }); + + it("should handle publicKeyMultibase format in did:web", async () => { + const didDocument = { + id: "did:web:api.example.com", + verificationMethod: [ + { + id: "did:web:api.example.com#key-1", + type: "Ed25519VerificationKey2020", + controller: "did:web:api.example.com", + publicKeyMultibase: "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK", + }, + ], + }; + + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(didDocument), + }); + + const extractedKey = await extractPublicKeyFromKid("did:web:api.example.com#key-1"); + expect(extractedKey).toBeDefined(); + }); + }); +}); + +// ============================================================================ +// Real DID Document Fixtures (captured from live endpoints) +// ============================================================================ + +describe("Real DID Document Fixtures", () => { + let originalFetch: typeof global.fetch; + + beforeEach(() => { + originalFetch = global.fetch; + }); + + afterEach(() => { + global.fetch = originalFetch; + }); + + // Captured from https://identity.foundation/.well-known/did.json (P-256 key) + const IDENTITY_FOUNDATION_DID_DOC = { + "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1"], + id: "did:web:identity.foundation", + verificationMethod: [ + { + id: "did:web:identity.foundation#XXS7zTsbIIAxgNlYEXJ4y810GFeLkYdqfK3ChhoQn7c", + type: "JsonWebKey2020", + controller: "did:web:identity.foundation", + publicKeyJwk: { + kty: "EC", + kid: "XXS7zTsbIIAxgNlYEXJ4y810GFeLkYdqfK3ChhoQn7c", + crv: "P-256", + alg: "ES256", + x: "TIIYSHfbBoXZi-B8Q5KBEmYpg6gXk0Getwt2nDPhxvI", + y: "zNbtUvyDHTdmtz3tyiw84UYgzma1X8r4ToP7PbCVHgI", + }, + }, + ], + authentication: ["did:web:identity.foundation#XXS7zTsbIIAxgNlYEXJ4y810GFeLkYdqfK3ChhoQn7c"], + assertionMethod: ["did:web:identity.foundation#XXS7zTsbIIAxgNlYEXJ4y810GFeLkYdqfK3ChhoQn7c"], + }; + + // Captured from https://demo.spruceid.com/.well-known/did.json (Ed25519 key) + const SPRUCE_DID_DOC = { + "@context": [ + "https://www.w3.org/ns/did/v1", + { "@id": "https://w3id.org/security#publicKeyJwk", "@type": "@json" }, + ], + id: "did:web:demo.spruceid.com", + verificationMethod: [ + { + id: "did:web:demo.spruceid.com#_t-v-Ep7AtkELhhvAzCCDzy1O5Bn_z1CVFv9yiRXdHY", + type: "Ed25519VerificationKey2018", + controller: "did:web:demo.spruceid.com", + publicKeyJwk: { + kty: "OKP", + crv: "Ed25519", + x: "2yv3J-Sf263OmwDLS9uFPTRD0PzbvfBGKLiSnPHtXIU", + }, + }, + ], + authentication: ["did:web:demo.spruceid.com#_t-v-Ep7AtkELhhvAzCCDzy1O5Bn_z1CVFv9yiRXdHY"], + assertionMethod: ["did:web:demo.spruceid.com#_t-v-Ep7AtkELhhvAzCCDzy1O5Bn_z1CVFv9yiRXdHY"], + }; + + it("should parse identity.foundation DID document (P-256)", async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(IDENTITY_FOUNDATION_DID_DOC), + }); + + const key = await extractPublicKeyFromKid( + "did:web:identity.foundation#XXS7zTsbIIAxgNlYEXJ4y810GFeLkYdqfK3ChhoQn7c", + ); + expect(key).toBeDefined(); + }); + + it("should parse identity.foundation via assertionMethod (no fragment)", async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(IDENTITY_FOUNDATION_DID_DOC), + }); + + const key = await extractPublicKeyFromKid("did:web:identity.foundation"); + expect(key).toBeDefined(); + }); + + it("should parse demo.spruceid.com DID document (Ed25519)", async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(SPRUCE_DID_DOC), + }); + + const key = await extractPublicKeyFromKid( + "did:web:demo.spruceid.com#_t-v-Ep7AtkELhhvAzCCDzy1O5Bn_z1CVFv9yiRXdHY", + ); + expect(key).toBeDefined(); + }); + + it("should parse demo.spruceid.com via assertionMethod (no fragment)", async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + json: () => Promise.resolve(SPRUCE_DID_DOC), + }); + + const key = await extractPublicKeyFromKid("did:web:demo.spruceid.com"); + expect(key).toBeDefined(); + }); +}); diff --git a/typescript/packages/extensions/tsup.config.ts b/typescript/packages/extensions/tsup.config.ts index f082e07998..bd85a73925 100644 --- a/typescript/packages/extensions/tsup.config.ts +++ b/typescript/packages/extensions/tsup.config.ts @@ -5,6 +5,7 @@ const baseConfig = { index: "src/index.ts", "bazaar/index": "src/bazaar/index.ts", "sign-in-with-x/index": "src/sign-in-with-x/index.ts", + "offer-receipt/index": "src/offer-receipt/index.ts", "payment-identifier/index": "src/payment-identifier/index.ts", }, dts: { diff --git a/typescript/pnpm-lock.yaml b/typescript/pnpm-lock.yaml index 9b3e47ec27..5d0d1f0597 100644 --- a/typescript/pnpm-lock.yaml +++ b/typescript/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: packages/extensions: dependencies: + '@noble/curves': + specifier: ^1.9.0 + version: 1.9.7 '@scure/base': specifier: ^1.2.6 version: 1.2.6 @@ -90,6 +93,9 @@ importers: ajv: specifier: ^8.17.1 version: 8.17.1 + jose: + specifier: ^5.9.6 + version: 5.10.0 siwe: specifier: ^2.3.2 version: 2.3.2(ethers@6.16.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) From 8931cb3b337ba4ab8d54c3d034992454608f310b Mon Sep 17 00:00:00 2001 From: JumpboxTech Date: Thu, 12 Mar 2026 07:30:34 -0600 Subject: [PATCH 060/129] fix(core): support Express-style :param dynamic route parameters (#1313) The route matching logic in parseRoutePattern only recognized Next.js-style [param] brackets and * wildcards. Express-style :param parameters passed through as literal characters, causing routes like /api/chapters/:seriesId to never match actual requests. Add a replacement step for :param patterns that converts them to [^/]+ (match one path segment), consistent with the existing [param] behavior. Includes tests for single params, multiple params, method-prefixed routes, and verification that :param does not match across path segments. Closes #673 --- .../support-express-style-route-params.md | 5 ++ .../core/src/http/x402HTTPResourceServer.ts | 5 +- .../unit/http/x402HTTPResourceService.test.ts | 78 +++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 typescript/.changeset/support-express-style-route-params.md diff --git a/typescript/.changeset/support-express-style-route-params.md b/typescript/.changeset/support-express-style-route-params.md new file mode 100644 index 0000000000..449fc73d09 --- /dev/null +++ b/typescript/.changeset/support-express-style-route-params.md @@ -0,0 +1,5 @@ +--- +"@x402/core": patch +--- + +Added support for Express-style `:param` dynamic route parameters in route matching. Routes like `/api/users/:id` and `/api/chapters/:seriesId/:chapterId` now match correctly alongside the existing `[param]` (Next.js) and `*` (wildcard) patterns. diff --git a/typescript/packages/core/src/http/x402HTTPResourceServer.ts b/typescript/packages/core/src/http/x402HTTPResourceServer.ts index 668ab2e89e..4d95371e89 100644 --- a/typescript/packages/core/src/http/x402HTTPResourceServer.ts +++ b/typescript/packages/core/src/http/x402HTTPResourceServer.ts @@ -877,7 +877,7 @@ export class x402HTTPResourceServer { /** * Parse route pattern into verb and regex * - * @param pattern - Route pattern like "GET /api/*" or "/api/[id]" + * @param pattern - Route pattern like "GET /api/*", "/api/[id]", or "/api/:id" * @returns Parsed pattern with verb and regex */ private parseRoutePattern(pattern: string): { verb: string; regex: RegExp } { @@ -888,7 +888,8 @@ export class x402HTTPResourceServer { path .replace(/[$()+.?^{|}]/g, "\\$&") // Escape regex special chars .replace(/\*/g, ".*?") // Wildcards - .replace(/\[([^\]]+)\]/g, "[^/]+") // Parameters + .replace(/\[([^\]]+)\]/g, "[^/]+") // Parameters (Next.js style [param]) + .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, "[^/]+") // Parameters (Express style :param) .replace(/\//g, "\\/") // Escape slashes }$`, "i", diff --git a/typescript/packages/core/test/unit/http/x402HTTPResourceService.test.ts b/typescript/packages/core/test/unit/http/x402HTTPResourceService.test.ts index 3c31df05e5..0587fe5f42 100644 --- a/typescript/packages/core/test/unit/http/x402HTTPResourceService.test.ts +++ b/typescript/packages/core/test/unit/http/x402HTTPResourceService.test.ts @@ -372,6 +372,84 @@ describe("x402HTTPResourceServer", () => { expect(result.type).toBe("payment-error"); // Route matched }); + it("should match Express-style :param dynamic routes", async () => { + const routes = { + "/api/chapters/:seriesId/:chapterId": { + accepts: { + scheme: "exact", + payTo: "0xabc", + price: "$1.00" as Price, + network: "eip155:8453" as Network, + }, + }, + }; + + const httpServer = new x402HTTPResourceServer(ResourceServer, routes); + + const adapter = new MockHTTPAdapter(); + const context: HTTPRequestContext = { + adapter, + path: "/api/chapters/abc123/chapter-7", + method: "GET", + }; + + const result = await httpServer.processHTTPRequest(context); + + expect(result.type).toBe("payment-error"); // Route matched + }); + + it("should match Express-style :param with HTTP method prefix", async () => { + const routes = { + "GET /api/users/:id": { + accepts: { + scheme: "exact", + payTo: "0xabc", + price: "$1.00" as Price, + network: "eip155:8453" as Network, + }, + }, + }; + + const httpServer = new x402HTTPResourceServer(ResourceServer, routes); + + const adapter = new MockHTTPAdapter(); + const context: HTTPRequestContext = { + adapter, + path: "/api/users/42", + method: "GET", + }; + + const result = await httpServer.processHTTPRequest(context); + + expect(result.type).toBe("payment-error"); // Route matched + }); + + it("should not match :param against paths with extra segments", async () => { + const routes = { + "/api/users/:id": { + accepts: { + scheme: "exact", + payTo: "0xabc", + price: "$1.00" as Price, + network: "eip155:8453" as Network, + }, + }, + }; + + const httpServer = new x402HTTPResourceServer(ResourceServer, routes); + + const adapter = new MockHTTPAdapter(); + const context: HTTPRequestContext = { + adapter, + path: "/api/users/42/posts", + method: "GET", + }; + + const result = await httpServer.processHTTPRequest(context); + + expect(result.type).toBe("no-payment-required"); + }); + it("should return no-payment-required for unmatched routes", async () => { const routes = { "/api/protected": { From 85ac66d88bed9ee006d41cd17ac353aea506c0f1 Mon Sep 17 00:00:00 2001 From: Pablo <72654865+moonshot-cyber@users.noreply.github.com> Date: Thu, 12 Mar 2026 20:19:58 +0000 Subject: [PATCH 061/129] ecosystem: add Agent Health Monitor (#1207) * ecosystem: add Agent Health Monitor * ecosystem: add AHM logo to public/logos and use local path Add agent-health-monitor.png to public/logos/ and update metadata.json to reference the local logo instead of an external GitHub raw URL. Co-Authored-By: Claude Opus 4.6 --------- Co-authored-by: Claude Opus 4.6 --- .../agent-health-monitor/metadata.json | 7 +++++++ .../site/public/logos/agent-health-monitor.png | Bin 0 -> 107659 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json create mode 100644 typescript/site/public/logos/agent-health-monitor.png diff --git a/typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json b/typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json new file mode 100644 index 0000000000..2ff2937c07 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Agent Health Monitor", + "description": "10-endpoint wallet intelligence API enriched with Nansen blockchain analytics. Risk scores, health checks, counterparty analysis, wallet network mapping, PnL summaries, and autonomous protection β€” all pay-per-call via x402 on Base.", + "logoUrl": "/logos/agent-health-monitor.png", + "websiteUrl": "https://agenthealthmonitor.xyz", + "category": "Services/Endpoints" +} diff --git a/typescript/site/public/logos/agent-health-monitor.png b/typescript/site/public/logos/agent-health-monitor.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d36b41edc0478e16390d30695c010de7284037 GIT binary patch literal 107659 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 Date: Fri, 13 Mar 2026 09:09:25 -0700 Subject: [PATCH 062/129] fix: e2e mainnet testing (#1585) * fix: e2e mainnet testing * fix: lock --- e2e/clients/axios/index.ts | 10 ++- e2e/clients/fetch/index.ts | 10 ++- e2e/pnpm-lock.yaml | 127 +++++++++++++++++------------- e2e/scripts/permit2-approval.ts | 42 ++++++---- e2e/servers/express/index.ts | 16 ++-- e2e/servers/gin/main.go | 31 ++++---- e2e/servers/hono/index.ts | 13 ++- e2e/servers/next/proxy.ts | 12 ++- e2e/src/clients/generic-client.ts | 2 + e2e/src/networks/networks.ts | 3 + e2e/src/servers/generic-server.ts | 1 + e2e/src/types.ts | 2 + e2e/test.ts | 2 + 13 files changed, 166 insertions(+), 105 deletions(-) diff --git a/e2e/clients/axios/index.ts b/e2e/clients/axios/index.ts index 9923e9a033..dc5b2a01e8 100644 --- a/e2e/clients/axios/index.ts +++ b/e2e/clients/axios/index.ts @@ -3,7 +3,7 @@ import axios from "axios"; import { wrapAxiosWithPayment, decodePaymentResponseHeader } from "@x402/axios"; import { createPublicClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; -import { baseSepolia } from "viem/chains"; +import { base, baseSepolia } from "viem/chains"; import { ExactEvmScheme, type ExactEvmSchemeOptions } from "@x402/evm/exact/client"; import { ExactEvmSchemeV1 } from "@x402/evm/v1"; import { toClientEvmSigner } from "@x402/evm"; @@ -27,9 +27,13 @@ const svmSigner = await createKeyPairSignerFromBytes( base58.decode(process.env.SVM_PRIVATE_KEY as string), ); +const evmNetwork = process.env.EVM_NETWORK || "eip155:84532"; +const evmRpcUrl = process.env.EVM_RPC_URL; +const evmChain = evmNetwork === "eip155:8453" ? base : baseSepolia; + const publicClient = createPublicClient({ - chain: baseSepolia, - transport: http(), + chain: evmChain, + transport: http(evmRpcUrl), }); const evmSigner = toClientEvmSigner(evmAccount, publicClient); diff --git a/e2e/clients/fetch/index.ts b/e2e/clients/fetch/index.ts index 809b7bc292..c698056320 100644 --- a/e2e/clients/fetch/index.ts +++ b/e2e/clients/fetch/index.ts @@ -2,7 +2,7 @@ import { config } from "dotenv"; import { wrapFetchWithPayment } from "@x402/fetch"; import { createPublicClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; -import { baseSepolia } from "viem/chains"; +import { base, baseSepolia } from "viem/chains"; import { ExactEvmScheme, type ExactEvmSchemeOptions } from "@x402/evm/exact/client"; import { ExactEvmSchemeV1 } from "@x402/evm/v1"; import { toClientEvmSigner } from "@x402/evm"; @@ -24,9 +24,13 @@ 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)); +const evmNetwork = process.env.EVM_NETWORK || "eip155:84532"; +const evmRpcUrl = process.env.EVM_RPC_URL; +const evmChain = evmNetwork === "eip155:8453" ? base : baseSepolia; + const publicClient = createPublicClient({ - chain: baseSepolia, - transport: http(), + chain: evmChain, + transport: http(evmRpcUrl), }); const evmSigner = toClientEvmSigner(evmAccount, publicClient); diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index 6cb78a3757..4c13181b6b 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -94,6 +94,9 @@ importers: ../typescript/packages/extensions: dependencies: + '@noble/curves': + specifier: ^1.9.0 + version: 1.9.7 '@scure/base': specifier: ^1.2.6 version: 1.2.6 @@ -103,6 +106,9 @@ importers: ajv: specifier: ^8.17.1 version: 8.17.1 + jose: + specifier: ^5.9.6 + version: 5.10.0 siwe: specifier: ^2.3.2 version: 2.3.2(ethers@6.16.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -1539,7 +1545,7 @@ importers: dependencies: '@coinbase/x402': specifier: ^0.7.3 - version: 0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(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 @@ -1606,11 +1612,8 @@ importers: specifier: workspace:* version: link:../../../../typescript/packages/legacy/x402 - facilitators/external-proxies/cdp-dev-new: + facilitators/external-proxies/cdp-local: 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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@x402/core': specifier: workspace:* version: link:../../../../typescript/packages/core @@ -1647,7 +1650,7 @@ importers: dependencies: '@coinbase/x402': specifier: ^0.7.3 - version: 0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(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 @@ -10545,11 +10548,11 @@ snapshots: - 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.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@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.19.0(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.2(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.2(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.2(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.19.0(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.19.0(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.19.0(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.13.4 @@ -10568,11 +10571,11 @@ snapshots: - 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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@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(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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.19.0(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.19.0(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))) + '@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.13.4 @@ -10712,11 +10715,11 @@ snapshots: - utf-8-validate - zod - '@coinbase/x402@0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@coinbase/x402@0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(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)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: 0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10) + x402: 0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10) zod: 3.25.71 transitivePeerDependencies: - '@azure/app-configuration' @@ -12462,6 +12465,10 @@ snapshots: dependencies: '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@solana-program/compute-budget@0.11.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))': + dependencies: + '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@solana-program/compute-budget@0.8.0(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) @@ -12470,14 +12477,14 @@ snapshots: 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.2(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.2(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.19.0(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.19.0(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@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) @@ -12493,6 +12500,11 @@ snapshots: '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana-program/token-2022@0.6.1(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(typescript@5.8.3))': + dependencies: + '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana-program/token@0.5.1(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) @@ -12501,14 +12513,14 @@ snapshots: 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.2(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.2(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.19.0(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.19.0(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.19.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -12517,6 +12529,10 @@ snapshots: dependencies: '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@solana-program/token@0.9.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))': + dependencies: + '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@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) @@ -13063,7 +13079,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.2(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.19.0(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) @@ -13077,11 +13093,11 @@ snapshots: '@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.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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 @@ -13089,7 +13105,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/kit@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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))': 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) @@ -13103,11 +13119,11 @@ snapshots: '@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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@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(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@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 @@ -13759,7 +13775,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/rpc-subscriptions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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) @@ -13767,7 +13783,7 @@ snapshots: '@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-channel-websocket': 3.0.3(typescript@5.8.3)(ws@8.19.0(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) @@ -13777,7 +13793,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/rpc-subscriptions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@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) @@ -13785,7 +13801,7 @@ snapshots: '@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.19.0(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)) '@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) @@ -14246,7 +14262,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.2(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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) @@ -14254,7 +14270,7 @@ snapshots: '@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.2(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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) @@ -14263,7 +14279,7 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@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) @@ -14271,7 +14287,7 @@ snapshots: '@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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@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) @@ -15356,7 +15372,7 @@ snapshots: - wagmi - zod - '@wagmi/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.71) '@coinbase/wallet-sdk': 4.3.6(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.71) @@ -15364,10 +15380,10 @@ snapshots: '@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)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@wagmi/core': 2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(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.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) + porto: 0.2.19(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) viem: 2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) optionalDependencies: typescript: 5.8.3 @@ -15448,14 +15464,13 @@ snapshots: - react - use-sync-external-store - '@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))': + '@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) zustand: 5.0.0(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) optionalDependencies: - '@tanstack/query-core': 5.90.8 typescript: 5.8.3 transitivePeerDependencies: - '@types/react' @@ -19026,9 +19041,9 @@ snapshots: - immer - use-sync-external-store - porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)): + porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@wagmi/core': 2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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) @@ -19040,7 +19055,7 @@ snapshots: '@tanstack/react-query': 5.90.8(react@19.2.3) react: 19.2.3 typescript: 5.8.3 - wagmi: 2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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 @@ -19390,7 +19405,7 @@ snapshots: buffer: 6.0.3 eventemitter3: 5.0.1 uuid: 8.3.2 - ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: bufferutil: 4.0.9 utf-8-validate: 5.0.10 @@ -20558,11 +20573,11 @@ snapshots: - utf-8-validate - zod - wagmi@2.18.2(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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.3) - '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.8)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) + '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) viem: 2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) @@ -20731,12 +20746,12 @@ snapshots: bufferutil: 4.0.9 utf-8-validate: 5.0.10 - x402@0.7.3(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.8)(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10): + x402@0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10): dependencies: '@scure/base': 1.2.6 - '@solana-program/compute-budget': 0.11.0(@solana/kit@5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@solana-program/token': 0.9.0(@solana/kit@5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@solana-program/token-2022': 0.6.1(@solana/kit@5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana-program/compute-budget': 0.11.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@solana-program/token': 0.9.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@solana-program/token-2022': 0.6.1(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(typescript@5.8.3)) '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) '@solana/transaction-confirmation': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) '@solana/wallet-standard-features': 1.3.0 @@ -20744,7 +20759,7 @@ snapshots: '@wallet-standard/base': 1.1.0 '@wallet-standard/features': 1.1.0 viem: 2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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' diff --git a/e2e/scripts/permit2-approval.ts b/e2e/scripts/permit2-approval.ts index b8df93cd6c..326a757481 100644 --- a/e2e/scripts/permit2-approval.ts +++ b/e2e/scripts/permit2-approval.ts @@ -24,27 +24,37 @@ import { getAddress, } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; -import { baseSepolia } from 'viem/chains'; +import { base, baseSepolia } from 'viem/chains'; config(); // Permit2 canonical address (same on all EVM chains) const PERMIT2_ADDRESS = '0x000000000022D473030F116dDEE9F6B43aC78BA3'; -// Known tokens on Base Sepolia -const TOKENS: Record = { - USDC: { - address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', - decimals: 6, - name: 'USDC', +const evmNetwork = process.env.EVM_NETWORK || 'eip155:84532'; +const evmRpcUrl = process.env.EVM_RPC_URL; +const evmChain = evmNetwork === 'eip155:8453' ? base : baseSepolia; +const isMainnet = evmNetwork === 'eip155:8453'; + +const TOKENS_BY_NETWORK: Record> = { + 'eip155:84532': { + USDC: { + address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', + decimals: 6, + name: 'USDC', + }, }, - MockERC20: { - address: '0xeED520980fC7C7B4eB379B96d61CEdea2423005a', - decimals: 6, - name: 'MockERC20', + 'eip155:8453': { + USDC: { + address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', + decimals: 6, + name: 'USDC', + }, }, }; +const TOKENS = TOKENS_BY_NETWORK[evmNetwork] || TOKENS_BY_NETWORK['eip155:84532']; + // Maximum uint256 for unlimited approval const MAX_UINT256 = 2n ** 256n - 1n; @@ -83,18 +93,18 @@ Environment variables required: const account = privateKeyToAccount(privateKey as `0x${string}`); const publicClient = createPublicClient({ - chain: baseSepolia, - transport: http(), + chain: evmChain, + transport: http(evmRpcUrl), }); const walletClient = createWalletClient({ account, - chain: baseSepolia, - transport: http(), + chain: evmChain, + transport: http(evmRpcUrl), }); console.log(`\nπŸ”‘ Wallet: ${account.address}`); - console.log(`πŸ“ Network: Base Sepolia`); + console.log(`πŸ“ Network: ${evmChain.name} (${evmNetwork})`); console.log(`πŸ” Permit2: ${PERMIT2_ADDRESS}\n`); // Display balance and allowance for all known tokens diff --git a/e2e/servers/express/index.ts b/e2e/servers/express/index.ts index 2dd496bfac..9d79bd5303 100644 --- a/e2e/servers/express/index.ts +++ b/e2e/servers/express/index.ts @@ -29,6 +29,7 @@ const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${s const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") 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 EVM_PERMIT2_ASSET = process.env.EVM_PERMIT2_ASSET as `0x${string}`; const APTOS_PAYEE_ADDRESS = process.env.APTOS_PAYEE_ADDRESS as string; const STELLAR_PAYEE_ADDRESS = process.env.STELLAR_PAYEE_ADDRESS as string | undefined; const facilitatorUrl = process.env.FACILITATOR_URL; @@ -192,7 +193,7 @@ app.use( }, } : {}), - // Permit2 endpoint for generic ERC-20 tokens (no EIP-2612, uses raw approve tx) + // Permit2 endpoint for ERC-20 approval gas sponsoring (no EIP-2612) "GET /protected-permit2-erc20": { accepts: { payTo: EVM_PAYEE_ADDRESS, @@ -200,10 +201,9 @@ app.use( network: EVM_NETWORK, price: { amount: "1000", - asset: "0xeED520980fC7C7B4eB379B96d61CEdea2423005a", // Generic MockERC20 token (no EIP-2612) + asset: EVM_PERMIT2_ASSET, extra: { assetTransferMethod: "permit2", - // No name/version - generic ERC-20 without EIP-2612 }, }, }, @@ -217,9 +217,13 @@ app.use( payTo: EVM_PAYEE_ADDRESS, scheme: "exact", network: EVM_NETWORK, - price: "$0.001", - // Use pre-parsed price with assetTransferMethod to force Permit2 - extra: { assetTransferMethod: "permit2" }, + price: { + amount: "1000", + asset: EVM_PERMIT2_ASSET, + extra: { + assetTransferMethod: "permit2", + }, + }, }, extensions: { ...declareDiscoveryExtension({ diff --git a/e2e/servers/gin/main.go b/e2e/servers/gin/main.go index 65ad0adeba..9264df11d8 100644 --- a/e2e/servers/gin/main.go +++ b/e2e/servers/gin/main.go @@ -72,6 +72,11 @@ func main() { evmNetwork := x402.Network(evmNetworkStr) svmNetwork := x402.Network(svmNetworkStr) + evmPermit2Asset := os.Getenv("EVM_PERMIT2_ASSET") + if evmPermit2Asset == "" { + evmPermit2Asset = "0x036CbD53842c5426634e7929541eC2318f3dCF7e" + } + 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) @@ -150,15 +155,14 @@ func main() { Scheme: "exact", PayTo: evmPayeeAddress, Network: evmNetwork, - // Use pre-parsed price with assetTransferMethod to force Permit2 - Price: map[string]interface{}{ - "amount": "1000", // 0.001 USDC (6 decimals) - "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // Base Sepolia USDC - "extra": map[string]interface{}{ - "assetTransferMethod": "permit2", - }, + Price: map[string]interface{}{ + "amount": "1000", + "asset": evmPermit2Asset, + "extra": map[string]interface{}{ + "assetTransferMethod": "permit2", }, }, + }, }, Extensions: func() map[string]interface{} { ext := map[string]interface{}{ @@ -178,15 +182,14 @@ func main() { Scheme: "exact", PayTo: evmPayeeAddress, Network: evmNetwork, - // Use MockGenericERC20 token that does NOT implement EIP-2612 - Price: map[string]interface{}{ - "amount": "1000", // smallest unit - "asset": "0xeED520980fC7C7B4eB379B96d61CEdea2423005a", // MockGenericERC20 on Base Sepolia - "extra": map[string]interface{}{ - "assetTransferMethod": "permit2", - }, + Price: map[string]interface{}{ + "amount": "1000", + "asset": evmPermit2Asset, + "extra": map[string]interface{}{ + "assetTransferMethod": "permit2", }, }, + }, }, Extensions: func() map[string]interface{} { ext := map[string]interface{}{ diff --git a/e2e/servers/hono/index.ts b/e2e/servers/hono/index.ts index 3e29980b63..531747be38 100644 --- a/e2e/servers/hono/index.ts +++ b/e2e/servers/hono/index.ts @@ -32,6 +32,7 @@ const EVM_PAYEE_ADDRESS = process.env.EVM_PAYEE_ADDRESS as `0x${string}`; const SVM_PAYEE_ADDRESS = process.env.SVM_PAYEE_ADDRESS as string; const APTOS_PAYEE_ADDRESS = process.env.APTOS_PAYEE_ADDRESS as string; const STELLAR_PAYEE_ADDRESS = process.env.STELLAR_PAYEE_ADDRESS as string | undefined; +const EVM_PERMIT2_ASSET = process.env.EVM_PERMIT2_ASSET as `0x${string}`; const facilitatorUrl = process.env.FACILITATOR_URL; if (!EVM_PAYEE_ADDRESS) { @@ -202,9 +203,13 @@ app.use( payTo: EVM_PAYEE_ADDRESS, scheme: "exact", network: EVM_NETWORK, - price: "$0.001", - // Use pre-parsed price with assetTransferMethod to force Permit2 - extra: { assetTransferMethod: "permit2" }, + price: { + amount: "1000", + asset: EVM_PERMIT2_ASSET, + extra: { + assetTransferMethod: "permit2", + }, + }, }, extensions: { ...declareDiscoveryExtension({ @@ -234,7 +239,7 @@ app.use( network: EVM_NETWORK, price: { amount: "1000", - asset: "0xeED520980fC7C7B4eB379B96d61CEdea2423005a", + asset: EVM_PERMIT2_ASSET, extra: { assetTransferMethod: "permit2", }, diff --git a/e2e/servers/next/proxy.ts b/e2e/servers/next/proxy.ts index 02a4797382..83bb44e1d8 100644 --- a/e2e/servers/next/proxy.ts +++ b/e2e/servers/next/proxy.ts @@ -20,6 +20,7 @@ export const SVM_NETWORK = (process.env.SVM_NETWORK || export const APTOS_NETWORK = (process.env.APTOS_NETWORK || "aptos:2") as `${string}:${string}`; export const STELLAR_NETWORK = (process.env.STELLAR_NETWORK || "stellar:testnet") as `${string}:${string}`; +const EVM_PERMIT2_ASSET = process.env.EVM_PERMIT2_ASSET as `0x${string}`; const facilitatorUrl = process.env.FACILITATOR_URL; if (!facilitatorUrl) { @@ -163,8 +164,13 @@ export const proxy = paymentProxy( payTo: EVM_PAYEE_ADDRESS, scheme: "exact", network: EVM_NETWORK, - price: "$0.001", - extra: { assetTransferMethod: "permit2" }, + price: { + amount: "1000", + asset: EVM_PERMIT2_ASSET, + extra: { + assetTransferMethod: "permit2", + }, + }, }, extensions: { ...declareDiscoveryExtension({ @@ -194,7 +200,7 @@ export const proxy = paymentProxy( network: EVM_NETWORK, price: { amount: "1000", - asset: "0xeED520980fC7C7B4eB379B96d61CEdea2423005a", + asset: EVM_PERMIT2_ASSET, extra: { assetTransferMethod: "permit2", }, diff --git a/e2e/src/clients/generic-client.ts b/e2e/src/clients/generic-client.ts index 1bad2d5e94..aff2ed44a0 100644 --- a/e2e/src/clients/generic-client.ts +++ b/e2e/src/clients/generic-client.ts @@ -26,6 +26,8 @@ export class GenericClientProxy extends BaseProxy implements ClientProxy { STELLAR_PRIVATE_KEY: config.stellarPrivateKey, RESOURCE_SERVER_URL: config.serverUrl, ENDPOINT_PATH: config.endpointPath, + EVM_NETWORK: config.evmNetwork, + EVM_RPC_URL: config.evmRpcUrl, } }; diff --git a/e2e/src/networks/networks.ts b/e2e/src/networks/networks.ts index 8425f255e2..5d8441a1b6 100644 --- a/e2e/src/networks/networks.ts +++ b/e2e/src/networks/networks.ts @@ -12,6 +12,7 @@ export type NetworkConfig = { name: string; caip2: `${string}:${string}`; rpcUrl: string; + permit2Asset?: string; }; export type NetworkSet = { @@ -30,6 +31,7 @@ const NETWORK_SETS: Record = { name: 'Base Sepolia', caip2: 'eip155:84532', rpcUrl: process.env.BASE_SEPOLIA_RPC_URL || 'https://sepolia.base.org', + permit2Asset: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', }, svm: { name: 'Solana Devnet', @@ -52,6 +54,7 @@ const NETWORK_SETS: Record = { name: 'Base', caip2: 'eip155:8453', rpcUrl: process.env.BASE_RPC_URL || 'https://mainnet.base.org', + permit2Asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', }, svm: { name: 'Solana', diff --git a/e2e/src/servers/generic-server.ts b/e2e/src/servers/generic-server.ts index 36c7895d80..0c42f87b1a 100644 --- a/e2e/src/servers/generic-server.ts +++ b/e2e/src/servers/generic-server.ts @@ -92,6 +92,7 @@ export class GenericServerProxy extends BaseProxy implements ServerProxy { EVM_NETWORK: evmNetwork, EVM_RPC_URL: config.networks.evm.rpcUrl, EVM_PAYEE_ADDRESS: config.evmPayTo, + EVM_PERMIT2_ASSET: config.networks.evm.permit2Asset || '', // SVM network config SVM_NETWORK: svmNetwork, diff --git a/e2e/src/types.ts b/e2e/src/types.ts index cfa2c2940c..6d893d302f 100644 --- a/e2e/src/types.ts +++ b/e2e/src/types.ts @@ -19,6 +19,8 @@ export interface ClientConfig { stellarPrivateKey: string; serverUrl: string; endpointPath: string; + evmNetwork: string; + evmRpcUrl: string; } export interface ServerConfig { diff --git a/e2e/test.ts b/e2e/test.ts index 9188a2a3a6..d8ba95d189 100644 --- a/e2e/test.ts +++ b/e2e/test.ts @@ -531,6 +531,8 @@ async function runTest() { stellarPrivateKey: clientStellarPrivateKey || '', serverUrl: `http://localhost:${port}`, endpointPath: scenario.endpoint.path, + evmNetwork: networks.evm.caip2, + evmRpcUrl: networks.evm.rpcUrl, }; try { From d1ad494421c34c04ea86c0cb6665d818d3fedb61 Mon Sep 17 00:00:00 2001 From: phdargen Date: Sat, 14 Mar 2026 01:41:14 +0900 Subject: [PATCH 063/129] fix ts changeset version bumps (#1588) --- examples/typescript/pnpm-lock.yaml | 583 +++++++++++++----- typescript/.changeset/config.json | 27 +- typescript/packages/http/express/package.json | 2 +- typescript/packages/http/hono/package.json | 2 +- typescript/packages/http/next/package.json | 2 +- typescript/pnpm-lock.yaml | 10 +- 6 files changed, 459 insertions(+), 167 deletions(-) diff --git a/examples/typescript/pnpm-lock.yaml b/examples/typescript/pnpm-lock.yaml index eec18decf0..9b065b182e 100644 --- a/examples/typescript/pnpm-lock.yaml +++ b/examples/typescript/pnpm-lock.yaml @@ -213,7 +213,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall viem: specifier: ^2.39.3 @@ -341,7 +341,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall zod: specifier: ^3.24.2 @@ -405,7 +405,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall next: specifier: ^16.0.10 @@ -1633,7 +1633,7 @@ importers: version: 16.6.1 openai: specifier: ^4.77.3 - version: 4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + version: 4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) viem: specifier: ^2.39.0 version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -1984,10 +1984,10 @@ importers: dependencies: '@coinbase/onchainkit': specifier: 1.1.2 - version: 1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76))(zod@3.25.76) + version: 1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(zod@4.1.13) '@farcaster/miniapp-sdk': specifier: 0.2.1 - version: 0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@tanstack/react-query': specifier: ^5 version: 5.90.11(react@19.2.3) @@ -2014,10 +2014,10 @@ importers: version: 19.2.3(react@19.2.3) viem: specifier: ^2.27.2 - version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + version: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) wagmi: specifier: ^2.14.11 - version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + version: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) devDependencies: '@eslint/js': specifier: ^9.24.0 @@ -3483,70 +3483,6 @@ importers: specifier: ^5.3.0 version: 5.9.2 - servers/receipt-attestation: - 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.4.7 - version: 16.6.1 - express: - specifier: ^4.18.2 - version: 4.21.2 - viem: - specifier: ^2.39.0 - version: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - devDependencies: - '@eslint/js': - specifier: ^9.24.0 - version: 9.33.0 - '@types/express': - specifier: ^5.0.1 - version: 5.0.3 - '@types/node': - specifier: ^20.0.0 - version: 20.19.11 - '@typescript-eslint/eslint-plugin': - specifier: ^8.29.1 - version: 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) - '@typescript-eslint/parser': - specifier: ^8.29.1 - version: 8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2) - eslint: - specifier: ^9.24.0 - version: 9.33.0(jiti@2.6.1) - eslint-plugin-import: - specifier: ^2.31.0 - version: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.33.0(jiti@2.6.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.33.0(jiti@2.6.1)) - eslint-plugin-jsdoc: - specifier: ^50.6.9 - version: 50.8.0(eslint@9.33.0(jiti@2.6.1)) - eslint-plugin-prettier: - specifier: ^5.2.6 - version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.6.1)))(eslint@9.33.0(jiti@2.6.1))(prettier@3.5.2) - prettier: - specifier: 3.5.2 - version: 3.5.2 - tsx: - specifier: ^4.7.0 - version: 4.20.4 - typescript: - specifier: ^5.3.0 - version: 5.9.2 - servers/sign-in-with-x: dependencies: '@x402/core': @@ -14621,16 +14557,16 @@ snapshots: - ws - zod - '@base-org/account@2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)': + '@base-org/account@2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)': dependencies: '@coinbase/cdp-sdk': 1.39.0(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@noble/hashes': 1.4.0 clsx: 1.2.1 eventemitter3: 5.0.1 idb-keyval: 6.2.1 - ox: 0.6.9(typescript@5.9.2)(zod@3.25.76) + ox: 0.6.9(typescript@5.9.2)(zod@4.1.13) preact: 10.24.2 - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) zustand: 5.0.3(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) transitivePeerDependencies: - '@types/react' @@ -14975,10 +14911,10 @@ snapshots: - ws - zod - '@coinbase/onchainkit@1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76))(zod@3.25.76)': + '@coinbase/onchainkit@1.1.2(@tanstack/query-core@5.90.11)(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13))(zod@4.1.13)': dependencies: - '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@farcaster/miniapp-wagmi-connector': 1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@farcaster/miniapp-wagmi-connector': 1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@floating-ui/react': 0.27.16(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -14986,7 +14922,7 @@ snapshots: '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-toast': 1.2.15(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) clsx: 2.1.1 graphql: 16.11.0 graphql-request: 6.1.0(encoding@0.1.13)(graphql@16.11.0) @@ -14995,8 +14931,8 @@ snapshots: react-dom: 19.2.3(react@19.2.3) tailwind-merge: 3.4.0 usehooks-ts: 3.1.1(react@19.2.3) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@tanstack/query-core' - '@types/react' @@ -15123,15 +15059,15 @@ snapshots: - utf-8-validate - zod - '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76)': + '@coinbase/wallet-sdk@4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13)': 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.9.2)(zod@3.25.76) + ox: 0.6.9(typescript@5.9.2)(zod@4.1.13) preact: 10.24.2 - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) zustand: 5.0.3(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) transitivePeerDependencies: - '@types/react' @@ -15694,11 +15630,11 @@ snapshots: - utf-8-validate - zod - '@farcaster/miniapp-wagmi-connector@1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': + '@farcaster/miniapp-wagmi-connector@1.0.0(@farcaster/miniapp-sdk@0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))': dependencies: - '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@farcaster/miniapp-sdk': 0.1.9(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@farcaster/miniapp-wagmi-connector@1.0.0(@farcaster/miniapp-sdk@0.2.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.1)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.1))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(viem@2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': dependencies: @@ -17784,7 +17720,7 @@ snapshots: dependencies: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -17814,13 +17750,13 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-controllers@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -17988,12 +17924,12 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-pay@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-pay@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) lit: 3.3.0 valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) transitivePeerDependencies: @@ -18171,12 +18107,12 @@ snapshots: - valtio - zod - '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76)': + '@reown/appkit-scaffold-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 transitivePeerDependencies: @@ -18343,10 +18279,10 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit-ui@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) lit: 3.3.0 qrcode: 1.5.3 @@ -18495,7 +18431,7 @@ snapshots: '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: @@ -18525,16 +18461,16 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76)': + '@reown/appkit-utils@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-polyfills': 1.7.8 '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/logger': 2.1.2 - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -18710,7 +18646,7 @@ snapshots: '@reown/appkit-utils': 1.7.8(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.1.10)(react@19.2.3))(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.1.10)(react@19.2.3) viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) @@ -18741,21 +18677,21 @@ snapshots: - utf-8-validate - zod - '@reown/appkit@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@reown/appkit@1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': dependencies: - '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-pay': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-controllers': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-pay': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@reown/appkit-polyfills': 1.7.8 - '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) - '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@3.25.76) + '@reown/appkit-scaffold-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) + '@reown/appkit-ui': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@reown/appkit-utils': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(valtio@1.13.2(@types/react@19.2.1)(react@19.2.3))(zod@4.1.13) '@reown/appkit-wallet': 1.7.8(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10) '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) bs58: 6.0.0 valtio: 1.13.2(@types/react@19.2.1)(react@19.2.3) - viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.43.5(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -22079,18 +22015,18 @@ snapshots: - utf-8-validate - zod - '@wagmi/connectors@6.2.0(26b6de6e2b894d3d8ec3de3fd9d7a34e)': + '@wagmi/connectors@6.2.0(1aee367860625464d156864b651beb8c)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@base-org/account': 2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 @@ -22132,19 +22068,19 @@ snapshots: - ws - zod - '@wagmi/connectors@6.2.0(696284975690661567148e5458660a80)': + '@wagmi/connectors@6.2.0(26b6de6e2b894d3d8ec3de3fd9d7a34e)': dependencies: - '@base-org/account': 2.4.0(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) - '@coinbase/wallet-sdk': 4.3.6(@types/react@19.2.1)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.76) - '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@base-org/account': 2.4.0(@types/react@19.1.10)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) + '@coinbase/wallet-sdk': 4.3.6(@types/react@19.1.10)(bufferutil@4.0.9)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@4.1.13) + '@gemini-wallet/core': 0.3.2(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) '@metamask/sdk': 0.33.1(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) - '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) + '@walletconnect/ethereum-provider': 2.21.1(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + porto: 0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.1.10)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.1.10)(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -22653,11 +22589,11 @@ snapshots: - react - use-sync-external-store - '@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))': + '@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))': dependencies: eventemitter3: 5.0.1 mipd: 0.0.7(typescript@5.9.2) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) zustand: 5.0.0(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) optionalDependencies: '@tanstack/query-core': 5.90.11 @@ -22764,6 +22700,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/core@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/window-getters': 1.0.1 + es-toolkit: 1.33.0 + events: 3.3.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/core@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/heartbeat': 1.2.2 @@ -22850,6 +22829,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/core@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.16(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/window-getters': 1.0.1 + es-toolkit: 1.33.0 + events: 3.3.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/environment@1.0.1': dependencies: tslib: 1.14.1 @@ -22982,10 +23004,10 @@ snapshots: '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) - '@walletconnect/utils': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -23014,18 +23036,18 @@ snapshots: - utf-8-validate - zod - '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': + '@walletconnect/ethereum-provider@2.21.1(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': dependencies: - '@reown/appkit': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@reown/appkit': 1.7.8(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) '@walletconnect/jsonrpc-provider': 1.0.14 '@walletconnect/jsonrpc-types': 1.0.4 '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) - '@walletconnect/sign-client': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) - '@walletconnect/universal-provider': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) - '@walletconnect/utils': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + '@walletconnect/universal-provider': 2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) events: 3.3.0 transitivePeerDependencies: - '@azure/app-configuration' @@ -23216,6 +23238,41 @@ snapshots: - utf-8-validate - zod + '@walletconnect/sign-client@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/core': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/sign-client@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/core': 2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) @@ -23286,6 +23343,41 @@ snapshots: - utf-8-validate - zod + '@walletconnect/sign-client@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/core': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/time@1.0.2': dependencies: tslib: 1.14.1 @@ -23424,6 +23516,45 @@ snapshots: - utf-8-validate - zod + '@walletconnect/universal-provider@2.21.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/sign-client': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + es-toolkit: 1.33.0 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/universal-provider@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@walletconnect/events': 1.0.1 @@ -23502,6 +23633,45 @@ snapshots: - utf-8-validate - zod + '@walletconnect/universal-provider@2.21.1(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/logger': 2.1.2 + '@walletconnect/sign-client': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/utils': 2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + es-toolkit: 1.33.0 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/utils@2.21.0(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 @@ -23588,6 +23758,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/utils@2.21.0(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@noble/ciphers': 1.2.1 + '@noble/curves': 1.8.1 + '@noble/hashes': 1.7.1 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.0(@upstash/redis@1.35.3) + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + bs58: 6.0.0 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 + viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + 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/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/utils@2.21.1(@upstash/redis@1.35.3)(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)': dependencies: '@noble/ciphers': 1.2.1 @@ -23674,6 +23887,49 @@ snapshots: - utf-8-validate - zod + '@walletconnect/utils@2.21.1(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)': + dependencies: + '@noble/ciphers': 1.2.1 + '@noble/curves': 1.8.1 + '@noble/hashes': 1.7.1 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1(@upstash/redis@1.35.3) + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.1.0 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.21.1(@upstash/redis@1.35.3) + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + bs58: 6.0.0 + detect-browser: 5.3.0 + query-string: 7.1.3 + uint8arrays: 3.1.0 + viem: 2.23.2(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) + 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/kv' + - aws4fetch + - bufferutil + - db0 + - ioredis + - typescript + - uploadthing + - utf-8-validate + - zod + '@walletconnect/window-getters@1.0.1': dependencies: tslib: 1.14.1 @@ -27254,6 +27510,21 @@ snapshots: dependencies: mimic-fn: 2.1.0 + openai@4.104.0(encoding@0.1.13)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): + dependencies: + '@types/node': 18.19.123 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0(encoding@0.1.13) + optionalDependencies: + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + zod: 3.25.76 + transitivePeerDependencies: + - encoding + openai@4.104.0(encoding@0.1.13)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): dependencies: '@types/node': 18.19.123 @@ -27804,21 +28075,21 @@ snapshots: - immer - use-sync-external-store - porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76)): + porto@0.2.35(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(@wagmi/core@2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)))(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13)): dependencies: - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) hono: 4.10.7 idb-keyval: 6.2.2 mipd: 0.0.7(typescript@5.9.2) ox: 0.9.17(typescript@5.9.2)(zod@4.1.13) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) zod: 4.1.13 zustand: 5.0.8(@types/react@19.2.1)(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) optionalDependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) react: 19.2.3 typescript: 5.9.2 - wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76) + wagmi: 2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13) transitivePeerDependencies: - '@types/react' - immer @@ -30029,14 +30300,14 @@ snapshots: - ws - zod - wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.76): + wagmi@2.19.5(@tanstack/query-core@5.90.11)(@tanstack/react-query@5.90.11(react@19.2.3))(@types/react@19.2.1)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.2)(utf-8-validate@5.0.10)(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13))(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@4.1.13): dependencies: '@tanstack/react-query': 5.90.11(react@19.2.3) - '@wagmi/connectors': 6.2.0(696284975690661567148e5458660a80) - '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76)) + '@wagmi/connectors': 6.2.0(1aee367860625464d156864b651beb8c) + '@wagmi/core': 2.22.1(@tanstack/query-core@5.90.11)(@types/react@19.2.1)(react@19.2.3)(typescript@5.9.2)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13)) react: 19.2.3 use-sync-external-store: 1.4.0(react@19.2.3) - viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@3.25.76) + viem: 2.40.3(bufferutil@4.0.9)(typescript@5.9.2)(utf-8-validate@5.0.10)(zod@4.1.13) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: diff --git a/typescript/.changeset/config.json b/typescript/.changeset/config.json index 893f241ab4..83c6b62309 100644 --- a/typescript/.changeset/config.json +++ b/typescript/.changeset/config.json @@ -3,9 +3,30 @@ "changelog": "@changesets/cli/changelog", "commit": false, "fixed": [], - "linked": [], + "linked": [ + [ + "@x402/core", + "@x402/extensions", + "@x402/evm", + "@x402/aptos", + "@x402/stellar", + "@x402/svm", + "@x402/express", + "@x402/hono", + "@x402/next", + "@x402/paywall", + "@x402/fetch", + "@x402/axios", + "@x402/mcp" + ] + ], "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["site"] -} + "ignore": [ + "site" + ], + "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { + "onlyUpdatePeerDependentsWhenOutOfRange": true + } +} \ No newline at end of file diff --git a/typescript/packages/http/express/package.json b/typescript/packages/http/express/package.json index 2ba9f8668f..a733f9e1b3 100644 --- a/typescript/packages/http/express/package.json +++ b/typescript/packages/http/express/package.json @@ -46,7 +46,7 @@ "zod": "^3.24.2" }, "peerDependencies": { - "@x402/paywall": "workspace:*", + "@x402/paywall": "workspace:^", "express": "^4.0.0 || ^5.0.0" }, "peerDependenciesMeta": { diff --git a/typescript/packages/http/hono/package.json b/typescript/packages/http/hono/package.json index a7f95fe114..95f49f7733 100644 --- a/typescript/packages/http/hono/package.json +++ b/typescript/packages/http/hono/package.json @@ -45,7 +45,7 @@ }, "peerDependencies": { "hono": "^4.0.0", - "@x402/paywall": "workspace:*" + "@x402/paywall": "workspace:^" }, "peerDependenciesMeta": { "@x402/paywall": { diff --git a/typescript/packages/http/next/package.json b/typescript/packages/http/next/package.json index 5adb87dc35..d9a14168bf 100644 --- a/typescript/packages/http/next/package.json +++ b/typescript/packages/http/next/package.json @@ -44,7 +44,7 @@ }, "peerDependencies": { "next": "^16.0.10", - "@x402/paywall": "workspace:*" + "@x402/paywall": "workspace:^" }, "peerDependenciesMeta": { "@x402/paywall": { diff --git a/typescript/pnpm-lock.yaml b/typescript/pnpm-lock.yaml index 5d0d1f0597..435d1faa82 100644 --- a/typescript/pnpm-lock.yaml +++ b/typescript/pnpm-lock.yaml @@ -222,7 +222,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall viem: specifier: ^2.39.3 @@ -350,7 +350,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall zod: specifier: ^3.24.2 @@ -414,7 +414,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall next: specifier: ^16.0.10 @@ -13455,7 +13455,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2) '@typescript-eslint/types': 8.42.0 - debug: 4.4.1 + debug: 4.4.3 typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -15527,7 +15527,7 @@ snapshots: eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.34.0(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.1 + debug: 4.4.3 eslint: 9.34.0(jiti@2.6.1) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 From 13ad532b03eae039d17c495edf6049d4c0295af3 Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:59:05 -0700 Subject: [PATCH 064/129] Add spec for ERC-7710 support to the exact_evm scheme (#732) --- specs/schemes/exact/scheme_exact_evm.md | 127 +++++++++++++++++++++++- 1 file changed, 122 insertions(+), 5 deletions(-) diff --git a/specs/schemes/exact/scheme_exact_evm.md b/specs/schemes/exact/scheme_exact_evm.md index 6f5e165384..6cb2dc7ef8 100644 --- a/specs/schemes/exact/scheme_exact_evm.md +++ b/specs/schemes/exact/scheme_exact_evm.md @@ -6,14 +6,15 @@ The `exact` scheme on EVM executes a transfer where the Facilitator (server) pay This is implemented via one of two asset transfer methods, depending on the token's capabilities: -| AssetTransferMethod | Use Case | Recommendation | -| :------------------ | :----------------------------------------------------------- | :--------------------------------------------- | -| **1. EIP-3009** | Tokens with native `transferWithAuthorization` (e.g., USDC). | **Recommended** (Simplest, truly gasless). | -| **2. Permit2** | Tokens without EIP-3009. Uses a Proxy + Permit2. | **Universal Fallback** (Works for any ERC-20). | +| AssetTransferMethod | Use Case | Recommendation | Usage Semantics | +| :------------------ | :----------------------------------------------------------- | :--------------------------------------------- | :---------------------------------- | +| **1. EIP-3009** | Tokens with native `transferWithAuthorization` (e.g., USDC). | **Recommended** (Simplest, truly gasless). | One-time use | +| **2. Permit2** | Tokens without EIP-3009. Uses a Proxy + Permit2. | **Universal Fallback** (Works for any ERC-20). | One-time use | +| **3. ERC-7710** | Smart accounts with delegation support. | **Smart Account Option** (Paid from ERC-7710 compatible account). | One-time use and multi-use | If no `assetTransferMethod` is specified in the payload, the implementation should prioritize `eip3009` (if compatible) and then `permit2`. -In both cases, the Facilitator cannot modify the amount or destination. They serve only as the transaction broadcaster. +In all cases, the Facilitator cannot modify the amount or destination. They serve only as the transaction broadcaster. --- @@ -201,6 +202,114 @@ Settlement is performed by calling the `x402ExactPermit2Proxy`. --- +## 3. AssetTransferMethod: `ERC-7710` + +This asset transfer method uses [ERC-7710](https://eips.ethereum.org/EIPS/eip-7710) smart contract delegation to authorize transfers from accounts that support the standard. It is particularly suited for smart contract accounts (e.g., ERC-4337 accounts, ERC-7579 modular accounts) that have enabled delegation capabilities. + +### Prerequisites + +For ERC-7710 to work, the following must be true: + +1. **Delegator Account**: The payer's account must be a smart contract that supports ERC-7710 delegation (e.g., a modular smart account with delegation capabilities). +2. **Delegation Manager**: A `DelegationManager` contract implementing the `ERC7710Manager` interface must be deployed on the network. +3. **Active Delegation**: The payer must have created a delegation authorizing the delegate to execute token transfers on their behalf, with appropriate caveats (amount limits, recipient restrictions, etc.). + +### Phase 1: Obtaining a Delegation + +The process of obtaining a delegation is outside the scope of x402. Delegations may be obtained through: + +- [ERC-7715](https://eips.ethereum.org/EIPS/eip-7715) permission requests +- Direct wallet interactions +- Pre-configured session keys +- Other delegation protocols + +The key requirement is that the client is able to issue a delegation to the facilitator that permits the required token transfer. + +### Phase 2: `PAYMENT-SIGNATURE` Header Payload + +The `payload` field must contain: + +- `delegationManager`: The address of the ERC-7710 Delegation Manager contract. +- `permissionContext`: The delegation proof/context required by the specific Delegation Manager implementation. +- `delegator`: The address of the account that created the delegation. + +**Example PaymentPayload:** + +```json +{ + "x402Version": 2, + "resource": { + "url": "https://api.example.com/premium-data", + "description": "Access to premium market data", + "mimeType": "application/json" + }, + "accepted": { + "scheme": "exact", + "network": "eip155:84532", + "amount": "10000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "payTo": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", + "maxTimeoutSeconds": 60, + "extra": { + "assetTransferMethod": "erc7710", + "name": "USDC", + "version": "2" + } + }, + "payload": { + "delegationManager": "0xDelegationManagerAddress", + "permissionContext": "0x...", + "delegator": "0x857b06519E91e3A54538791bDbb0E22373e36b66" + } +} +``` + +**Note:** The structure of `permissionContext` is determined by the specific Delegation Manager implementation. Common implementations (e.g., MetaMask Delegation Framework) use EIP-712 signed delegation chains. + +### Phase 3: Verification Logic + +Unlike EIP-3009 and Permit2, ERC-7710 verification is performed entirely through simulation. The `permissionContext` is opaque to the facilitator but verifiable by simulating the intended action. + +The facilitator: + +1. **Constructs** the `executionCallData` encoding an ERC-20 `transfer(payTo, amount)` call for the required payment. + +2. **Constructs** the `mode` appropriate for the execution (typically `0x00...` for single call mode per ERC-7579). + +3. **Simulates** `delegationManager.redeemDelegations([permissionContext], [mode], [executionCallData])` to verify: + - The delegation is valid and authorizes the intended transfer. + - The delegator has sufficient balance of the asset. + - The transaction will succeed when executed. + +If the simulation succeeds, the payment is considered valid. The simulation serves as the sole verification mechanismβ€”no trusted list of Delegation Manager implementations is required. + +**Security Considerations**: + +1. **Race Condition Risk**: A facilitator may be vulnerable to a race condition where the client invalidates their delegation between simulation and transaction execution, causing the facilitator to pay gas for a failed transaction. This risk can be mitigated by: + - Submitting transactions via a private mempool to reduce the window for front-running. + - Building trust signals for client accounts (e.g., reputation systems) that can be used to flag or ban abusive behavior. + +2. **Malicious Delegation Manager Gas Consumption**: A malicious or poorly implemented Delegation Manager could attempt to consume excessive gas during execution. To mitigate this risk: + - Facilitators should always set an explicit gas limit on their `redeemDelegations` call, as is standard practice for all Ethereum transactions. + - Pre-execution simulation helps identify whether a transaction is likely to use a reasonable amount of gas. + - If simulation reveals unexpectedly high gas consumption, this may indicate a "trap door" implementation designed to drain facilitator funds, and the transaction should be rejected. + +### Phase 4: Settlement Logic + +Settlement is performed by calling `redeemDelegations` on the Delegation Manager: + +```solidity +delegationManager.redeemDelegations( + [permissionContext], // bytes[] - delegation proof + [mode], // bytes32[] - execution mode + [executionCallData] // bytes[] - encoded transfer call +); +``` + +The Delegation Manager validates the delegation authority and calls the delegator account to execute the token transfer. The delegator account then performs `token.transfer(payTo, amount)`. + +--- + ## Implementer Notes - **Permit2 Dependency:** Both the Permit2 contract and the x402ExactPermit2Proxy are audited, battle-tested contracts. However, integrators inherit their security properties and any future vulnerabilities discovered in either dependency. @@ -209,6 +318,14 @@ Settlement is performed by calling the `x402ExactPermit2Proxy`. ## Annex +### ERC-7710 Delegation Managers + +ERC-7710 does not define a canonical Delegation Manager. Implementations may vary in their delegation structure, caveat enforcement, and permission context format. Notable implementations include: + +- **MetaMask Delegation Framework**: A full-featured implementation supporting EIP-712 signed delegation chains, caveat enforcement, and batch processing. See [gator.metamask.io](https://gator.metamask.io/) for documentation. + +Since verification is performed entirely through simulation, facilitators do not need to maintain a trusted list of Delegation Manager implementations. + ### Canonical Permit2 The Canonical Permit2 contract address can be found at [https://docs.uniswap.org/contracts/v4/deployments](https://docs.uniswap.org/contracts/v4/deployments). From 21d38d67771e2fa35dae2dadb26c4da0cf5b808d Mon Sep 17 00:00:00 2001 From: Alfred Tom <79275786+alftom@users.noreply.github.com> Date: Sat, 14 Mar 2026 21:14:17 -0700 Subject: [PATCH 065/129] feat(ecosystem): add OMATrust reputation layer entry to follow up on the offer-receipt extension (#1616) --- .../omatrust-offer-receipt/metadata.json | 7 +++++++ typescript/site/public/logos/oma3-icon.png | Bin 0 -> 9753 bytes 2 files changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/omatrust-offer-receipt/metadata.json create mode 100644 typescript/site/public/logos/oma3-icon.png diff --git a/typescript/site/app/ecosystem/partners-data/omatrust-offer-receipt/metadata.json b/typescript/site/app/ecosystem/partners-data/omatrust-offer-receipt/metadata.json new file mode 100644 index 0000000000..53a5112e34 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/omatrust-offer-receipt/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "OMATrust: x402 Reputation", + "logoUrl": "/logos/oma3-icon.png", + "description": "Decentralized reputation for x402 resource servers. Use x402 signed offers and receipts as cryptographic proof-of-interaction in on-chain EAS attestations.", + "websiteUrl": "https://docs.omatrust.org/integrations/x402/overview", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/public/logos/oma3-icon.png b/typescript/site/public/logos/oma3-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a9d87b57b490a57b5de7adcb28f83d31176b7e1f GIT binary patch literal 9753 zcmcgyhgTEb)80)2p?B%hMFgaGkOTxlrGr#~0Meui0xBgTR28Hv9V{q_0-{uf(4+~1 zBE1EWUJ|62Bp>hZkND2nJ$LUpGqZE&+&i;7&-2*K#DI~Gmks~`#_NW9761UAJ%RuY z_1SPcsMOj1!~6#7#aDgd}p zaa~Wx>H)Y};F!ce8nQg_F@;RdU7brfbg`(8w=mQ<@olNyt$Ju@_|Q2H3@u{&5%4rl z|H_sOKkkvs-RQ{PUKLIdA}z-A(?MDr7KqJOVbe^#W5H(d$~cWfKj@L#71FfhE!BhF zs>Qkb@MG)Yk86#?%kU)i!c`uN=}7WHK1Kb&3BU@`{J&iLEg0Lo3dzaA`8zhzpO^mn zOv!aD&oCY2b1Hr??RXK&ur2?g(is%FWs8(n7C`EsZi~o~zsd%Mox!sqTTwFH97f#=IP5*E+FRgT@ z7TGqVMwUkJWQf?PU8;`flJ{X5Z&S0xPeo2D=NBPK%mI)zH3_I~P^LSu!@>i>Y_ppi zeKQ`{2@(QrgIw7$O#TYd7r&9c2%f~6e` z0~?0>;aD*GoW#noLZNi5jaSDQLJTmE2_d~bFy0oA`Z;HOhyD1u4nR()@U*Dwgt94emMJp?m`+KfZ$w^by=@4z{jPuXbABWY>4GPz(ii8;={QNz&r3gX+Hs7b>iZTVIx? z0*5;0jYZQxZA{B8_F8t`3rzxogZ+EL? zV6L=G01Sbpp$CLFR1JbO2I_;I{0ygUo3|?-NEO{&zbku_Kt!z=&=4ESDb@DVKG@J_ zd(;I(P5xsauzDyiHVl-;a@`U?aLt;gSC#H4{cwyD(npZdumdRz{Bqt<$MWIVck|L zS@JTgPGbM+Zg#%3r|k^9HIB);-z2tmTPzZdA~Yuw<*F`U1a?#&;gNVdny; zxMN>`!`pqe0l(%c6A;%?KvfHWrZ#zuZ(GdC@w*XExjV(O8V`VEID{ zn#Y_mW=lc>ilJVl$tsxiI{+4VEWc>rCdrf_7}H$kuE21ZWV7e{Mg#kie+jS{rG#x(n|Z#!KK7OedRPmh#9Lb;Fx%lfeeZOVa zG(8s3FW%1Dd`n2yyHv<=n+_xnEgQVUotl5*)+f@t4V2D&c_BhP7*gLL?$3Rv2mOux zBg$4~OH8*TkZYbJUF=cXSoB`O4gC<}q+`rSzdQXC0g5+yP7SvUzmHV78*}K`3aQoK zVucXa6ZFQt{MyP>buCE#yP7lMD=%u^ueEFR7L8v!vV5un-xQ{GZ~e(W?Z2#7cP4FN zOZUbG2u&e0ik$=wD}=JT65YHL2QvI%S{LB0 zo)PvuZIEk?AQhf^#OFb&<4#mE{g=OOJfn>Z=P7B!%pi9#FurYO--fef-1vp7COlwbfjoDbgC} zIzMBim%osLh*YWLz>X-zdcQ3Ze1cqf{BoUR9`~%TPB8V=IL3;$rG33&CjH@u>FWL( zbh)(-XiKPc8t7m|?7kS2rFdputrqp<--fvMr`^+uA@cFe(H+&e=*Ur+GcVvAB&%AmrfpoxwYVY9b z%*3#3G26?KzHNI0gHKNYf8l1z*I0X3G&>V0tAz~@Yd6;$+GOZ{njw=o0+xfa&)=Z5 zZ21k^zeZEzMfZxP6rjS76%Kz*`3UaY1`O|zPOg0Fo*_*vsqq<#WV34Ry>724@)g=L zYB?yaTC&6J^I#SiWx7X5XH{ZwvsofW(1!H!BEO;`Q8a#qJY10_T!y+voN=C#4dEZT&_;cHZA|kmDm2 zD*yNi>@s;?w*9X7*$7qMNg$46P%j--SU(@pI z=HG6m7BbY-;@t;1{HRdAr{6P=7h;_`u4*r2Ql36rmCz0nlTyI^yV#=u^Srl?@a0pu z5dDA=aE7)gFJE>bixqWEzf?#${{qbQ04L}GsO8-WQ~fpPCik`&q8KGwC`I^MVyCF+*)~Qp1BIMz7;Xh`Z*skl`1c{%I6O2ip z&SeGI-gu3>e0;q5+Ud=}6<+LhA9?}30Ke`E^0H=dWOPJ(2YZ(5!&z4cGZlJ#KIM{E z;&X`5*W=3DmlLWxJ}p@_y%3DSg?B$)d}tsGEJN>ukzhVg_C?5HZpR!P#hJ=ZPW#(l z^g~JIO-lYvx(Qm$##&0J^H}?pswG%l2hSsNa*=lbpmBokC!yfW_bv<~%sw0G#)Pd|?9+ zH1FX5u$X>~lPl%kyhT+@B{h1L5MxiHCjBKiNX{}_s)$r^JI~0s!tqD;3VU&ijd)TaO-?I4%cP4S5gl-n>CHm6(;D zziwD8s!Dcqdn<^EF7(M=*lbUj9msu9{%?lBMaX^G1o5Tq&5bsB=3`0iB@8T_N3)$B z*es@DSCv66`CYwhc%~o!Jcs8J2_nY07~AVa|JE3!B~b{0+FR)B%gFvEWtK+uSH-U^ z2PlZg?sfx7N970;k~?4MogaDXsRz{dUFqfrrdPXa@vvPelOz?Bu0Cff?nTC<`3{6x zUUYE>J?6tvf+B^5HB0kfIGCP&On^^fHF&YzIwdVSXM1K=L6>Ck<2k5N1I?hw5RJ+n zNe+E^!+ehzGp(Av;RM_#W#k?cEOe1D!clo(g+FyXLE=Xj#uccFoo%BzP zmCC8$3N5_Jo1S~GlkRJzB!pqbGqo?>&7+z+d0i_Up55(4%&o10KfP0Xxj`XgXITfz zMq-j{%~G)ZSLB}MxL(7hMZT%BXRyFLum(3aJl=MJN898_9`AV+ANXH-!y}=|AvQzn zsRK=Kf*HQ0G<-A?TXH_KJX*lrw*+t!#+}{S`zyVDErl)JwV2w>hi)Zj`;PSrl((F#G@%Kb6$I zTY4}mJaC>85c3Sh$?`_jjOJkr{c}(u#SK-6iOu+{y45y? zMwBBoC>q1$aJ!=}O*dAx6T}v_CL^CO?(|Fp6=GMa01V`$PVoP|fMZX+4WH7N>osQ8#(NMm z-)_^VFOOdAmf^guC?V|DQODz=&h66pamxOsmF|MdBUR|mxNFk<`$sV7`)5e3z_jm%oEuS={dQ%0!?JryQMhGlE zc%=zWcmUP|X3Yx~4+fqyd7U4keA+&EJshTke!U$wxQ3YP3nTc9a!y5kTR&;a_v3l#boJ&d zc2qs`0!C1}s)S?6Kko)rOTaOr^npDsKuwNX2;lUhDLmS`GDtghVI@q7J0LusMK0$G zNK1f;eS)R-0t{VdyqKtW?fD;^cv{@hpXb)MHEOBCOm-ui#9auHsXc&RY#MMFebdC$ z?!09gJas#bY2JKR>ysz>RNL$H7G+QSP`|DgMW}*C(FW5g1ux|#_Pu0l;Y#X9kl>m? zF^iV&#K6Lp{-4A7o~Qk~XQE;KlysRsEt(q~d4u!Uez3Keopzjjq$Ke2V7N~eI%lPu zcb)foAb|ovgln=8(Z{=947lsvZES4kSHp)nZEW>7VTJ~d9)5+obkFj)9#j4~YfD4& z;Y3XqrA>}GcM)?4s)rZzBx`iPLB34c>Gq|0r4B5X z<^y`{-2}x5dxZUAca7B-SRqHoQBQ;MV(6kz*V z_LP9VAxA&h%EGajQ`yB=QTSE;R+~o&WH-W4}Kj>=JG5kM=Cb0(OW~%Gd$t{Ou8JhvO%>7hpkcg~+nW<5Ey_1I0Oz!7( zHBiVowOt99Auf=aSlDZK>f&mcA$xer(Gxmf`n5+9V@g^XmqYqldP3~Y6-${7HZV^7 zg(I#tm&-gHS=i;uHV{ivl7lSYNXyDAQ91+Vod<0n@!PV!$qi*Jsu=~K*Cn9;q9%Oe z*COBdh%&$Hj_3TDey151ufBVK77kzf`M^O<$}+dKqOR5w9S}UNmnYt1PZrw;4N18) zo?jScb1uDJtDV&%%7Eunm?u;6Xtz8cJioZ@B$t_%r;2;E zT$$`ijlOiA7F;=xPHzOf+YQaQe1pCYyc#^R7Vfz8AesZ&32;bFoHJAt13mySp;Na>+a{LD;@y4X(?h8fF7GN&EM#+ z?Hpcgb$_#_KXa=(qT7+yDffKgGHa;8Eawy_KgMn$mN#JFov^N-uI8Xw*=lhnALfLLX)CO%7lv*zzafN0wKc}8J? zk``8->U}Zn(NSNDP3u}GrM3+$K8-wLLvhF*b|D=8EfpauqQOM5K3LzSRY)Rd@_nlv z%-7cHg2QCwZIX?)$^Jg01B{X*I4bPlTSqE@{Vs2ecE-8*Dd84h{-<~oSXeH}ys8x@jMW8KHA;?hP-oS%_iuMAK*7h(6 zzaRuZ*2?wINV8c1wdlt8UUhH$+tJ3lfsl!H1=nAF1c9m$Yz2!O2(q32x+G@ySrEx4 z0T?|F>J=E}@Zf$!6l#8n7bUEHIyNmurwXDwbT%Iqp6~!`6;y~`AKMVI-{^XV+|+O7 ztsFTQO|Jih6OFzZLD(Fr#ikGQzQ1rn(A_g5Nf6fe))Pu8;ReSs4a^Etbvo?nVd@g4 z>N@&wynnw`mpH;%1?fipNK&FlE(B~sub9sC1lU)R7rZ93R>+l2&Pf+YT}SCU#;?fE z$~9h~$YXY3dqeViQI(ApX^h1kS#i!!6|kXHjoQklcgcR#o8a7CC)Y7+MpJ!t7VIwy zY9k{YMqS^Wzg`G0E@hXKZ20}-xR`s2wX+QQl`olQWpF>w;E!Lc8=~@WHQ{oF8+0`574SluAt)6b$L(t3xHedSIGV=g@RD^*Zf$y@Hi)A*{_l>U%sw z>e_YA*q@EnqiZotd%|=_yjDO#ddIB1zE`@1Uw(5UYNv$(-(C5nm=0HtcuV$A>_-$V zG&O`HLvB*i?mP$fKHFqtql?Ym#Wtb4<#WA2mR-xlu+e*K3hgp^ze?fiAYly`taNzx zz5cKCJ`ohE&zk;-AW?f=b4`Km2%Y-BpL-HPjoATSvrGee`kZnzn+N{XziDcz1kswO z0!u>Wlq&vj9qakryGvK%gZJ47Q#GD}XK562~HBmIYVO^Yj&+vM&`eC7_K&8{R<(jb$&3tkS?kN$7+@ zn>(n+dz*Prhm>e zH+3`n`7f9>m35R)gThy;p^5#xgpF;N6w<4;qj5rtmYOnMjp^se_oFvY)>6Cz6 zFgG6jJ3h>1(Q|gdjIizT2Hpa>JRRktb2ZS(f#u*>@Z{n5uryZk#UVt| z$6Nqw&5a4Es75gHi8Rm?z~{7$Il_FYBQ4!qBCIJ+Vr>tKqQZwq*NesX2qEs)X!!BO zf9os)|8zM>T@44P7n+&{70qsOVu}UjjA4U^H^V1QQh)_m{`aDnS zmlo*pW=j43sP7h<_t9;p-m!I-^ldY<{=F+ zX2LN7YL!dOS*g@wM zONW{yWqNQm{w@!niP?L(?$Pj{^1y&&swE{V?f3^b8udh4iK=tfX_pm3g%tlDbqnPa-OWdV3rFYa^7d<~a1 zi47E}qdq+7QlNA2SbG%9{Z04pR58?AG6v@y7SH_CudY=#ze!$3-!h$X9^ex|A&i^L&DFi=msQQH4#6pn3EReT-S4A* z?!kHM4g>mvLVSS9iBpuK=V-LSlIE}odpZRbGhEbm#T2K&p4Dx1iihI)<4sqT&mbDhs} zLn^j&h2J*>9LCnw>^9-b1C}-6Y?kExPpmfP1TEVn0Bm96RWBZM->LhaaHzP3ZZH13&01LF{4dil=UU(}T5gL?qOdVZ z;qa4Gpcm=fU}nkWv(QxG>@(=;3_X!#Vd01#UeAfsJP3UuAMAyhc8woa1Q2!cWM`k- z)AAp?)Fa>F?_C`Do&a|lI`P(;>VJ2C*g(YTDB#%vwbvBe?PgMG8_SobjS{;OnzYDx<`fM8-@U zRFG2ni1S|vc5QImlUpBq^8>-#&2D_|zZ#+Q!LOJiwDuX7PwwI1dir!06xttObvJ*q z-e!A?@9~~xT8A68FzIYQ_mghpH)1n~Yh$l!bD#E}oSys|+nXJ*z)3OlvR}JVN7wLg zPZ!j!{%`?2rrB)w7h9T%%1>YD-P)k1a+}TI)gFp1sWe|c0{{E*SiLqw(GMMpdLco3 z_$3H(+3Cn=FbXAFmq_&Jn#;HL6iSW(d)X#&1z zL3Xn45su1cES5F%vMqbKWkB^4et~PA;Sp?|G{W_$=_f5Zp@~{VKZN3B2&Ae<0k14z zEW6Z_BBFzS8O#+#sQG~At6OT)_ZS`|YBUvH^Swm*OK|&1Z-yveJcoztK;%GG2A!>b zI}uCNk5PYrNAsF0PBT>ZA^ngsz12cHcq^s-ok}wG?K|t z#K0W$NXH(=Ti4HEVCJ08PW7$rIuAx#{ReXB%hEw7bJX~tst0k%-jxZo)!~e?oR=h^jMH+^gz%|b=MZ0-$+7rp*NVbi~eYv# zSViO*IjA|X(|)-5S=HldZiU)IjfDJ;8RIccEpC6r^gr~SFm9sN>aD|01uBFtMCfsn zd}7BU{hNaS03=r_=<^O@9<|@Ctd8$GES=<_8OHA`^mwQHss?qGc%4MA6=PcqRC&Pl z7{QkeEwaJl)E80L&Dh3~WPfpbJ)zox+KHx`)>DV@nDl?bf;@(2jE+kX!@1A5Yj>|} z7jXn2FHUW=^F{pO!)l5g;FG`(BYujoH-@s82ELtD+GDx7bG?NPCZg>0Jrx~-nr5$cZPQ}zsU)^x{v9v1)qs7ogWWs2&sNn41IZ(M_yK!gX zIA_cDfLM?-`rI@+7H=-XLplHM^mV|Sd$Kq>Lx96gMO$s4<(p6*qmTsb=xc-TTkp$@ zUZHn_DP!~Ht@<~PJg-7nsLo6@&_`8+9sZLZ+o9TZ3?9PIPWPWNP?L@WOSOm>Dv~aS z3WJHMLgN6|!^LB=)|}zPv$9iSnm)EX678q7BDl#YIyV1wvuU*8)}i*t=v^bEer<`(?G)1}vC7|MDZ#pj_zrPLzqH_%8vMXAX3ca~?X&AatePB$3IQP%p>Ec2v0oAaZ zA*#y_^`FxwMGlPv?ipa8S~>MZcWul9j z788#@=TWh&HNdb=mE{;~JN9w)UL4LyiZp-rDlq$e;K0L9V0}G5nd&8^2k<#^hH~5J z1SPX{A+EbM(4J+I z9G3I(eVqBbu`G!~S1vV@Zkb=p{7&cSQfM>1)BV^?tJ*##W-{0wRV5Dn>8ikqF4bw`#GbR^sUEf5nLKlVoKN~1 Date: Sun, 15 Mar 2026 04:16:18 +0000 Subject: [PATCH 066/129] Add x402-proxy to ecosystem (#1602) --- .../app/ecosystem/partners-data/x402-proxy/metadata.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/x402-proxy/metadata.json diff --git a/typescript/site/app/ecosystem/partners-data/x402-proxy/metadata.json b/typescript/site/app/ecosystem/partners-data/x402-proxy/metadata.json new file mode 100644 index 0000000000..117b33f46c --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/x402-proxy/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "x402-proxy", + "description": "curl for x402 paid APIs. CLI and library that auto-pays HTTP 402 responses with USDC on Base and Solana, with MCP stdio proxy for AI agents. npx x402-proxy.", + "logoUrl": "/logos/cascade.png", + "websiteUrl": "https://github.com/cascade-protocol/x402-proxy", + "category": "Client-Side Integrations" +} From f6af4f0e2886c6e57717c0058dfbffe9f81e0024 Mon Sep 17 00:00:00 2001 From: Akash Prasad Date: Sun, 15 Mar 2026 09:47:29 +0530 Subject: [PATCH 067/129] add elsa facilitator (#1591) --- .../app/ecosystem/partners-data/elsa-x402/metadata.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/typescript/site/app/ecosystem/partners-data/elsa-x402/metadata.json b/typescript/site/app/ecosystem/partners-data/elsa-x402/metadata.json index 9075296981..604b79cf88 100644 --- a/typescript/site/app/ecosystem/partners-data/elsa-x402/metadata.json +++ b/typescript/site/app/ecosystem/partners-data/elsa-x402/metadata.json @@ -3,5 +3,12 @@ "description": "DeFi API endpoints with x402 micropayments. Access portfolio data, token prices, swap quotes, wallet analytics, yield suggestions, and more - pay per request with USDC on Base.", "logoUrl": "/logos/elsa-x402.png", "websiteUrl": "https://x402.heyelsa.ai", - "category": "Services/Endpoints" + "category": "Facilitators", + "facilitator": { + "baseUrl": "https://facilitator.heyelsa.build/", + "networks": ["base", "base-sepolia"], + "schemes": ["exact"], + "assets": ["EIP-3009"], + "supports": { "verify": true, "settle": true, "supported": true, "list": false } + } } From c92c0d12e01b542047e09a4166fe6f95cdf96284 Mon Sep 17 00:00:00 2001 From: Marcelo Salloum dos Santos Date: Sun, 15 Mar 2026 18:18:21 -0700 Subject: [PATCH 068/129] stellar: Bump `@stellar/stellar-sdk` dependency and improve API call for better performance (#1598) * chore: bump @stellar/stellar-sdk and remove the now unneeded fix * Update getEstimatedLedgerCloseTimeSeconds to receive the rpc latest ledger, thus reducing by one the rpc calls needed * Update getEstimatedLedgerCloseTimeSeconds to use horizon, which is way more efficient than rpc for this particular request * Add changeset --- e2e/pnpm-lock.yaml | 907 ++---------------- examples/typescript/pnpm-lock.yaml | 33 +- typescript/.changeset/ten-knives-trade.md | 5 + .../packages/mechanisms/stellar/package.json | 2 +- .../mechanisms/stellar/src/constants.ts | 6 + .../stellar/src/exact/client/scheme.ts | 21 +- .../stellar/src/exact/facilitator/scheme.ts | 2 +- .../packages/mechanisms/stellar/src/utils.ts | 52 +- .../stellar/test/unit/utils.test.ts | 83 +- typescript/pnpm-lock.yaml | 20 +- 10 files changed, 206 insertions(+), 925 deletions(-) create mode 100644 typescript/.changeset/ten-knives-trade.md diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index 4c13181b6b..e3dadfcb2f 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -235,7 +235,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall viem: specifier: ^2.39.3 @@ -363,7 +363,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall zod: specifier: ^3.24.2 @@ -427,7 +427,7 @@ importers: specifier: workspace:~ version: link:../../extensions '@x402/paywall': - specifier: workspace:* + specifier: workspace:^ version: link:../paywall next: specifier: ^16.0.10 @@ -792,10 +792,10 @@ importers: 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.19.0(bufferutil@4.0.9)(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@7.5.10(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10)) express: specifier: ^4.18.2 version: 4.21.2 @@ -1233,8 +1233,8 @@ importers: ../typescript/packages/mechanisms/stellar: dependencies: '@stellar/stellar-sdk': - specifier: ^14.4.2 - version: 14.5.0 + specifier: ^14.6.1 + version: 14.6.1 '@x402/core': specifier: workspace:* version: link:../../core @@ -1541,145 +1541,6 @@ importers: 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@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(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/external-proxies/cdp-local: - dependencies: - '@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/external-proxies/x402.org: - dependencies: - '@coinbase/x402': - specifier: ^0.7.3 - version: 0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(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/typescript: dependencies: '@aptos-labs/ts-sdk': @@ -2898,9 +2759,6 @@ packages: '@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==} engines: {node: '>=18'} @@ -5297,12 +5155,12 @@ packages: '@stellar/js-xdr@3.1.2': resolution: {integrity: sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==} - '@stellar/stellar-base@14.0.4': - resolution: {integrity: sha512-UbNW6zbdOBXJwLAV2mMak0bIC9nw3IZVlQXkv2w2dk1jgCbJjy3oRVC943zeGE5JAm0Z9PHxrIjmkpGhayY7kw==} + '@stellar/stellar-base@14.1.0': + resolution: {integrity: sha512-A8kFli6QGy22SRF45IjgPAJfUNGjnI+R7g4DF5NZYVsD1kGf7B4ITyc4OPclLV9tqNI4/lXxafGEw0JEUbHixw==} engines: {node: '>=20.0.0'} - '@stellar/stellar-sdk@14.5.0': - resolution: {integrity: sha512-Uzjq+An/hUA+Q5ERAYPtT0+MMiwWnYYWMwozmZMjxjdL2MmSjucBDF8Q04db6K/ekU4B5cHuOfsdlrfaxQYblw==} + '@stellar/stellar-sdk@14.6.1': + resolution: {integrity: sha512-A1rQWDLdUasXkMXnYSuhgep+3ZZzyuXJKdt5/KAIc0gkmSp906HTvUpbT4pu+bVr41tu0+J4Ugz9J4BQAGGytg==} engines: {node: '>=20.0.0'} hasBin: true @@ -9579,9 +9437,6 @@ 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'} @@ -10505,26 +10360,6 @@ snapshots: - utf-8-validate - zod - '@base-org/account@1.1.1(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - zustand: 5.0.3(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) - 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-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))) @@ -10571,29 +10406,6 @@ snapshots: - 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.13.4 - axios-retry: 4.5.0(axios@1.13.4) - jose: 6.1.3 - md5: 2.3.0 - uncrypto: 0.1.3 - viem: 2.45.1(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.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.1.12(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) @@ -10695,67 +10507,6 @@ snapshots: - utf-8-validate - zod - '@coinbase/wallet-sdk@4.3.6(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - zustand: 5.0.3(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) - transitivePeerDependencies: - - '@types/react' - - bufferutil - - immer - - react - - typescript - - use-sync-external-store - - utf-8-validate - - zod - - '@coinbase/x402@0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - x402: 0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(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' - - '@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: esbuild: 0.25.5 @@ -11707,13 +11458,14 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-controllers@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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)': 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-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.3) - viem: 2.45.1(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: - '@azure/app-configuration' - '@azure/cosmos' @@ -11742,14 +11494,14 @@ snapshots: - utf-8-validate - zod - '@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-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: '@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-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.0) + valtio: 1.13.2(@types/react@19.2.2)(react@19.2.1) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -11778,83 +11530,11 @@ snapshots: - utf-8-validate - zod - '@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: - '@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 - - ioredis - - react - - typescript - - uploadthing - - utf-8-validate - - zod - - '@reown/appkit-pay@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(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.3)(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.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(zod@3.25.71) - lit: 3.3.0 - valtio: 1.13.2(react@19.2.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-polyfills@1.7.8': - dependencies: - buffer: 6.0.3 - - '@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-polyfills@1.7.8': + dependencies: + buffer: 6.0.3 + + '@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: '@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) @@ -11928,43 +11608,6 @@ snapshots: - valtio - zod - '@reown/appkit-scaffold-ui@1.7.8(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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.3)(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.3)(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.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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-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: '@reown/appkit-common': 1.7.8(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) @@ -12035,41 +11678,6 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-ui@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(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-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) @@ -12146,44 +11754,6 @@ snapshots: - utf-8-validate - zod - '@reown/appkit-utils@1.7.8(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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.3)(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(react@19.2.3) - viem: 2.45.1(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-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) @@ -12281,49 +11851,6 @@ snapshots: - utf-8-validate - zod - '@reown/appkit@1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(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.3)(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(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(zod@3.25.71) - '@reown/appkit-ui': 1.7.8(bufferutil@4.0.9)(react@19.2.3)(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.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(valtio@1.13.2(react@19.2.3))(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(react@19.2.3) - viem: 2.45.1(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 - '@rollup/rollup-android-arm-eabi@4.52.5': optional: true @@ -12465,10 +11992,6 @@ snapshots: dependencies: '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana-program/compute-budget@0.11.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))': - dependencies: - '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana-program/compute-budget@0.8.0(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) @@ -12481,10 +12004,6 @@ snapshots: dependencies: '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) @@ -12500,11 +12019,6 @@ snapshots: '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana-program/token-2022@0.6.1(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(typescript@5.8.3))': - dependencies: - '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana/sysvars': 6.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana-program/token@0.5.1(@solana/kit@6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@solana/kit': 6.1.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) @@ -12517,10 +12031,6 @@ snapshots: dependencies: '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.19.0(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.19.0(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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -12529,10 +12039,6 @@ snapshots: dependencies: '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana-program/token@0.9.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))': - dependencies: - '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@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) @@ -13105,27 +12611,27 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@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@5.0.0(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(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) + '@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) + '@solana/codecs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 5.0.0(typescript@5.8.3) + '@solana/functional': 5.0.0(typescript@5.8.3) + '@solana/instruction-plans': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/instructions': 5.0.0(typescript@5.8.3) + '@solana/keys': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 5.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@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@7.5.10(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@7.5.10(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 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -13646,23 +13152,23 @@ snapshots: 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))': + '@solana/rpc-subscriptions-channel-websocket@3.0.3(typescript@5.8.3)(ws@8.19.0(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) + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-channel-websocket@3.0.3(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions-channel-websocket@5.0.0(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) + '@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.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 7.5.10(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@solana/rpc-subscriptions-channel-websocket@5.0.0(typescript@5.8.3)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: @@ -13793,19 +13299,19 @@ snapshots: - 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))': + '@solana/rpc-subscriptions@5.0.0(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@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) + '@solana/errors': 5.0.0(typescript@5.8.3) + '@solana/fast-stable-stringify': 5.0.0(typescript@5.8.3) + '@solana/functional': 5.0.0(typescript@5.8.3) + '@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@7.5.10(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) + '@solana/subscribable': 5.0.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -14279,18 +13785,18 @@ snapshots: - 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))': + '@solana/transaction-confirmation@5.0.0(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(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) + '@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) + '@solana/errors': 5.0.0(typescript@5.8.3) + '@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@7.5.10(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) typescript: 5.8.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -14567,7 +14073,7 @@ snapshots: '@stellar/js-xdr@3.1.2': {} - '@stellar/stellar-base@14.0.4': + '@stellar/stellar-base@14.1.0': dependencies: '@noble/curves': 1.9.7 '@stellar/js-xdr': 3.1.2 @@ -14576,12 +14082,12 @@ snapshots: buffer: 6.0.3 sha.js: 2.4.12 - '@stellar/stellar-sdk@14.5.0': + '@stellar/stellar-sdk@14.6.1': dependencies: - '@stellar/stellar-base': 14.0.4 + '@stellar/stellar-base': 14.1.0 axios: 1.13.4 bignumber.js: 9.3.1 - commander: 14.0.2 + commander: 14.0.3 eventsource: 2.0.2 feaxios: 0.0.23 randombytes: 2.1.0 @@ -14707,11 +14213,6 @@ snapshots: '@tanstack/query-core': 5.90.8 react: 19.2.1 - '@tanstack/react-query@5.90.8(react@19.2.3)': - dependencies: - '@tanstack/query-core': 5.90.8 - react: 19.2.3 - '@trysound/sax@0.2.0': {} '@tybys/wasm-util@0.10.1': @@ -15372,53 +14873,6 @@ snapshots: - wagmi - zod - '@wagmi/connectors@6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.71) - '@coinbase/wallet-sdk': 4.3.6(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(zod@3.25.71) - '@gemini-wallet/core': 0.2.0(viem@2.45.1(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(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(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.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71))(zod@3.25.71)) - viem: 2.45.1(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/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 @@ -15464,20 +14918,6 @@ snapshots: - react - use-sync-external-store - '@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71) - zustand: 5.0.0(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) - optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - '@types/react' - - immer - - react - - use-sync-external-store - '@wallet-standard/app@1.1.0': dependencies: '@wallet-standard/base': 1.1.0 @@ -15662,47 +15102,6 @@ snapshots: - utf-8-validate - zod - '@walletconnect/ethereum-provider@2.21.1(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)': - dependencies: - '@reown/appkit': 1.7.8(bufferutil@4.0.9)(react@19.2.3)(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/events@1.0.1': dependencies: keyvaluestorage-interface: 1.0.0 @@ -16883,10 +16282,6 @@ snapshots: dependencies: 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.3)): - dependencies: - valtio: 1.13.2(react@19.2.3) - des.js@1.1.0: dependencies: inherits: 2.0.4 @@ -19041,26 +18436,6 @@ snapshots: - immer - use-sync-external-store - porto@0.2.19(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)))(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.45.1(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(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)) - optionalDependencies: - '@tanstack/react-query': 5.90.8(react@19.2.3) - react: 19.2.3 - typescript: 5.8.3 - wagmi: 2.18.2(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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 - poseidon-lite@0.2.1: {} possible-typed-array-names@1.1.0: {} @@ -20160,10 +19535,6 @@ snapshots: dependencies: react: 19.2.1 - use-sync-external-store@1.2.0(react@19.2.3): - dependencies: - react: 19.2.3 - use-sync-external-store@1.4.0(react@19.2.0): dependencies: react: 19.2.0 @@ -20172,10 +19543,6 @@ snapshots: dependencies: react: 19.2.1 - use-sync-external-store@1.4.0(react@19.2.3): - dependencies: - react: 19.2.3 - utf-8-validate@5.0.10: dependencies: node-gyp-build: 4.8.4 @@ -20216,14 +19583,6 @@ snapshots: '@types/react': 19.2.2 react: 19.2.1 - valtio@1.13.2(react@19.2.3): - dependencies: - derive-valtio: 0.1.0(valtio@1.13.2(react@19.2.3)) - proxy-compare: 2.6.0 - use-sync-external-store: 1.2.0(react@19.2.3) - optionalDependencies: - react: 19.2.3 - vary@1.1.2: {} viem@2.23.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71): @@ -20573,45 +19932,6 @@ snapshots: - utf-8-validate - zod - wagmi@2.18.2(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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.3) - '@wagmi/connectors': 6.1.0(@tanstack/react-query@5.90.8(react@19.2.3))(@wagmi/core@2.22.1(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(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.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(utf-8-validate@5.0.10)(viem@2.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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(react@19.2.3)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.2.3))(viem@2.45.1(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.71)) - react: 19.2.3 - use-sync-external-store: 1.4.0(react@19.2.3) - viem: 2.45.1(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 - webextension-polyfill@0.10.0: {} webidl-conversions@3.0.1: {} @@ -20746,54 +20066,6 @@ snapshots: bufferutil: 4.0.9 utf-8-validate: 5.0.10 - x402@0.7.3(@solana/sysvars@6.1.0(typescript@5.8.3))(@tanstack/react-query@5.90.8(react@19.2.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10): - dependencies: - '@scure/base': 1.2.6 - '@solana-program/compute-budget': 0.11.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@solana-program/token': 0.9.0(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@solana-program/token-2022': 0.6.1(@solana/kit@5.3.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/sysvars@6.1.0(typescript@5.8.3)) - '@solana/kit': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana/transaction-confirmation': 5.3.0(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(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.45.1(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.3))(bufferutil@4.0.9)(react@19.2.3)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.45.1(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 - xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} @@ -20859,11 +20131,6 @@ snapshots: react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) - zustand@5.0.0(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): - optionalDependencies: - react: 19.2.3 - use-sync-external-store: 1.4.0(react@19.2.3) - 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 @@ -20876,11 +20143,6 @@ snapshots: react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) - zustand@5.0.3(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): - optionalDependencies: - react: 19.2.3 - use-sync-external-store: 1.4.0(react@19.2.3) - 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 @@ -20892,8 +20154,3 @@ snapshots: '@types/react': 19.2.2 react: 19.2.1 use-sync-external-store: 1.4.0(react@19.2.1) - - zustand@5.0.8(react@19.2.3)(use-sync-external-store@1.4.0(react@19.2.3)): - optionalDependencies: - react: 19.2.3 - use-sync-external-store: 1.4.0(react@19.2.3) diff --git a/examples/typescript/pnpm-lock.yaml b/examples/typescript/pnpm-lock.yaml index 9b065b182e..7c3631b1fd 100644 --- a/examples/typescript/pnpm-lock.yaml +++ b/examples/typescript/pnpm-lock.yaml @@ -1211,8 +1211,8 @@ importers: ../../typescript/packages/mechanisms/stellar: dependencies: '@stellar/stellar-sdk': - specifier: ^14.4.2 - version: 14.5.0 + specifier: ^14.6.1 + version: 14.6.1 '@x402/core': specifier: workspace:* version: link:../../core @@ -7770,12 +7770,12 @@ packages: '@stellar/js-xdr@3.1.2': resolution: {integrity: sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==} - '@stellar/stellar-base@14.0.4': - resolution: {integrity: sha512-UbNW6zbdOBXJwLAV2mMak0bIC9nw3IZVlQXkv2w2dk1jgCbJjy3oRVC943zeGE5JAm0Z9PHxrIjmkpGhayY7kw==} + '@stellar/stellar-base@14.1.0': + resolution: {integrity: sha512-A8kFli6QGy22SRF45IjgPAJfUNGjnI+R7g4DF5NZYVsD1kGf7B4ITyc4OPclLV9tqNI4/lXxafGEw0JEUbHixw==} engines: {node: '>=20.0.0'} - '@stellar/stellar-sdk@14.5.0': - resolution: {integrity: sha512-Uzjq+An/hUA+Q5ERAYPtT0+MMiwWnYYWMwozmZMjxjdL2MmSjucBDF8Q04db6K/ekU4B5cHuOfsdlrfaxQYblw==} + '@stellar/stellar-sdk@14.6.1': + resolution: {integrity: sha512-A1rQWDLdUasXkMXnYSuhgep+3ZZzyuXJKdt5/KAIc0gkmSp906HTvUpbT4pu+bVr41tu0+J4Ugz9J4BQAGGytg==} engines: {node: '>=20.0.0'} hasBin: true @@ -14691,8 +14691,8 @@ snapshots: '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10) abitype: 1.0.6(typescript@5.9.2)(zod@3.25.76) - axios: 1.13.2 - axios-retry: 4.5.0(axios@1.13.2) + axios: 1.13.4 + axios-retry: 4.5.0(axios@1.13.4) jose: 6.0.12 md5: 2.3.0 uncrypto: 0.1.3 @@ -14714,8 +14714,8 @@ snapshots: '@solana/kit': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.2)(ws@8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/web3.js': 1.98.4(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.9.2)(utf-8-validate@5.0.10) abitype: 1.0.6(typescript@5.9.2)(zod@3.25.76) - axios: 1.13.2 - axios-retry: 4.5.0(axios@1.13.2) + axios: 1.13.4 + axios-retry: 4.5.0(axios@1.13.4) jose: 6.0.12 md5: 2.3.0 uncrypto: 0.1.3 @@ -21133,7 +21133,7 @@ snapshots: '@stellar/js-xdr@3.1.2': {} - '@stellar/stellar-base@14.0.4': + '@stellar/stellar-base@14.1.0': dependencies: '@noble/curves': 1.9.7 '@stellar/js-xdr': 3.1.2 @@ -21142,12 +21142,12 @@ snapshots: buffer: 6.0.3 sha.js: 2.4.12 - '@stellar/stellar-sdk@14.5.0': + '@stellar/stellar-sdk@14.6.1': dependencies: - '@stellar/stellar-base': 14.0.4 + '@stellar/stellar-base': 14.1.0 axios: 1.13.4 bignumber.js: 9.3.1 - commander: 14.0.2 + commander: 14.0.3 eventsource: 2.0.2 feaxios: 0.0.23 randombytes: 2.1.0 @@ -24230,6 +24230,11 @@ snapshots: axios: 1.13.2 is-retry-allowed: 2.2.0 + axios-retry@4.5.0(axios@1.13.4): + dependencies: + axios: 1.13.4 + is-retry-allowed: 2.2.0 + axios@1.13.2: dependencies: follow-redirects: 1.15.11 diff --git a/typescript/.changeset/ten-knives-trade.md b/typescript/.changeset/ten-knives-trade.md new file mode 100644 index 0000000000..45e4be2dae --- /dev/null +++ b/typescript/.changeset/ten-knives-trade.md @@ -0,0 +1,5 @@ +--- +'@x402/stellar': patch +--- + +Bump "@stellar/stellar-sdk" dependency and refactor API call for better performance diff --git a/typescript/packages/mechanisms/stellar/package.json b/typescript/packages/mechanisms/stellar/package.json index 58a0ba7411..af03da5b1a 100644 --- a/typescript/packages/mechanisms/stellar/package.json +++ b/typescript/packages/mechanisms/stellar/package.json @@ -46,7 +46,7 @@ "vitest": "^3.0.5" }, "dependencies": { - "@stellar/stellar-sdk": "^14.4.2", + "@stellar/stellar-sdk": "^14.6.1", "@x402/core": "workspace:*" }, "exports": { diff --git a/typescript/packages/mechanisms/stellar/src/constants.ts b/typescript/packages/mechanisms/stellar/src/constants.ts index 0afcc7ea3b..e3ef92198a 100644 --- a/typescript/packages/mechanisms/stellar/src/constants.ts +++ b/typescript/packages/mechanisms/stellar/src/constants.ts @@ -10,6 +10,12 @@ export const STELLAR_WILDCARD_CAIP2 = "stellar:*"; */ export const DEFAULT_TESTNET_RPC_URL = "https://soroban-testnet.stellar.org"; +/** + * Default Horizon API URLs + */ +export const DEFAULT_TESTNET_HORIZON_URL = "https://horizon-testnet.stellar.org"; +export const DEFAULT_PUBNET_HORIZON_URL = "https://horizon.stellar.org"; + /** * Stellar validation regex for destination and asset addresses */ diff --git a/typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts b/typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts index 0e78c31d10..2724fcad67 100644 --- a/typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts +++ b/typescript/packages/mechanisms/stellar/src/exact/client/scheme.ts @@ -1,5 +1,4 @@ -import { nativeToScVal, TransactionBuilder, contract } from "@stellar/stellar-sdk"; -import { Api } from "@stellar/stellar-sdk/rpc"; +import { nativeToScVal, contract } from "@stellar/stellar-sdk"; import { handleSimulationResult } from "../../shared"; import { getEstimatedLedgerCloseTimeSeconds, @@ -14,9 +13,6 @@ import { import type { ClientStellarSigner } from "../../signer"; import type { PaymentPayload, PaymentRequirements, SchemeNetworkClient } from "@x402/core/types"; -/** Base fee in stroops (0.001 XLM) used when building the final tx fee after auth signing. */ -const DEFAULT_BASE_FEE_STROOPS = 10_000; - /** * Stellar client implementation for the Exact payment scheme. */ @@ -61,11 +57,11 @@ export class ExactStellarScheme implements SchemeNetworkClient { throw new Error(`Exact scheme requires areFeesSponsored to be true`); } - // Fetch current ledger and calculate maxLedger (uses RPC getLedgers for close time) + // Fetch current ledger and calculate maxLedger const rpcServer = getRpcClient(network, this.rpcConfig); const latestLedger = await rpcServer.getLatestLedger(); const currentLedger = latestLedger.sequence; - const estimatedLedgerSeconds = await getEstimatedLedgerCloseTimeSeconds(rpcServer); + const estimatedLedgerSeconds = await getEstimatedLedgerCloseTimeSeconds(network); const maxLedger = currentLedger + Math.ceil(maxTimeoutSeconds / estimatedLedgerSeconds); const tx = await contract.AssembledTransaction.build({ @@ -103,19 +99,10 @@ export class ExactStellarScheme implements SchemeNetworkClient { throw new Error(`unexpected signer(s) required: [${missingSigners.join(", ")}]`); } - const finalTx = - tx.simulation && Api.isSimulationSuccess(tx.simulation) - ? TransactionBuilder.cloneFrom(tx.built!, { - fee: (DEFAULT_BASE_FEE_STROOPS + parseInt(tx.simulation.minResourceFee, 10)).toString(), - sorobanData: tx.simulationData.transactionData, - networkPassphrase, - }).build() - : tx.built!; - return { x402Version, payload: { - transaction: finalTx.toXDR(), + transaction: tx.built!.toXDR(), }, }; } diff --git a/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts index ec90f599d5..bac8c87dd2 100644 --- a/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/stellar/src/exact/facilitator/scheme.ts @@ -308,7 +308,7 @@ export class ExactStellarScheme implements SchemeNetworkFacilitator { const latestLedger = await server.getLatestLedger(); const currentLedger = latestLedger.sequence; const maxTimeoutSeconds = requirements.maxTimeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS; - const estimatedLedgerSeconds = await getEstimatedLedgerCloseTimeSeconds(server); + const estimatedLedgerSeconds = await getEstimatedLedgerCloseTimeSeconds(requirements.network); const maxLedgerOffset = Math.ceil(maxTimeoutSeconds / estimatedLedgerSeconds); const maxLedger = currentLedger + maxLedgerOffset; diff --git a/typescript/packages/mechanisms/stellar/src/utils.ts b/typescript/packages/mechanisms/stellar/src/utils.ts index 15349f561f..2005cc2969 100644 --- a/typescript/packages/mechanisms/stellar/src/utils.ts +++ b/typescript/packages/mechanisms/stellar/src/utils.ts @@ -1,5 +1,7 @@ -import { rpc } from "@stellar/stellar-sdk"; +import { Horizon, rpc } from "@stellar/stellar-sdk"; import { + DEFAULT_PUBNET_HORIZON_URL, + DEFAULT_TESTNET_HORIZON_URL, DEFAULT_TESTNET_RPC_URL, DEFAULT_TOKEN_DECIMALS, STELLAR_ASSET_ADDRESS_REGEX, @@ -13,7 +15,7 @@ import { import type { Network } from "@x402/core/types"; export const DEFAULT_ESTIMATED_LEDGER_SECONDS = 5; -const RPC_LEDGERS_SAMPLE_SIZE = 20; +const HORIZON_LEDGERS_SAMPLE_SIZE = 20; /** * Configuration for RPC client connections @@ -109,24 +111,42 @@ export function getRpcClient(network: Network, rpcConfig?: RpcConfig): rpc.Serve } /** - * Fetches the estimated ledger close time (seconds per ledger) from RPC getLedgers. + * Creates a Horizon SDK client for the given network. * - * @param server - The Soroban RPC Server instance + * @param network - The CAIP-2 network identifier + * @returns A configured Horizon.Server instance + * @throws {Error} If the network is unknown + */ +export function getHorizonClient(network: Network): Horizon.Server { + switch (network) { + case STELLAR_TESTNET_CAIP2: + return new Horizon.Server(DEFAULT_TESTNET_HORIZON_URL); + case STELLAR_PUBNET_CAIP2: + return new Horizon.Server(DEFAULT_PUBNET_HORIZON_URL); + default: + throw new Error(`Unknown Stellar network: ${network}`); + } +} + +/** + * Estimates ledger close time by fetching the most recent ledgers from Horizon. + * + * Uses the Horizon SDK's ledger query builder which is significantly faster + * than the Soroban RPC `getLedgers` method for this purpose. + * + * @param network - The CAIP-2 network identifier * @returns Estimated seconds per ledger, or DEFAULT_ESTIMATED_LEDGER_SECONDS (5) on error */ -export async function getEstimatedLedgerCloseTimeSeconds(server: rpc.Server): Promise { +export async function getEstimatedLedgerCloseTimeSeconds(network: Network): Promise { try { - const latestLedger = await server.getLatestLedger(); - const startLedger = latestLedger.sequence; - const { ledgers } = await server.getLedgers({ - startLedger, - pagination: { limit: RPC_LEDGERS_SAMPLE_SIZE }, - }); - if (!ledgers || ledgers.length < 2) return DEFAULT_ESTIMATED_LEDGER_SECONDS; - - const oldestTs = parseInt(ledgers[0].ledgerCloseTime); - const newestTs = parseInt(ledgers[ledgers.length - 1].ledgerCloseTime); - const intervals = ledgers.length - 1; + const horizon = getHorizonClient(network); + const page = await horizon.ledgers().limit(HORIZON_LEDGERS_SAMPLE_SIZE).order("desc").call(); + const records = page.records; + if (!records || records.length < 2) return DEFAULT_ESTIMATED_LEDGER_SECONDS; + + const newestTs = new Date(records[0].closed_at).getTime() / 1000; + const oldestTs = new Date(records[records.length - 1].closed_at).getTime() / 1000; + const intervals = records.length - 1; return Math.ceil((newestTs - oldestTs) / intervals); } catch { return DEFAULT_ESTIMATED_LEDGER_SECONDS; diff --git a/typescript/packages/mechanisms/stellar/test/unit/utils.test.ts b/typescript/packages/mechanisms/stellar/test/unit/utils.test.ts index 9662e63514..4adaf1a44f 100644 --- a/typescript/packages/mechanisms/stellar/test/unit/utils.test.ts +++ b/typescript/packages/mechanisms/stellar/test/unit/utils.test.ts @@ -1,4 +1,4 @@ -import { rpc } from "@stellar/stellar-sdk"; +import { Horizon, rpc } from "@stellar/stellar-sdk"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { STELLAR_PUBNET_CAIP2, STELLAR_TESTNET_CAIP2 } from "../../src"; import { @@ -17,6 +17,9 @@ import { // Mock the Stellar SDK vi.mock("@stellar/stellar-sdk", () => ({ + Horizon: { + Server: vi.fn(), + }, rpc: { Server: vi.fn(), }, @@ -228,66 +231,64 @@ describe("Stellar RPC Helper Functions", () => { }); describe("getEstimatedLedgerCloseTimeSeconds", () => { - it("should compute seconds per ledger from RPC getLedgers response", async () => { + function mockHorizonServer(records: Array<{ closed_at: string; sequence: number }>) { + const mockCall = vi.fn().mockResolvedValue({ records }); + const mockOrder = vi.fn().mockReturnValue({ call: mockCall }); + const mockLimit = vi.fn().mockReturnValue({ order: mockOrder }); + const mockLedgers = vi.fn().mockReturnValue({ limit: mockLimit }); + vi.mocked(Horizon.Server).mockImplementation(() => ({ ledgers: mockLedgers }) as any); + return { mockCall, mockOrder, mockLimit, mockLedgers }; + } + + it("should compute seconds per ledger from Horizon SDK ledgers response", async () => { const baseTs = 1734032457; - const ledgers = [100, 101, 102, 103, 104, 105].map((seq, i) => ({ + const records = [105, 104, 103, 102, 101, 100].map((seq, i) => ({ sequence: seq, - ledgerCloseTime: String(baseTs + i * 3), + closed_at: new Date((baseTs + (5 - i) * 3) * 1000).toISOString(), })); - const mockGetLedgers = vi.fn().mockResolvedValue({ ledgers }); - const mockServer = { - getLatestLedger: vi.fn().mockResolvedValue({ sequence: 105 }), - getLedgers: mockGetLedgers, - } as unknown as rpc.Server; + const { mockLedgers, mockLimit, mockOrder } = mockHorizonServer(records); - const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + const result = await getEstimatedLedgerCloseTimeSeconds(STELLAR_TESTNET_CAIP2); expect(result).toBe(3); - expect(mockGetLedgers).toHaveBeenCalledWith( - expect.objectContaining({ - pagination: { limit: 20 }, - }), - ); - const callArg = mockGetLedgers.mock.calls[0][0]; - expect(callArg.startLedger).toBeGreaterThanOrEqual(1); - expect(callArg.startLedger).toBeLessThanOrEqual(105); + expect(Horizon.Server).toHaveBeenCalledWith("https://horizon-testnet.stellar.org"); + expect(mockLedgers).toHaveBeenCalled(); + expect(mockLimit).toHaveBeenCalledWith(20); + expect(mockOrder).toHaveBeenCalledWith("desc"); }); - it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when getLatestLedger throws", async () => { - const mockGetLedgers = vi.fn(); - const mockServer = { - getLatestLedger: vi.fn().mockRejectedValue(new Error("RPC error")), - getLedgers: mockGetLedgers, - } as unknown as rpc.Server; + it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when SDK call throws", async () => { + const mockCall = vi.fn().mockRejectedValue(new Error("Network error")); + const mockOrder = vi.fn().mockReturnValue({ call: mockCall }); + const mockLimit = vi.fn().mockReturnValue({ order: mockOrder }); + const mockLedgers = vi.fn().mockReturnValue({ limit: mockLimit }); + vi.mocked(Horizon.Server).mockImplementation(() => ({ ledgers: mockLedgers }) as any); - const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + const result = await getEstimatedLedgerCloseTimeSeconds(STELLAR_TESTNET_CAIP2); expect(result).toBe(DEFAULT_ESTIMATED_LEDGER_SECONDS); - expect(mockGetLedgers).not.toHaveBeenCalled(); }); - it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when getLedgers throws", async () => { - const mockServer = { - getLatestLedger: vi.fn().mockResolvedValue({ sequence: 100 }), - getLedgers: vi.fn().mockRejectedValue(new Error("Network error")), - } as unknown as rpc.Server; + it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when fewer than 2 records", async () => { + mockHorizonServer([{ sequence: 100, closed_at: "2024-12-13T00:00:57Z" }]); - const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + const result = await getEstimatedLedgerCloseTimeSeconds(STELLAR_TESTNET_CAIP2); expect(result).toBe(DEFAULT_ESTIMATED_LEDGER_SECONDS); }); - it("should return DEFAULT_ESTIMATED_LEDGER_SECONDS when getLedgers returns fewer than 2 records", async () => { - const mockServer = { - getLatestLedger: vi.fn().mockResolvedValue({ sequence: 100 }), - getLedgers: vi.fn().mockResolvedValue({ - ledgers: [{ sequence: 100, ledgerCloseTime: "1734032457" }], - }), - } as unknown as rpc.Server; + it("should use pubnet Horizon URL for pubnet network", async () => { + const baseTs = 1734032457; + const records = [102, 101, 100].map((seq, i) => ({ + sequence: seq, + closed_at: new Date((baseTs + (2 - i) * 6) * 1000).toISOString(), + })); + mockHorizonServer(records); - const result = await getEstimatedLedgerCloseTimeSeconds(mockServer); + const result = await getEstimatedLedgerCloseTimeSeconds(STELLAR_PUBNET_CAIP2); - expect(result).toBe(DEFAULT_ESTIMATED_LEDGER_SECONDS); + expect(result).toBe(6); + expect(Horizon.Server).toHaveBeenCalledWith("https://horizon.stellar.org"); }); }); diff --git a/typescript/pnpm-lock.yaml b/typescript/pnpm-lock.yaml index 435d1faa82..bec28727ab 100644 --- a/typescript/pnpm-lock.yaml +++ b/typescript/pnpm-lock.yaml @@ -1220,8 +1220,8 @@ importers: packages/mechanisms/stellar: dependencies: '@stellar/stellar-sdk': - specifier: ^14.4.2 - version: 14.5.0 + specifier: ^14.6.1 + version: 14.6.1 '@x402/core': specifier: workspace:* version: link:../../core @@ -4216,12 +4216,12 @@ packages: '@stellar/js-xdr@3.1.2': resolution: {integrity: sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==} - '@stellar/stellar-base@14.0.4': - resolution: {integrity: sha512-UbNW6zbdOBXJwLAV2mMak0bIC9nw3IZVlQXkv2w2dk1jgCbJjy3oRVC943zeGE5JAm0Z9PHxrIjmkpGhayY7kw==} + '@stellar/stellar-base@14.1.0': + resolution: {integrity: sha512-A8kFli6QGy22SRF45IjgPAJfUNGjnI+R7g4DF5NZYVsD1kGf7B4ITyc4OPclLV9tqNI4/lXxafGEw0JEUbHixw==} engines: {node: '>=20.0.0'} - '@stellar/stellar-sdk@14.5.0': - resolution: {integrity: sha512-Uzjq+An/hUA+Q5ERAYPtT0+MMiwWnYYWMwozmZMjxjdL2MmSjucBDF8Q04db6K/ekU4B5cHuOfsdlrfaxQYblw==} + '@stellar/stellar-sdk@14.6.1': + resolution: {integrity: sha512-A1rQWDLdUasXkMXnYSuhgep+3ZZzyuXJKdt5/KAIc0gkmSp906HTvUpbT4pu+bVr41tu0+J4Ugz9J4BQAGGytg==} engines: {node: '>=20.0.0'} hasBin: true @@ -13070,7 +13070,7 @@ snapshots: '@stellar/js-xdr@3.1.2': {} - '@stellar/stellar-base@14.0.4': + '@stellar/stellar-base@14.1.0': dependencies: '@noble/curves': 1.9.7 '@stellar/js-xdr': 3.1.2 @@ -13079,12 +13079,12 @@ snapshots: buffer: 6.0.3 sha.js: 2.4.12 - '@stellar/stellar-sdk@14.5.0': + '@stellar/stellar-sdk@14.6.1': dependencies: - '@stellar/stellar-base': 14.0.4 + '@stellar/stellar-base': 14.1.0 axios: 1.13.4 bignumber.js: 9.3.1 - commander: 14.0.2 + commander: 14.0.3 eventsource: 2.0.2 feaxios: 0.0.23 randombytes: 2.1.0 From 30e01607975ee0e1a4b5a672d3524d2d174bccf9 Mon Sep 17 00:00:00 2001 From: Alfred Tom <79275786+alftom@users.noreply.github.com> Date: Sun, 15 Mar 2026 18:20:03 -0700 Subject: [PATCH 069/129] docs: add extensions overview and signed offers & receipts guide (#1617) * docs: add extensions overview and signed offers & receipts guide - Add extensions/overview.mdx documenting the extension system - Add extensions/offer-receipt.mdx - Add offer-receipt row to sdk-features.md - Update docs.json navigation with new pages in alphabetical order * Refined the link to the ecosystem page. --- docs/docs.json | 4 +- docs/extensions/offer-receipt.mdx | 424 ++++++++++++++++++++++++++++++ docs/extensions/overview.mdx | 160 +++++++++++ docs/sdk-features.md | 1 + 4 files changed, 588 insertions(+), 1 deletion(-) create mode 100644 docs/extensions/offer-receipt.mdx create mode 100644 docs/extensions/overview.mdx diff --git a/docs/docs.json b/docs/docs.json index ad1a0c407b..2cb4cf1d57 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -65,9 +65,11 @@ { "group": "Extensions", "pages": [ + "extensions/overview", "extensions/bazaar", + "extensions/payment-identifier", "extensions/sign-in-with-x", - "extensions/payment-identifier" + "extensions/offer-receipt" ] }, { diff --git a/docs/extensions/offer-receipt.mdx b/docs/extensions/offer-receipt.mdx new file mode 100644 index 0000000000..b7d116e837 --- /dev/null +++ b/docs/extensions/offer-receipt.mdx @@ -0,0 +1,424 @@ +--- +title: "Signed Offers & Receipts" +description: "Sign offers on 402 responses and receipts on 200 responses, producing cryptographic proof-of-interaction artifacts that clients can use for reputation, auditing, or dispute resolution." +--- + +The Offer & Receipt extension adds cryptographic proof-of-interaction to x402 payment flows. When enabled, your server automatically signs an **offer** on every `402` response (committing to payment terms) and a **receipt** on every `200` response (confirming service delivery). No changes to your business logic. + +## Why Enable Offer & Receipt Signing? + +Signed offers and receipts are portable, verifiable artifacts that any third party can check. They enable: + +* **Reputation systems** β€” Clients can attach receipts to on-chain attestations as proof they actually paid for and received a service. This is the "Verified Purchase" equivalent for the open web. +* **Dispute resolution** β€” Offers prove the server committed to specific terms; receipts prove delivery. If either party disputes a transaction, the signed artifacts provide evidence. +* **Auditing** β€” Receipts create a verifiable trail of service delivery without exposing transaction details (the transaction hash is optional). +* **Client confidence** β€” Services with verifiable proof-of-interaction build stronger trust signals, making new clients more likely to use the service. + +## Prerequisites + +- An existing x402 resource server (or a new Express.js project) +- Node.js 18+ +- A facilitator URL (see [Quickstart for Sellers](/getting-started/quickstart-for-sellers)) + +## Installation + +```bash +npm install @x402/express @x402/extensions @x402/evm @x402/core viem +``` + +## Signing Formats + +The extension supports two signature formats. Choose based on your key management setup: + +| Format | Key Type | Identity | Best For | +|--------|----------|----------|----------| +| **EIP-712** | secp256k1 (Ethereum) | `did:pkh` (address recovered from signature) | Wallet-based signing. Simpler setup, especially with managed wallet providers. | +| **JWS** | Any asymmetric key (EC P-256, Ed25519, secp256k1) | `did:web` (resolved via `/.well-known/did.json`) | Server-side signing with KMS/HSM. Also supports Solana keys (Ed25519), so if your infrastructure is Solana-native, JWS may be the more natural fit. | + +Both formats produce equivalent proof artifacts. Clients and verifiers handle both transparently. + +## Quick Start: EIP-712 with Environment Variables + +This example uses EIP-712 signing with a raw private key from an environment variable. This is the simplest way to get started. + +> **Not for Production:** Storing private keys in environment variables is acceptable for local development and testing. For production deployments, use a key management service (KMS), hardware security module (HSM), or a managed wallet provider. See [Production Key Management](#production-key-management) below. + +> **Signing Key β‰  Payment Address:** The signing key used for offers and receipts should be a dedicated signing key, not the wallet that receives payments (`payTo`). Separating signing from payment receipt limits exposure if the signing key is compromised. + +### Environment Variables + +Create a `.env` file: + +```bash +# Wallet address that receives payments +EVM_ADDRESS=0xYourPaymentWalletAddress + +# Private key for signing offers and receipts (EIP-712) +# This should be a DEDICATED SIGNING KEY, not the payment wallet's key +# For production deployments, do not store private keys in an environment variable +SIGNING_PRIVATE_KEY=0xYourDedicatedSigningPrivateKey + +# x402 facilitator URL +FACILITATOR_URL=https://facilitator.x402.org +``` + +### Server Setup (EIP-712) + +```typescript +import { config } from "dotenv"; +import express from "express"; +import { paymentMiddleware, x402ResourceServer } from "@x402/express"; +import { ExactEvmScheme } from "@x402/evm/exact/server"; +import { HTTPFacilitatorClient } from "@x402/core/server"; +import { + createOfferReceiptExtension, + createEIP712OfferReceiptIssuer, + declareOfferReceiptExtension, +} from "@x402/extensions/offer-receipt"; +import { privateKeyToAccount } from "viem/accounts"; + +config(); + +const evmAddress = process.env.EVM_ADDRESS as `0x${string}`; +const signingPrivateKey = process.env.SIGNING_PRIVATE_KEY as `0x${string}`; // not for production +const facilitatorUrl = process.env.FACILITATOR_URL!; + +// Create EIP-712 signer from the dedicated signing key +const signingAccount = privateKeyToAccount(signingPrivateKey); +const kid = `did:pkh:eip155:1:${signingAccount.address}#key-1`; + +const offerReceiptIssuer = createEIP712OfferReceiptIssuer( + kid, + signingAccount.signTypedData.bind(signingAccount), +); + +// Set up the resource server with the extension +const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); +const resourceServer = new x402ResourceServer(facilitatorClient) + .register("eip155:84532", new ExactEvmScheme()) + .registerExtension(createOfferReceiptExtension(offerReceiptIssuer)); + +const app = express(); + +// Configure payment routes with offer-receipt enabled +app.use( + paymentMiddleware( + { + "GET /api/data": { + accepts: [ + { + scheme: "exact", + price: "$0.001", + network: "eip155:84532", + payTo: evmAddress, // Payment goes here (different from signing key) + }, + ], + description: "Premium data endpoint", + mimeType: "application/json", + extensions: { + ...declareOfferReceiptExtension({ includeTxHash: false }), + }, + }, + }, + resourceServer, + ), +); + +// Your business logic β€” unchanged +app.get("/api/data", (req, res) => { + res.json({ data: "your premium content" }); +}); + +app.listen(4021, () => { + console.log("Server listening on http://localhost:4021"); + console.log("Offer-receipt extension enabled (EIP-712)"); +}); +``` + +### What Happens Automatically + +Once configured, the extension hooks into the x402 payment flow: + +1. **On `402` responses**: The extension signs an offer for each entry in `accepts[]` and includes them in the response's `extensions` field. Each offer contains the payment terms (`scheme`, `network`, `amount`, `payTo`) and a `validUntil` timestamp. + +2. **On `200` responses** (after successful payment): The extension signs a receipt containing the `resourceUrl`, `payer` address, `network`, and `issuedAt` timestamp. The receipt is included in the `PAYMENT-RESPONSE` header's `extensions` field. + +No changes to your route handlers are needed. The extension is composable middleware. + +## Alternative: JWS Signing with `did:web` + +JWS signing uses a `did:web` identifier, which means your server must host a DID document at `/.well-known/did.json`. Clients and verifiers resolve this document to find your public key so they can verify the signature. + +JWS supports a wider range of key types than EIP-712 (secp256k1 only), including secp256r1 (EC P-256), Ed25519, and secp256k1 (ES256K). If your infrastructure is enterprise-oriented or Solana-native (Ed25519), JWS lets you use your existing key infrastructure. + +### Environment Variables + +```bash +EVM_ADDRESS=0xYourPaymentWalletAddress +FACILITATOR_URL=https://facilitator.x402.org + +# Base64-encoded PKCS#8 private key (EC P-256) +# For production deployments, do not store private keys in an environment variable +SIGNING_PRIVATE_KEY=base64EncodedPrivateKey + +# Your server's domain (URL-encoded for did:web) +# e.g., "api.example.com" or "localhost%3A4021" for local dev +SERVER_DOMAIN=api.example.com +``` + +### Server Setup (JWS) + +```typescript +import * as crypto from "crypto"; +import { + createOfferReceiptExtension, + createJWSOfferReceiptIssuer, + declareOfferReceiptExtension, + type JWSSigner, +} from "@x402/extensions/offer-receipt"; + +const serverDomain = process.env.SERVER_DOMAIN!; +const signingPrivateKey = process.env.SIGNING_PRIVATE_KEY!; // not for production + +const did = `did:web:${serverDomain}`; +const kid = `${did}#key-1`; + +// Create JWS signer from PKCS#8 private key +const privateKeyPem = `-----BEGIN PRIVATE KEY-----\n${signingPrivateKey}\n-----END PRIVATE KEY-----`; +const keyObject = crypto.createPrivateKey(privateKeyPem); +const publicKeyJwk = keyObject.export({ format: "jwk" }); +delete (publicKeyJwk as Record).d; // Remove private component + +const jwsSigner: JWSSigner = { + kid, + format: "jws", + algorithm: "ES256", + async sign(payload: Uint8Array): Promise { + const sign = crypto.createSign("SHA256"); + sign.update(payload); + const signature = sign.sign(privateKeyPem); + return Buffer.from(derToRaw(signature)).toString("base64url"); + }, +}; + +const offerReceiptIssuer = createJWSOfferReceiptIssuer(kid, jwsSigner); + +// Register with x402ResourceServer the same way as the EIP-712 example: +// resourceServer.registerExtension(createOfferReceiptExtension(offerReceiptIssuer)); +``` + +### Hosting the DID Document + +For JWS verification, clients resolve your `did:web` to find the public key. Serve the DID document at `/.well-known/did.json`: + +```typescript +app.get("/.well-known/did.json", (req, res) => { + res.setHeader("Content-Type", "application/did+json"); + res.json({ + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1", + ], + id: did, + verificationMethod: [ + { + id: kid, + type: "JsonWebKey2020", + controller: did, + publicKeyJwk, + }, + ], + assertionMethod: [kid], + }); +}); +``` + +## Configuration + +The `declareOfferReceiptExtension` function accepts an optional configuration object: + +```typescript +declareOfferReceiptExtension({ + // Include the blockchain transaction hash in receipts. + // Default: false (for privacy β€” the payer address is still included). + // Set to true if verifiability is more important than privacy. + includeTxHash: false, + + // How long offers remain valid, in seconds. + // Default: 300 (5 minutes). Falls back to the route's maxTimeoutSeconds. + offerValiditySeconds: 300, +}); +``` + +Configuration is per-route β€” different endpoints can have different settings. + + +## What Gets Signed + +### Offer Payload + +Each offer is signed when the server returns a `402 Payment Required` response: + +| Field | Description | +|-------|-------------| +| `resourceUrl` | The URL the client is requesting | +| `offerType` | The payment scheme (e.g., `exact`) | +| `network` | The blockchain network (e.g., `eip155:84532`) | +| `amount` | The payment amount in the token's smallest unit | +| `payTo` | The server's payment address | +| `validUntil` | Unix timestamp after which the offer expires | + +### Receipt Payload + +Each receipt is signed when the server returns a `200` response after successful payment: + +| Field | Description | +|-------|-------------| +| `resourceUrl` | The URL the client requested | +| `payer` | The client's wallet address (from the payment) | +| `network` | The blockchain network used for payment | +| `issuedAt` | Unix timestamp when the receipt was issued | +| `txHash` | *(optional)* The blockchain transaction hash, included only if `includeTxHash: true` | + +Both payloads are signed using the format configured on the server (EIP-712 or JWS). The signed artifacts are self-contained β€” a verifier only needs the artifact and the signer's public key to verify. + +## Production Key Management + +> The examples above use environment variables for signing keys. This is fine for development but not for production. Private keys in environment variables can leak through process inspection, logging, crash dumps, and container metadata endpoints. + +For production, use a signing backend that keeps keys in secure hardware or managed infrastructure. The extension's signer interface is pluggable β€” you only need to implement the `sign()` function (for JWS) or `signTypedData()` function (for EIP-712) using your provider's SDK. The `OfferReceiptIssuer` interface handles the rest. + +When using a managed wallet provider, you won't have access to the raw private key. Instead, you call the provider's signing API. Here's what the EIP-712 setup looks like with a server wallet (conceptual example): + +```typescript +import { + createOfferReceiptExtension, + createEIP712OfferReceiptIssuer, +} from "@x402/extensions/offer-receipt"; + +// The provider's SDK gives you a signTypedData function +// that calls their API β€” the private key never leaves their infrastructure +const signerAddress = "0xYourServerWalletAddress"; +const kid = `did:pkh:eip155:1:${signerAddress}#key-1`; + +const offerReceiptIssuer = createEIP712OfferReceiptIssuer(kid, async (params) => { + // Call your wallet provider's signing API + return await yourWalletProvider.signTypedData({ + domain: params.domain, + types: params.types, + primaryType: params.primaryType, + message: params.message, + }); +}); + +// Register as usual +resourceServer.registerExtension(createOfferReceiptExtension(offerReceiptIssuer)); +``` + +The key difference from the environment variable example: you never construct a `privateKeyToAccount` β€” instead, you pass a function that delegates signing to the provider's API. Any managed wallet provider that supports `signTypedData` (for EIP-712) or raw signing (for JWS) works as a drop-in replacement. + +## Binding Your Signing Key to Your Service Identity + +Signing offers and receipts is only half the story. For verifiers to trust that your signatures are legitimate, they need to confirm that your signing key is authorized to act on behalf of your service's identity (`did:web:yourdomain.com`). + +### DID Document (`did.json`) + +If you're using JWS signing, you're already hosting a DID document at `/.well-known/did.json` (see [JWS setup above](#hosting-the-did-document)). This document declares which keys are authorized for your `did:web` identity. Verifiers resolve your DID and check that the signing key is listed in `verificationMethod`. + +If you're using EIP-712 signing, you can host a `did.json` as well β€” list your EIP-712 signing address as a `verificationMethod` so verifiers can confirm the key is authorized for your domain. + +This is a W3C standard mechanism and is sufficient for many use cases. However, the DID document is mutable β€” if you remove the key later, verifiers checking at that point won't find it. + +### Additional Binding Mechanisms + +For production services that need stronger guarantees β€” immutable on-chain attestations, DNS-based verification, temporal anchoring, or key lifecycle management (expiration, rotation, revocation) β€” ecosystem partners offer additional trust layers on top of `did.json`. See the [Infrastructure & Tooling category](https://www.x402.org/ecosystem?filter=ecosystem-infrastructure) on the ecosystem page for reputation and identity services that integrate with the offer-receipt extension. + +## Client-Side: Extracting Offers and Receipts + +The `@x402/extensions` package provides client utilities for extracting and verifying the signed artifacts your server produces. + +### Extract Offers from a `402` Response + +```typescript +import { + extractOffersFromPaymentRequired, + decodeSignedOffers, + verifyOfferSignatureJWS, + verifyOfferSignatureEIP712, + isJWSSignedOffer, +} from "@x402/extensions/offer-receipt"; + +// After receiving a 402 response: +const paymentRequiredBody = await response.json(); +const signedOffers = extractOffersFromPaymentRequired(paymentRequiredBody); +const decodedOffers = decodeSignedOffers(signedOffers); + +// Verify an offer signature +for (const decoded of decodedOffers) { + if (isJWSSignedOffer(decoded.signedOffer)) { + await verifyOfferSignatureJWS(decoded.signedOffer); + } else { + await verifyOfferSignatureEIP712(decoded.signedOffer); + } +} +``` + +### Extract a Receipt from a `200` Response + +```typescript +import { + extractReceiptFromResponse, + verifyReceiptMatchesOffer, + verifyReceiptSignatureJWS, + verifyReceiptSignatureEIP712, + isJWSSignedReceipt, +} from "@x402/extensions/offer-receipt"; + +// After a successful payment response: +const signedReceipt = extractReceiptFromResponse(paidResponse); + +// Verify the receipt signature +if (isJWSSignedReceipt(signedReceipt)) { + await verifyReceiptSignatureJWS(signedReceipt); +} else { + await verifyReceiptSignatureEIP712(signedReceipt); +} + +// Verify the receipt matches the offer you accepted +const verified = verifyReceiptMatchesOffer( + signedReceipt, + selectedOffer, + [yourWalletAddress], +); +``` + +`verifyReceiptMatchesOffer` checks that: +- `resourceUrl` matches the offer +- `network` matches the offer +- `payer` matches one of your wallet addresses +- `issuedAt` is recent (within 1 hour by default) + +### What Can Clients Do with These Artifacts? + +Signed offers and receipts are portable, verifiable artifacts. Clients can: + +- **Attach them to reputation attestations** as proof-of-interaction (e.g., "Verified Purchase" reviews) +- **Store them for auditing** β€” receipts create a verifiable trail of service delivery +- **Use them in dispute resolution** β€” offers prove the server committed to terms; receipts prove delivery +- **Share them with aggregators** β€” trust scoring engines can verify the signatures independently + +Ecosystem partners (see the [Infrastructure & Tooling category](https://www.x402.org/ecosystem?filter=ecosystem-infrastructure) on the ecosystem page) build on these artifacts to provide reputation systems, trust scoring, and other value-added services. + +## Working Examples + +Complete working examples are available in the x402 repository: + +- [Server Example (Express.js)](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/offer-receipt) β€” Resource server with offer-receipt enabled, showing both EIP-712 and JWS configurations +- [Client Example](https://github.com/coinbase/x402/tree/main/examples/typescript/clients/offer-receipt) β€” Complete client flow: offer extraction, payment, receipt capture, and verification + +## Further Reading + +- [Extensions Overview](./overview) β€” How the x402 extension system works +- [Offer & Receipt Extension Specification](https://github.com/coinbase/x402/blob/main/specs/extensions/extension-offer-and-receipt.md) β€” Full protocol spec with payload schemas, EIP-712 types, verification rules, and wire format examples +- [@x402/extensions package](https://github.com/coinbase/x402/tree/main/typescript/packages/extensions/src/offer-receipt) β€” TypeScript implementation source +- [SDK Features](/sdk-features) β€” Extension support across TypeScript, Go, and Python diff --git a/docs/extensions/overview.mdx b/docs/extensions/overview.mdx new file mode 100644 index 0000000000..98b5707088 --- /dev/null +++ b/docs/extensions/overview.mdx @@ -0,0 +1,160 @@ +--- +title: "Extensions Overview" +description: "x402 extensions are composable, optional capabilities that plug into the payment lifecycle. They enrich 402 responses, settlement responses, or both β€” without changing your business logic." +--- + +Extensions are the composable layer on top of x402's core payment protocol. They let resource servers, facilitators, and clients add optional capabilities β€” discovery, authentication, receipts, gas sponsoring β€” without modifying the core payment flow. + +## How Extensions Work + +x402 has two extension points that serve different roles in the payment flow: + +### Resource Server Extensions + +These run on the resource server (the service accepting payments) and hook into the HTTP payment lifecycle. A `ResourceServerExtension` can intervene at three points: + +1. **Declaration** (`enrichDeclaration`) β€” Called at route registration time. The extension can modify or narrow the route's extension declaration based on transport context (e.g., Bazaar narrows the HTTP method). +2. **402 Response** (`enrichPaymentRequiredResponse`) β€” Called when the server returns `402 Payment Required`. The extension can add data to the response (e.g., signed offers, discovery metadata). +3. **Settlement Response** (`enrichSettlementResponse`) β€” Called after successful payment. The extension can add data to the `PAYMENT-RESPONSE` header (e.g., signed receipts, payment identifiers). + +All three hooks are optional. Most extensions use one or two β€” not all three. + +### Facilitator Extensions + +These run on the facilitator (the service that verifies and settles payments on behalf of the resource server). A `FacilitatorExtension` provides a `key` and is stored for use by mechanism implementations during verification and settlement. Gas sponsoring extensions are the primary example β€” they inject batch signing capabilities into the settlement flow so the facilitator can sponsor gas on behalf of the payer. + +## Registering an Extension (Server) + +Extensions implement the `ResourceServerExtension` interface and are registered via `registerExtension`: + +```typescript +import { x402ResourceServer } from "@x402/express"; + +const resourceServer = new x402ResourceServer(facilitatorClient) + .register("eip155:84532", new ExactEvmScheme()) + .registerExtension(myExtension) // Add one extension + .registerExtension(anotherExtension); // Stack another +``` + +Each extension has a unique `key` that identifies it in route declarations and response payloads. + +## The ResourceServerExtension Interface + +```typescript +interface ResourceServerExtension { + /** Unique identifier for this extension */ + key: string; + + /** Enrich the extension declaration at route registration time */ + enrichDeclaration?: (declaration: unknown, transportContext: unknown) => unknown; + + /** Add data to the 402 PaymentRequired response */ + enrichPaymentRequiredResponse?: ( + declaration: unknown, + context: PaymentRequiredContext, + ) => Promise; + + /** Add data to the settlement response after successful payment */ + enrichSettlementResponse?: ( + declaration: unknown, + context: SettleResultContext, + ) => Promise; +} +``` + +## Declaring Extensions on Routes + +Extensions are declared per-route in the payment middleware configuration. Each extension's declaration goes under `extensions` keyed by the extension's `key`: + +```typescript +app.use( + paymentMiddleware( + { + "GET /api/data": { + accepts: [{ scheme: "exact", price: "$0.01", network: "eip155:84532", payTo: address }], + description: "Premium data", + mimeType: "application/json", + extensions: { + // Each key matches a registered extension + "offer-receipt": { includeTxHash: false }, + "bazaar": { /* bazaar config */ }, + }, + }, + }, + resourceServer, + ), +); +``` + +If an extension is declared on a route but not registered on the server, it is silently ignored. + +## Which Hooks Do Extensions Use? + +Not all extensions use the same hooks. Here's how the built-in extensions map to the extension points: + +| Extension | `enrichDeclaration` | `enrichPaymentRequiredResponse` | `enrichSettlementResponse` | Facilitator | +|-----------|:---:|:---:|:---:|:---:| +| Bazaar | βœ… (narrows HTTP method) | β€” | β€” | βœ… (discovery cataloging) | +| EIP-2612 Gas Sponsoring | β€” | β€” | β€” | βœ… (batch signing) | +| ERC-20 Approval Gas Sponsoring | β€” | β€” | β€” | βœ… (batch signing) | +| Payment Identifier | β€” | βœ… | βœ… | β€” | +| Sign-In-With-X | β€” | β€” | β€” | β€” | +| Signed Offers & Receipts | β€” | βœ… (signs offers) | βœ… (signs receipts) | β€” | + +Bazaar is unique in that it spans both sides: the resource server extension enriches declarations, while the facilitator component handles discovery cataloging and validation. Sign-In-With-X manages its own session lifecycle outside the standard hooks. + +## Available Extensions + + +| Extension | Type | Description | SDK Support | +|-----------|------|-------------|-------------| +| [Bazaar](./bazaar) | Server + Facilitator | Discovery layer for x402 endpoints and MCP tools. Makes your services findable by AI agents and developers. | TypeScript, Go, Python | +| EIP-2612 Gas Sponsoring | Facilitator | Sponsors gas for EIP-2612 permit-based token transfers. | TypeScript | +| ERC-20 Approval Gas Sponsoring | Facilitator | Sponsors gas for ERC-20 approval-based token transfers. | TypeScript | +| [Payment Identifier](./payment-identifier) | Server + Client | Attaches a unique identifier to each payment for tracking, reconciliation, and idempotency. | TypeScript, Go, Python | +| [Sign-In-With-X](./sign-in-with-x) | Server + Client | CAIP-122 wallet authentication. Lets clients prove wallet ownership to access previously purchased content without repaying. | TypeScript | +| [Signed Offers & Receipts](./offer-receipt) | Server + Client | Signs offers on 402 responses and receipts on 200 responses, producing cryptographic proof-of-interaction artifacts. | TypeScript | + +## Building a Custom Extension + +To create your own extension: + +1. **Define the extension object** implementing `ResourceServerExtension` +2. **Choose a unique key** β€” this identifies your extension in route declarations and response payloads +3. **Implement the hooks you need** β€” `enrichDeclaration`, `enrichPaymentRequiredResponse`, `enrichSettlementResponse` +4. **Create a declare function** β€” a helper that returns the route-level configuration for your extension +5. **Register it** on the `x402ResourceServer` via `registerExtension` +6. **Submit a pull request** to [coinbase/x402](https://github.com/coinbase/x402) β€” extensions must be reviewed and approved by the x402 maintainers before they are included in the SDK + +Here's a minimal example: + +```typescript +import type { ResourceServerExtension } from "@x402/core"; + +const myExtension: ResourceServerExtension = { + key: "my-extension", + + enrichPaymentRequiredResponse: async (declaration, context) => { + // Add custom data to the 402 response + return { customField: "value", timestamp: Date.now() }; + }, + + enrichSettlementResponse: async (declaration, context) => { + // Add custom data after successful payment + return { settled: true, processedAt: Date.now() }; + }, +}; + +// Declare helper for route config +function declareMyExtension(config: { customOption: boolean }) { + return { "my-extension": config }; +} +``` + +The data returned from each hook is included in the response under `extensions["my-extension"]`. + +## Further Reading + +- [x402 SDK Features](/sdk-features) β€” Extension support across TypeScript, Go, and Python +- [Extension Specs](https://github.com/coinbase/x402/tree/main/specs/extensions) β€” Protocol-level extension specifications +- [@x402/extensions package](https://github.com/coinbase/x402/tree/main/typescript/packages/extensions) β€” TypeScript implementation source diff --git a/docs/sdk-features.md b/docs/sdk-features.md index 326a5bd6da..3180b97db4 100644 --- a/docs/sdk-features.md +++ b/docs/sdk-features.md @@ -48,6 +48,7 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt | bazaar (facilitator client) | βœ… | βœ… | βœ… | | sign-in-with-x | βœ… | ❌ | ❌ | | payment-identifier | βœ… | βœ… | βœ… | +| offer-receipt | βœ… | ❌ | ❌ | ## Client Hooks From 62a4c16684a106760879191c7b4492de6de02616 Mon Sep 17 00:00:00 2001 From: phdargen Date: Tue, 17 Mar 2026 00:01:29 +0900 Subject: [PATCH 070/129] chore: version python package (#1635) --- python/x402/CHANGELOG.md | 11 +++++++++++ python/x402/changelog.d/1474.feature.md | 1 - python/x402/changelog.d/1550.bugfix.md | 1 - python/x402/pyproject.toml | 2 +- python/x402/uv.lock | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) delete mode 100644 python/x402/changelog.d/1474.feature.md delete mode 100644 python/x402/changelog.d/1550.bugfix.md diff --git a/python/x402/CHANGELOG.md b/python/x402/CHANGELOG.md index 030f8b0f4b..cf6aa58628 100644 --- a/python/x402/CHANGELOG.md +++ b/python/x402/CHANGELOG.md @@ -2,6 +2,17 @@ +## [2.4.0] - 2026-03-16 + +### Fixed + +- Fixed paywall config injection targeting causing SVG parse errors in the browser ([#1550](https://github.com/coinbase/x402/pull/1550)) + +### Added + +- Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling to prevent facilitator grieving and account for implementation dependent verifyTypedData; Enforce strict amount equality per spec in evm exact; Fix extra field passthrough in resource configs ([#1474](https://github.com/coinbase/x402/pull/1474)) + + ## [2.3.0] - 2026-03-06 ### Fixed diff --git a/python/x402/changelog.d/1474.feature.md b/python/x402/changelog.d/1474.feature.md deleted file mode 100644 index 30f8d76e9c..0000000000 --- a/python/x402/changelog.d/1474.feature.md +++ /dev/null @@ -1 +0,0 @@ -Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling to prevent facilitator grieving and account for implementation dependent verifyTypedData; Enforce strict amount equality per spec in evm exact; Fix extra field passthrough in resource configs diff --git a/python/x402/changelog.d/1550.bugfix.md b/python/x402/changelog.d/1550.bugfix.md deleted file mode 100644 index 4dfa4b1a09..0000000000 --- a/python/x402/changelog.d/1550.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Fixed paywall config injection targeting causing SVG parse errors in the browser diff --git a/python/x402/pyproject.toml b/python/x402/pyproject.toml index c23db453a3..218acc1d30 100644 --- a/python/x402/pyproject.toml +++ b/python/x402/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "x402" -version = "2.3.0" +version = "2.4.0" description = "x402 Payment Protocol SDK for Python" readme = "README.md" license = { text = "MIT" } diff --git a/python/x402/uv.lock b/python/x402/uv.lock index 37af8be178..845f4badd9 100644 --- a/python/x402/uv.lock +++ b/python/x402/uv.lock @@ -3407,7 +3407,7 @@ wheels = [ [[package]] name = "x402" -version = "2.3.0" +version = "2.4.0" source = { editable = "." } dependencies = [ { name = "nest-asyncio" }, From d8e9f3f8ab640efb03334c74c8cd1d6f7b668c32 Mon Sep 17 00:00:00 2001 From: phdargen Date: Tue, 17 Mar 2026 00:16:12 +0900 Subject: [PATCH 071/129] Simulate permit2 (#1579) * sim permit2 * add verifyTypedData failure fallback for deployed smart wallets * add go --- e2e/clients/httpx/uv.lock | 4 +- e2e/clients/mcp-python/uv.lock | 2 +- e2e/clients/requests/uv.lock | 4 +- e2e/facilitators/python/uv.lock | 4 +- e2e/pnpm-lock.yaml | 2 +- e2e/scripts/permit2-approval.ts | 29 +- e2e/servers/express/index.ts | 139 +++-- e2e/servers/express/test.config.json | 11 +- e2e/servers/fastapi/uv.lock | 4 +- e2e/servers/flask/uv.lock | 4 +- e2e/servers/gin/main.go | 49 +- e2e/servers/gin/test.config.json | 11 +- e2e/servers/hono/index.ts | 136 +++-- e2e/servers/hono/test.config.json | 11 +- e2e/servers/mcp-python/uv.lock | 2 +- .../protected-permit2-eip2612-proxy/route.ts | 14 + e2e/servers/next/proxy.ts | 29 ++ e2e/servers/next/test.config.json | 11 +- e2e/src/types.ts | 2 + e2e/test.ts | 71 ++- .../unreleased/added-20260313-141700.yaml | 3 + .../erc20approvalgassponsor/types.go | 7 + go/mechanisms/evm/constants.go | 27 + go/mechanisms/evm/exact/facilitator/errors.go | 7 + .../evm/exact/facilitator/permit2.go | 207 ++++---- .../evm/exact/facilitator/permit2_helpers.go | 317 ++++++++++++ go/mechanisms/evm/exact/facilitator/scheme.go | 6 +- go/test/unit/evm_client_facilitator_test.go | 24 +- typescript/.changeset/fifty-doodles-strive.md | 5 + .../mechanisms/evm/src/exact/extensions.ts | 1 + .../evm/src/exact/facilitator/errors.ts | 16 + .../src/exact/facilitator/permit2-utils.ts | 442 ++++++++++++++++ .../evm/src/exact/facilitator/permit2.ts | 474 +++++------------- .../evm/src/exact/facilitator/scheme.ts | 4 +- .../evm/test/unit/exact/facilitator.test.ts | 364 +++++++++++--- 35 files changed, 1774 insertions(+), 669 deletions(-) create mode 100644 e2e/servers/next/app/api/protected-permit2-eip2612-proxy/route.ts create mode 100644 go/.changes/unreleased/added-20260313-141700.yaml create mode 100644 go/mechanisms/evm/exact/facilitator/permit2_helpers.go create mode 100644 typescript/.changeset/fifty-doodles-strive.md create mode 100644 typescript/packages/mechanisms/evm/src/exact/facilitator/permit2-utils.ts diff --git a/e2e/clients/httpx/uv.lock b/e2e/clients/httpx/uv.lock index 2121a54895..06321eee76 100644 --- a/e2e/clients/httpx/uv.lock +++ b/e2e/clients/httpx/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -1907,7 +1907,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/clients/mcp-python/uv.lock b/e2e/clients/mcp-python/uv.lock index 84907b68f1..f3abfe2ca5 100644 --- a/e2e/clients/mcp-python/uv.lock +++ b/e2e/clients/mcp-python/uv.lock @@ -2137,7 +2137,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/clients/requests/uv.lock b/e2e/clients/requests/uv.lock index 11e3e49ebb..c98e27cc2b 100644 --- a/e2e/clients/requests/uv.lock +++ b/e2e/clients/requests/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -1907,7 +1907,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/facilitators/python/uv.lock b/e2e/facilitators/python/uv.lock index 569073a81f..dfb2a312d3 100644 --- a/e2e/facilitators/python/uv.lock +++ b/e2e/facilitators/python/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -2846,7 +2846,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index e3dadfcb2f..1956ed95c7 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -18780,7 +18780,7 @@ snapshots: buffer: 6.0.3 eventemitter3: 5.0.1 uuid: 8.3.2 - ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.19.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: bufferutil: 4.0.9 utf-8-validate: 5.0.10 diff --git a/e2e/scripts/permit2-approval.ts b/e2e/scripts/permit2-approval.ts index 326a757481..76b16d208a 100644 --- a/e2e/scripts/permit2-approval.ts +++ b/e2e/scripts/permit2-approval.ts @@ -8,7 +8,7 @@ * pnpm tsx scripts/permit2-approval.ts approve [tokenAddress] * pnpm tsx scripts/permit2-approval.ts revoke [tokenAddress] * - * If tokenAddress is not provided, defaults to Base Sepolia USDC. + * If tokenAddress is not provided, processes all known tokens. * * Environment variables required: * CLIENT_EVM_PRIVATE_KEY - Private key of the client wallet @@ -43,6 +43,11 @@ const TOKENS_BY_NETWORK: Record getAddress(t.address) === filterAddress) + : tokenStates; + + if (tokensToProcess.length === 0) { + const addr = filterAddress ?? 'none'; + console.error(`❌ No matching token found for address ${addr}`); + process.exit(1); + } + + let nonce = await publicClient.getTransactionCount({ address: account.address }); + if (action === 'revoke') { - for (const token of tokenStates) { + for (const token of tokensToProcess) { if (token.allowance === 0n) { console.log(`βœ… ${token.name}: Permit2 approval already revoked (allowance is 0)`); continue; @@ -153,6 +172,7 @@ Environment variables required: abi: erc20Abi, functionName: 'approve', args: [PERMIT2_ADDRESS, 0n], + nonce: nonce++, }); console.log(` πŸ“ Transaction: ${hash}`); @@ -169,7 +189,7 @@ Environment variables required: } // action === 'approve' - for (const token of tokenStates) { + for (const token of tokensToProcess) { if (token.allowance === MAX_UINT256) { console.log(`βœ… ${token.name}: Permit2 already has unlimited approval`); continue; @@ -182,6 +202,7 @@ Environment variables required: abi: erc20Abi, functionName: 'approve', args: [PERMIT2_ADDRESS, MAX_UINT256], + nonce: nonce++, }); console.log(` πŸ“ Transaction: ${hash}`); diff --git a/e2e/servers/express/index.ts b/e2e/servers/express/index.ts index 9d79bd5303..d798d8cfdb 100644 --- a/e2e/servers/express/index.ts +++ b/e2e/servers/express/index.ts @@ -166,32 +166,32 @@ app.use( }, ...(APTOS_PAYEE_ADDRESS ? { - "GET /protected-aptos": { - accepts: { - payTo: APTOS_PAYEE_ADDRESS, - scheme: "exact", - price: "$0.001", - network: APTOS_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-aptos": { + accepts: { + payTo: APTOS_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: APTOS_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"], }, - }), - }, + }, + }), }, - } + }, + } : {}), // Permit2 endpoint for ERC-20 approval gas sponsoring (no EIP-2612) "GET /protected-permit2-erc20": { @@ -211,7 +211,7 @@ app.use( ...declareErc20ApprovalGasSponsoringExtension(), }, }, - // Permit2 endpoint - explicitly requires Permit2 flow instead of EIP-3009 + // Permit2 standard/direct endpoint - no gas sponsoring, client must pre-approve Permit2 "GET /protected-permit2": { accepts: { payTo: EVM_PAYEE_ADDRESS, @@ -243,37 +243,66 @@ app.use( }, }, }), + }, + }, + // Permit2 endpoint with EIP-2612 gas sponsoring + "GET /protected-permit2-eip2612": { + accepts: { + payTo: EVM_PAYEE_ADDRESS, + scheme: "exact", + network: EVM_NETWORK, + price: "$0.001", + extra: { assetTransferMethod: "permit2" }, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Permit2 EIP-2612 endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + method: "permit2-eip2612", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + method: { type: "string" }, + }, + required: ["message", "timestamp", "method"], + }, + }, + }), ...declareEip2612GasSponsoringExtension(), }, }, ...(STELLAR_PAYEE_ADDRESS ? { - "GET /protected-stellar": { - accepts: { - payTo: STELLAR_PAYEE_ADDRESS!, - scheme: "exact", - price: "$0.001", - network: STELLAR_NETWORK, - }, - extensions: { - ...declareDiscoveryExtension({ - output: { - example: { - message: "Protected Stellar endpoint accessed successfully", - timestamp: "2024-01-01T00:00:00Z", - }, - schema: { - properties: { - message: { type: "string" }, - timestamp: { type: "string" }, - }, - required: ["message", "timestamp"], + "GET /protected-stellar": { + accepts: { + payTo: STELLAR_PAYEE_ADDRESS!, + scheme: "exact", + price: "$0.001", + network: STELLAR_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected Stellar 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 @@ -349,6 +378,19 @@ app.get("/protected-permit2", (req, res) => { }); }); +/** + * Protected Permit2 EIP-2612 endpoint - requires payment via Permit2 with gas sponsoring + * + * Uses EIP-2612 permit atomically in settleWithPermit. No pre-approval needed. + */ +app.get("/protected-permit2-eip2612", (req, res) => { + res.json({ + message: "Permit2 EIP-2612 endpoint accessed successfully", + timestamp: new Date().toISOString(), + method: "permit2-eip2612", + }); +}); + /** * Protected Stellar endpoint - requires payment to access * @@ -414,7 +456,8 @@ app.listen(parseInt(PORT), () => { β•‘ β€’ GET /protected (EIP-3009 payment - EVM) β•‘ β•‘ β€’ GET /protected-svm (SVM payment) β•‘ β•‘ β€’ GET /protected-aptos (Aptos payment) β•‘ -β•‘ β€’ GET /protected-permit2 (Permit2 payment - EVM) β•‘ +β•‘ β€’ GET /protected-permit2 (Permit2 direct - EVM) β•‘ +β•‘ β€’ GET /protected-permit2-eip2612 (Permit2 + EIP-2612) β•‘ β•‘ β€’ GET /protected-permit2-erc20 (Permit2 + ERC-20 approval) β•‘ β•‘ β€’ GET /protected-stellar (Stellar payment) β•‘ β•‘ β€’ GET /health (no payment required) β•‘ diff --git a/e2e/servers/express/test.config.json b/e2e/servers/express/test.config.json index 4f2cd84042..7e40f93fb7 100644 --- a/e2e/servers/express/test.config.json +++ b/e2e/servers/express/test.config.json @@ -16,7 +16,16 @@ { "path": "/protected-permit2", "method": "GET", - "description": "Protected endpoint requiring Permit2 payment", + "description": "Protected endpoint requiring Permit2 payment (standard settle, no gas sponsoring)", + "requiresPayment": true, + "protocolFamily": "evm", + "transferMethod": "permit2", + "permit2Direct": true + }, + { + "path": "/protected-permit2-eip2612", + "method": "GET", + "description": "Protected endpoint requiring Permit2 payment with EIP-2612 gas sponsoring", "requiresPayment": true, "protocolFamily": "evm", "transferMethod": "permit2" diff --git a/e2e/servers/fastapi/uv.lock b/e2e/servers/fastapi/uv.lock index fc87dfbe5b..3be86207ce 100644 --- a/e2e/servers/fastapi/uv.lock +++ b/e2e/servers/fastapi/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -2841,7 +2841,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/servers/flask/uv.lock b/e2e/servers/flask/uv.lock index 34f4b66b19..73fe48d97f 100644 --- a/e2e/servers/flask/uv.lock +++ b/e2e/servers/flask/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -2072,7 +2072,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/servers/gin/main.go b/e2e/servers/gin/main.go index 9264df11d8..b413d59d61 100644 --- a/e2e/servers/gin/main.go +++ b/e2e/servers/gin/main.go @@ -148,8 +148,28 @@ func main() { types.BAZAAR.Key(): discoveryExtension, }, }, + // Permit2 direct endpoint - standard settle, no gas sponsoring (client must pre-approve Permit2) + "GET /protected-permit2": { + Accepts: x402http.PaymentOptions{ + { + Scheme: "exact", + PayTo: evmPayeeAddress, + Network: evmNetwork, + Price: map[string]interface{}{ + "amount": "1000", + "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", + "extra": map[string]interface{}{ + "assetTransferMethod": "permit2", + }, + }, + }, + }, + Extensions: map[string]interface{}{ + types.BAZAAR.Key(): discoveryExtension, + }, + }, // Permit2 endpoint - explicitly requires Permit2 flow instead of EIP-3009 - "GET /protected-permit2": { + "GET /protected-permit2-eip2612": { Accepts: x402http.PaymentOptions{ { Scheme: "exact", @@ -280,10 +300,7 @@ func main() { }) /** - * Protected Permit2 endpoint - requires payment via Permit2 flow - * - * This endpoint demonstrates the Permit2 payment flow. - * Clients must have approved Permit2 to spend their USDC before accessing. + * Protected Permit2 direct endpoint - standard settle (no gas sponsoring) */ r.GET("/protected-permit2", func(c *ginfw.Context) { if shutdownRequested { @@ -300,6 +317,25 @@ func main() { }) }) + /** + * Protected Permit2 EIP-2612 endpoint - requires payment via Permit2 with gas sponsoring. + * Uses EIP-2612 permit atomically in settleWithPermit. No pre-approval needed. + */ + r.GET("/protected-permit2-eip2612", func(c *ginfw.Context) { + if shutdownRequested { + c.JSON(http.StatusServiceUnavailable, ginfw.H{ + "error": "Server shutting down", + }) + return + } + + c.JSON(http.StatusOK, ginfw.H{ + "message": "Permit2 EIP-2612 endpoint accessed successfully", + "timestamp": time.Now().Format(time.RFC3339), + "method": "permit2-eip2612", + }) + }) + /** * Protected Permit2 ERC-20 approval endpoint - requires payment via Permit2 flow * using a generic ERC-20 token that does NOT support EIP-2612. @@ -380,7 +416,8 @@ func main() { β•‘ Endpoints: β•‘ β•‘ β€’ GET /protected (EIP-3009 payment) β•‘ β•‘ β€’ GET /protected-svm (SVM payment) β•‘ -β•‘ β€’ GET /protected-permit2 (Permit2 payment) β•‘ +β•‘ β€’ GET /protected-permit2 (Permit2 - EVM) β•‘ +β•‘ β€’ GET /protected-permit2-eip2612 (Permit2 + EIP-2612)β•‘ β•‘ β€’ GET /protected-permit2-erc20 (Permit2 ERC-20) β•‘ β•‘ β€’ GET /health (no payment required) β•‘ β•‘ β€’ POST /close (shutdown server) β•‘ diff --git a/e2e/servers/gin/test.config.json b/e2e/servers/gin/test.config.json index 055a3b04bc..86fba7c340 100644 --- a/e2e/servers/gin/test.config.json +++ b/e2e/servers/gin/test.config.json @@ -21,7 +21,16 @@ { "path": "/protected-permit2", "method": "GET", - "description": "Protected endpoint requiring Permit2 payment", + "description": "Protected endpoint requiring Permit2 payment (standard settle, no gas sponsoring)", + "requiresPayment": true, + "protocolFamily": "evm", + "transferMethod": "permit2", + "permit2Direct": true + }, + { + "path": "/protected-permit2-eip2612", + "method": "GET", + "description": "Protected endpoint requiring Permit2 payment with EIP-2612 gas sponsoring", "requiresPayment": true, "protocolFamily": "evm", "transferMethod": "permit2" diff --git a/e2e/servers/hono/index.ts b/e2e/servers/hono/index.ts index 531747be38..bf8434d56f 100644 --- a/e2e/servers/hono/index.ts +++ b/e2e/servers/hono/index.ts @@ -171,32 +171,32 @@ app.use( }, ...(APTOS_PAYEE_ADDRESS ? { - "GET /protected-aptos": { - accepts: { - payTo: APTOS_PAYEE_ADDRESS, - scheme: "exact", - price: "$0.001", - network: APTOS_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-aptos": { + accepts: { + payTo: APTOS_PAYEE_ADDRESS, + scheme: "exact", + price: "$0.001", + network: APTOS_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-permit2": { accepts: { @@ -229,6 +229,35 @@ app.use( }, }, }), + }, + }, + "GET /protected-permit2-eip2612": { + accepts: { + payTo: EVM_PAYEE_ADDRESS, + scheme: "exact", + network: EVM_NETWORK, + price: "$0.001", + // Use pre-parsed price with assetTransferMethod to force Permit2 + extra: { assetTransferMethod: "permit2" }, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Permit2 EIP-2612 endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + method: "permit2-eip2612", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + method: { type: "string" }, + }, + required: ["message", "timestamp", "method"], + }, + }, + }), ...declareEip2612GasSponsoringExtension(), }, }, @@ -251,32 +280,32 @@ app.use( }, ...(STELLAR_PAYEE_ADDRESS ? { - "GET /protected-stellar": { - accepts: { - payTo: STELLAR_PAYEE_ADDRESS!, - scheme: "exact", - price: "$0.001", - network: STELLAR_NETWORK, - }, - extensions: { - ...declareDiscoveryExtension({ - output: { - example: { - message: "Protected Stellar endpoint accessed successfully", - timestamp: "2024-01-01T00:00:00Z", - }, - schema: { - properties: { - message: { type: "string" }, - timestamp: { type: "string" }, - }, - required: ["message", "timestamp"], + "GET /protected-stellar": { + accepts: { + payTo: STELLAR_PAYEE_ADDRESS!, + scheme: "exact", + price: "$0.001", + network: STELLAR_NETWORK, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Protected Stellar endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, }, + required: ["message", "timestamp"], }, - }), - }, + }, + }), }, - } + }, + } : {}), }, x402Server, // Pass pre-configured server instance @@ -324,7 +353,7 @@ app.get("/protected-aptos", c => { }); /** - * Protected Permit2 endpoint - requires Permit2 payment with EIP-2612 gas sponsoring + * Protected Permit2 endpoint - standard settle (no gas sponsoring) */ app.get("/protected-permit2", c => { return c.json({ @@ -335,6 +364,16 @@ app.get("/protected-permit2", c => { }); /** + * Protected Permit2 EIP-2612 endpoint - requires Permit2 with gas sponsoring + */ +app.get("/protected-permit2-eip2612", c => { + return c.json({ + message: "Permit2 EIP-2612 endpoint accessed successfully", + timestamp: new Date().toISOString(), + method: "permit2-eip2612", + }); +}); + /** * Protected Permit2 ERC-20 endpoint - requires Permit2 payment with ERC-20 approval gas sponsoring */ @@ -414,7 +453,8 @@ console.log(` β•‘ β•‘ β•‘ Endpoints: β•‘ β•‘ β€’ GET /protected (EIP-3009 payment) β•‘ -β•‘ β€’ GET /protected-permit2 (Permit2 + EIP-2612) β•‘ +β•‘ β€’ GET /protected-permit2 (Permit2 - EVM) β•‘ +β•‘ β€’ GET /protected-permit2-eip2612 (Permit2 + EIP-2612) β•‘ β•‘ β€’ GET /protected-permit2-erc20 (Permit2 + ERC-20 approval)β•‘ β•‘ β€’ GET /protected-svm (SVM payment) β•‘ β•‘ β€’ GET /protected-aptos (Aptos payment) β•‘ diff --git a/e2e/servers/hono/test.config.json b/e2e/servers/hono/test.config.json index be39d73b3d..6ef7ea12db 100644 --- a/e2e/servers/hono/test.config.json +++ b/e2e/servers/hono/test.config.json @@ -16,7 +16,16 @@ { "path": "/protected-permit2", "method": "GET", - "description": "Protected endpoint requiring Permit2 payment", + "description": "Protected endpoint requiring Permit2 payment (standard settle, no gas sponsoring)", + "requiresPayment": true, + "protocolFamily": "evm", + "transferMethod": "permit2", + "permit2Direct": true + }, + { + "path": "/protected-permit2-eip2612", + "method": "GET", + "description": "Protected endpoint requiring Permit2 payment with EIP-2612 gas sponsoring", "requiresPayment": true, "protocolFamily": "evm", "transferMethod": "permit2" diff --git a/e2e/servers/mcp-python/uv.lock b/e2e/servers/mcp-python/uv.lock index 0ca9a78b4d..37c6b8cdbf 100644 --- a/e2e/servers/mcp-python/uv.lock +++ b/e2e/servers/mcp-python/uv.lock @@ -2137,7 +2137,7 @@ wheels = [ [[package]] name = "x402" -version = "2.2.0" +version = "2.3.0" source = { editable = "../../../python/x402" } dependencies = [ { name = "nest-asyncio" }, diff --git a/e2e/servers/next/app/api/protected-permit2-eip2612-proxy/route.ts b/e2e/servers/next/app/api/protected-permit2-eip2612-proxy/route.ts new file mode 100644 index 0000000000..868e3cff6f --- /dev/null +++ b/e2e/servers/next/app/api/protected-permit2-eip2612-proxy/route.ts @@ -0,0 +1,14 @@ +import { NextResponse } from "next/server"; + +/** + * Protected Permit2 EIP-2612 endpoint requiring payment (proxy middleware) + */ +export const runtime = "nodejs"; + +export async function GET() { + return NextResponse.json({ + message: "Permit2 EIP-2612 endpoint accessed successfully", + timestamp: new Date().toISOString(), + method: "permit2-eip2612", + }); +} diff --git a/e2e/servers/next/proxy.ts b/e2e/servers/next/proxy.ts index 83bb44e1d8..ab34be83c8 100644 --- a/e2e/servers/next/proxy.ts +++ b/e2e/servers/next/proxy.ts @@ -190,6 +190,34 @@ export const proxy = paymentProxy( }, }, }), + }, + }, + "/api/protected-permit2-eip2612-proxy": { + accepts: { + payTo: EVM_PAYEE_ADDRESS, + scheme: "exact", + network: EVM_NETWORK, + price: "$0.001", + extra: { assetTransferMethod: "permit2" }, + }, + extensions: { + ...declareDiscoveryExtension({ + output: { + example: { + message: "Permit2 EIP-2612 endpoint accessed successfully", + timestamp: "2024-01-01T00:00:00Z", + method: "permit2-eip2612", + }, + schema: { + properties: { + message: { type: "string" }, + timestamp: { type: "string" }, + method: { type: "string" }, + }, + required: ["message", "timestamp", "method"], + }, + }, + }), ...declareEip2612GasSponsoringExtension(), }, }, @@ -221,6 +249,7 @@ export const config = { "/api/protected-aptos-proxy", "/api/protected-stellar-proxy", "/api/protected-permit2-proxy", + "/api/protected-permit2-eip2612-proxy", "/api/protected-permit2-erc20-proxy", ], }; diff --git a/e2e/servers/next/test.config.json b/e2e/servers/next/test.config.json index 0e984768ac..4021bf3012 100644 --- a/e2e/servers/next/test.config.json +++ b/e2e/servers/next/test.config.json @@ -16,7 +16,16 @@ { "path": "/api/protected-permit2-proxy", "method": "GET", - "description": "Protected Permit2 endpoint using proxy middleware", + "description": "Protected Permit2 direct endpoint (standard settle, no gas sponsoring)", + "requiresPayment": true, + "protocolFamily": "evm", + "transferMethod": "permit2", + "permit2Direct": true + }, + { + "path": "/api/protected-permit2-eip2612-proxy", + "method": "GET", + "description": "Protected Permit2 EIP-2612 endpoint using proxy middleware", "requiresPayment": true, "protocolFamily": "evm", "transferMethod": "permit2" diff --git a/e2e/src/types.ts b/e2e/src/types.ts index 6d893d302f..71e7744302 100644 --- a/e2e/src/types.ts +++ b/e2e/src/types.ts @@ -53,6 +53,8 @@ export interface TestEndpoint { protocolFamily?: ProtocolFamily; transferMethod?: TransferMethod; extensions?: string[]; + /** True for Permit2 standard/direct settle - requires pre-approval (approve before test, not revoke) */ + permit2Direct?: boolean; health?: boolean; close?: boolean; } diff --git a/e2e/test.ts b/e2e/test.ts index d8ba95d189..dd46c65a47 100644 --- a/e2e/test.ts +++ b/e2e/test.ts @@ -15,6 +15,60 @@ import { Semaphore, FacilitatorLock } from './src/concurrency'; import { FacilitatorManager } from './src/facilitators/facilitator-manager'; import { waitForHealth } from './src/health'; +// Base Sepolia token addresses used by permit2 E2E tests +const USDC_BASE_SEPOLIA = '0x036CbD53842c5426634e7929541eC2318f3dCF7e'; +const MOCK_ERC20_BASE_SEPOLIA = '0xeED520980fC7C7B4eB379B96d61CEdea2423005a'; + +/** + * Approve Permit2 so that the standard/direct settle path can be exercised. + * Grants unlimited Permit2 allowance for the given token (or USDC by default). + */ +async function approvePermit2Approval(tokenAddress?: string): Promise { + return new Promise((resolve) => { + const label = tokenAddress ? `token ${tokenAddress}` : 'USDC (default)'; + verboseLog(` πŸ”“ Approving Permit2 for ${label}...`); + + const args = ['scripts/permit2-approval.ts', 'approve']; + if (tokenAddress) { + args.push(tokenAddress); + } + const child = spawn('tsx', args, { + cwd: process.cwd(), + stdio: 'pipe', + shell: true, + }); + + let stderr = ''; + + child.stdout?.on('data', (data) => { + verboseLog(data.toString().trim()); + }); + + child.stderr?.on('data', (data) => { + stderr += data.toString(); + verboseLog(data.toString().trim()); + }); + + child.on('close', (code) => { + if (code === 0) { + verboseLog(' βœ… Permit2 approval granted'); + resolve(true); + } else { + errorLog(` ❌ Permit2 approve failed (exit code ${code})`); + if (stderr) { + errorLog(` Error: ${stderr}`); + } + resolve(false); + } + }); + + child.on('error', (error) => { + errorLog(` ❌ Failed to run Permit2 approve: ${error.message}`); + resolve(false); + }); + }); +} + /** * Revoke Permit2 approval so that gas sponsoring extensions are exercised. * Sets the Permit2 allowance to 0 for the given token (or USDC by default), @@ -323,12 +377,14 @@ async function runTest() { if (evmScenarios.length > 0) { const hasEip3009 = evmScenarios.some(s => (s.endpoint.transferMethod || 'eip3009') === 'eip3009'); const hasPermit2 = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2'); - const hasPermit2Eip2612 = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2' && !s.endpoint.extensions?.includes('erc20ApprovalGasSponsoring')); + const hasPermit2Direct = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2' && s.endpoint.permit2Direct === true); + const hasPermit2Eip2612 = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2' && !s.endpoint.extensions?.includes('erc20ApprovalGasSponsoring') && !s.endpoint.permit2Direct); const hasPermit2Erc20 = evmScenarios.some(s => s.endpoint.transferMethod === 'permit2' && s.endpoint.extensions?.includes('erc20ApprovalGasSponsoring')); log('πŸ” EVM Branch Coverage Check:'); log(` EIP-3009 route: ${hasEip3009 ? 'βœ…' : '❌ MISSING'}`); log(` Permit2 route: ${hasPermit2 ? 'βœ…' : '❌ MISSING'}`); + log(` Permit2+direct settle: ${hasPermit2Direct ? 'βœ…' : '⚠️ not found'}`); log(` Permit2+EIP2612 route: ${hasPermit2Eip2612 ? 'βœ…' : '⚠️ not found (may be covered by permit2 route if eip2612 extension enabled)'}`); log(` Permit2+ERC20 route: ${hasPermit2Erc20 ? 'βœ…' : '⚠️ not found'}`); log(''); @@ -340,7 +396,7 @@ async function runTest() { ); if (hasPermit2Scenarios) { - log('πŸ” Permit2 scenarios detected β€” approval will be revoked before each test to exercise extension paths'); + log('πŸ” Permit2 scenarios detected β€” revoke before gas-sponsored tests, approve before permit2-direct tests'); } // Collect unique facilitators and servers @@ -645,8 +701,15 @@ async function runTest() { const isEvm = scenario.protocolFamily === 'evm'; if (scenario.endpoint.transferMethod === 'permit2') { - await revokePermit2Approval(); - await revokePermit2Approval('0xeED520980fC7C7B4eB379B96d61CEdea2423005a'); + if (scenario.endpoint.permit2Direct) { + await approvePermit2Approval(USDC_BASE_SEPOLIA); + } else { + const token = + scenario.endpoint.extensions?.includes('erc20ApprovalGasSponsoring') + ? MOCK_ERC20_BASE_SEPOLIA + : USDC_BASE_SEPOLIA; + await revokePermit2Approval(token); + } } if (isEvm && facilitatorName && evmLock) { diff --git a/go/.changes/unreleased/added-20260313-141700.yaml b/go/.changes/unreleased/added-20260313-141700.yaml new file mode 100644 index 0000000000..a309dad93b --- /dev/null +++ b/go/.changes/unreleased/added-20260313-141700.yaml @@ -0,0 +1,3 @@ +kind: added +body: Added simulation to permit2 verify and (optional) settle +time: 2026-03-13T14:17:00.280905+09:00 diff --git a/go/extensions/erc20approvalgassponsor/types.go b/go/extensions/erc20approvalgassponsor/types.go index 72bcaff908..a62d049f51 100644 --- a/go/extensions/erc20approvalgassponsor/types.go +++ b/go/extensions/erc20approvalgassponsor/types.go @@ -78,6 +78,13 @@ type Erc20ApprovalGasSponsoringSigner interface { SendTransactions(ctx context.Context, transactions []TransactionRequest) ([]string, error) } +// Erc20ApprovalGasSponsoringSimulator is an optional extension of Erc20ApprovalGasSponsoringSigner with multi-transaction simulation. +// The signer owns the simulation strategy. +type Erc20ApprovalGasSponsoringSimulator interface { + Erc20ApprovalGasSponsoringSigner + SimulateTransactions(ctx context.Context, transactions []TransactionRequest) (bool, error) +} + // Erc20ApprovalFacilitatorExtension carries the signer; registered with the facilitator. // It implements x402.FacilitatorExtension so it can be registered and retrieved via FacilitatorContext. type Erc20ApprovalFacilitatorExtension struct { diff --git a/go/mechanisms/evm/constants.go b/go/mechanisms/evm/constants.go index 005bbd9b09..cf65a3c57b 100644 --- a/go/mechanisms/evm/constants.go +++ b/go/mechanisms/evm/constants.go @@ -60,6 +60,9 @@ const ( // ERC20ApproveGasLimit is the gas limit for a standard ERC-20 approve() transaction. ERC20ApproveGasLimit = 70000 + + // DefaultMaxFeePerGas is the fallback max fee per gas (1 gwei) for gas cost estimation. + DefaultMaxFeePerGas = 1_000_000_000 ) var ( @@ -312,6 +315,30 @@ var ( } ]`) + // X402ExactPermit2ProxyPermit2ABI for verifying proxy deployment + X402ExactPermit2ProxyPermit2ABI = []byte(`[ + { + "inputs": [], + "name": "PERMIT2", + "outputs": [{"name": "", "type": "address"}], + "stateMutability": "view", + "type": "function" + } + ]`) + + // Multicall3GetEthBalanceABI for querying native ETH balance via Multicall3. + Multicall3GetEthBalanceABI = []byte(`[ + { + "inputs": [ + {"name": "addr", "type": "address"} + ], + "name": "getEthBalance", + "outputs": [{"name": "balance", "type": "uint256"}], + "stateMutability": "view", + "type": "function" + } + ]`) + // EIP2612NoncesABI for querying EIP-2612 nonces EIP2612NoncesABI = []byte(`[ { diff --git a/go/mechanisms/evm/exact/facilitator/errors.go b/go/mechanisms/evm/exact/facilitator/errors.go index a22119ac5a..d73d15953f 100644 --- a/go/mechanisms/evm/exact/facilitator/errors.go +++ b/go/mechanisms/evm/exact/facilitator/errors.go @@ -58,6 +58,13 @@ const ( ErrPermit2InvalidNonce = "permit2_invalid_nonce" ErrPermit2612AmountMismatch = "permit2_2612_amount_mismatch" + // Permit2 simulation errors + ErrPermit2SimulationFailed = "permit2_simulation_failed" + ErrPermit2InsufficientBalance = "permit2_insufficient_balance" + ErrPermit2ProxyNotDeployed = "permit2_proxy_not_deployed" + ErrErc20ApprovalInsufficientEth = "erc20_approval_insufficient_eth_for_gas" + ErrErc20ApprovalTxFailed = "erc20_approval_tx_failed" + // ERC-20 approval gas sponsoring errors ErrErc20ApprovalInvalidFormat = "invalid_erc20_approval_extension_format" ErrErc20ApprovalFromMismatch = "erc20_approval_from_mismatch" diff --git a/go/mechanisms/evm/exact/facilitator/permit2.go b/go/mechanisms/evm/exact/facilitator/permit2.go index 77ddc5fcf0..25a7f19784 100644 --- a/go/mechanisms/evm/exact/facilitator/permit2.go +++ b/go/mechanisms/evm/exact/facilitator/permit2.go @@ -7,8 +7,6 @@ import ( "strings" "time" - "github.com/ethereum/go-ethereum/common" - x402 "github.com/coinbase/x402/go" "github.com/coinbase/x402/go/extensions/eip2612gassponsor" "github.com/coinbase/x402/go/extensions/erc20approvalgassponsor" @@ -16,6 +14,19 @@ import ( "github.com/coinbase/x402/go/types" ) +// VerifyPermit2Options controls optional behaviour for VerifyPermit2. +type VerifyPermit2Options struct { + // Simulate enables onchain simulation. Defaults to true when zero-value. + Simulate *bool +} + +func (o *VerifyPermit2Options) shouldSimulate() bool { + if o == nil || o.Simulate == nil { + return true + } + return *o.Simulate +} + // VerifyPermit2 verifies a Permit2 payment payload. func VerifyPermit2( ctx context.Context, @@ -24,6 +35,7 @@ func VerifyPermit2( requirements types.PaymentRequirements, permit2Payload *evm.ExactPermit2Payload, facilCtx *x402.FacilitatorContext, + opts *VerifyPermit2Options, ) (*x402.VerifyResponse, error) { payer := permit2Payload.Permit2Authorization.From @@ -60,8 +72,7 @@ func VerifyPermit2( if !ok { return nil, x402.NewVerifyError(ErrInvalidPayload, payer, "invalid deadline format") } - deadlineThreshold := big.NewInt(now + evm.Permit2DeadlineBuffer) - if deadline.Cmp(deadlineThreshold) < 0 { + if deadline.Cmp(big.NewInt(now+evm.Permit2DeadlineBuffer)) < 0 { return nil, x402.NewVerifyError(ErrPermit2DeadlineExpired, payer, "deadline expired") } @@ -70,8 +81,7 @@ func VerifyPermit2( if !ok { return nil, x402.NewVerifyError(ErrInvalidPayload, payer, "invalid validAfter format") } - nowBig := big.NewInt(now) - if validAfter.Cmp(nowBig) > 0 { + if validAfter.Cmp(big.NewInt(now)) > 0 { return nil, x402.NewVerifyError(ErrPermit2NotYetValid, payer, "not yet valid") } @@ -99,55 +109,38 @@ func VerifyPermit2( return nil, x402.NewVerifyError(ErrInvalidSignatureFormat, payer, err.Error()) } - valid, err := verifyPermit2Signature(ctx, signer, permit2Payload.Permit2Authorization, signatureBytes, chainID) - if err != nil || !valid { - return nil, x402.NewVerifyError(ErrPermit2InvalidSignature, payer, "invalid signature") - } - - needsExtension := true - allowance, allowanceErr := signer.ReadContract(ctx, tokenAddress, evm.ERC20AllowanceABI, "allowance", - common.HexToAddress(payer), common.HexToAddress(evm.PERMIT2Address)) - if allowanceErr == nil { - if allowanceBig, ok := allowance.(*big.Int); ok && allowanceBig.Cmp(requiredAmount) >= 0 { - needsExtension = false - } - } - - if needsExtension { - if extErr := verifyPermit2Extensions(payload, payer, tokenAddress, facilCtx); extErr != nil { - return nil, extErr + sigValid, sigErr := verifyPermit2Signature(ctx, signer, permit2Payload.Permit2Authorization, signatureBytes, chainID) + if sigErr != nil || !sigValid { + // Check if payer is a deployed smart contract + // ERC-1271 signatures may not be verifiable by all signer implementations + code, codeErr := signer.GetCode(ctx, payer) + if codeErr != nil || len(code) == 0 { + return nil, x402.NewVerifyError(ErrPermit2InvalidSignature, payer, "invalid signature") } + // Deployed smart contract: fall through to simulation } - // Check balance - balance, err := signer.GetBalance(ctx, payer, tokenAddress) - if err == nil && balance.Cmp(requiredAmount) < 0 { - return nil, x402.NewVerifyError(ErrInsufficientBalance, payer, "insufficient balance") + // Early return when simulation is disabled + if !opts.shouldSimulate() { + return &x402.VerifyResponse{IsValid: true, Payer: payer}, nil } - return &x402.VerifyResponse{ - IsValid: true, - Payer: payer, - }, nil -} - -// verifyPermit2Extensions validates gas-sponsoring extensions when Permit2 allowance -// is insufficient or could not be read. Returns nil if a valid extension is found, -// or a VerifyError if none are present/valid. -func verifyPermit2Extensions( - payload types.PaymentPayload, - payer string, - tokenAddress string, - facilCtx *x402.FacilitatorContext, -) error { + // EIP-2612 gas sponsoring (atomic settleWithPermit via contract) eip2612Info, _ := eip2612gassponsor.ExtractEip2612GasSponsoringInfo(payload.Extensions) if eip2612Info != nil { if validErr := validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); validErr != "" { - return x402.NewVerifyError(validErr, payer, "eip2612 validation failed") + return nil, x402.NewVerifyError(validErr, payer, "eip2612 validation failed") + } + + simOk, simErr := SimulatePermit2SettleWithPermit(ctx, signer, permit2Payload, eip2612Info.Signature, eip2612Info.Amount, eip2612Info.Deadline) + if simErr != nil || !simOk { + resp := DiagnosePermit2SimulationFailure(ctx, signer, tokenAddress, permit2Payload, requirements.Amount) + return nil, x402.NewVerifyError(resp.InvalidReason, payer, "simulation failed") } - return nil + return &x402.VerifyResponse{IsValid: true, Payer: payer}, nil } + // ERC-20 approval gas sponsoring erc20Info, _ := erc20approvalgassponsor.ExtractInfo(payload.Extensions) if erc20Info != nil && facilCtx != nil { ext, ok := facilCtx.GetExtension(erc20approvalgassponsor.ERC20ApprovalGasSponsoring.Key()).(*erc20approvalgassponsor.Erc20ApprovalFacilitatorExtension) @@ -155,15 +148,57 @@ func verifyPermit2Extensions( if ok && ext != nil { extensionSigner = ext.ResolveSigner(payload.Accepted.Network) } + if extensionSigner != nil { if reason, msg := ValidateErc20ApprovalForPayment(erc20Info, payer, tokenAddress); reason != "" { - return x402.NewVerifyError(reason, payer, msg) + return nil, x402.NewVerifyError(reason, payer, msg) + } + + // If the signer supports SimulateTransactions, use it for the approve+settle bundle + if simulator, ok := extensionSigner.(erc20approvalgassponsor.Erc20ApprovalGasSponsoringSimulator); ok { + simArgs, buildErr := BuildPermit2SettleArgs(permit2Payload) + if buildErr == nil { + simOk, simErr := simulator.SimulateTransactions(ctx, []erc20approvalgassponsor.TransactionRequest{ + {Serialized: erc20Info.SignedTransaction}, + {Call: &erc20approvalgassponsor.WriteContractCall{ + Address: evm.X402ExactPermit2ProxyAddress, + ABI: evm.X402ExactPermit2ProxySettleABI, + Function: evm.FunctionSettle, + Args: []interface{}{simArgs.permitStruct(), simArgs.Owner, simArgs.witnessStruct(), simArgs.Signature}, + }}, + }) + if simErr == nil && simOk { + return &x402.VerifyResponse{IsValid: true, Payer: payer}, nil + } + } + resp := DiagnosePermit2SimulationFailure(ctx, signer, tokenAddress, permit2Payload, requirements.Amount) + return nil, x402.NewVerifyError(resp.InvalidReason, payer, "simulation failed") } - return nil + + // Fallback: signer does not support simulation; check prerequisites only + prereqResp := CheckPermit2Prerequisites(ctx, signer, tokenAddress, payer, requirements.Amount) + if !prereqResp.IsValid { + return nil, x402.NewVerifyError(prereqResp.InvalidReason, payer, "prerequisites check failed") + } + return &x402.VerifyResponse{IsValid: true, Payer: payer}, nil } } - return x402.NewVerifyError(ErrPermit2AllowanceRequired, payer, "permit2 allowance required") + // Standard settle (allowance already on-chain) + simOk, simErr := SimulatePermit2Settle(ctx, signer, permit2Payload) + if simErr != nil || !simOk { + resp := DiagnosePermit2SimulationFailure(ctx, signer, tokenAddress, permit2Payload, requirements.Amount) + return nil, x402.NewVerifyError(resp.InvalidReason, payer, "simulation failed") + } + + return &x402.VerifyResponse{IsValid: true, Payer: payer}, nil +} + +// Permit2FacilitatorConfig holds optional settlement-time configuration. +type Permit2FacilitatorConfig struct { + // SimulateInSettle re-runs simulation during settle + // When false (default), the settle path skips simulation since verify already ran it + SimulateInSettle bool } // SettlePermit2 settles a Permit2 payment by calling x402ExactPermit2Proxy.settle(). @@ -174,12 +209,17 @@ func SettlePermit2( requirements types.PaymentRequirements, permit2Payload *evm.ExactPermit2Payload, facilCtx *x402.FacilitatorContext, + config *Permit2FacilitatorConfig, ) (*x402.SettleResponse, error) { network := x402.Network(payload.Accepted.Network) payer := permit2Payload.Permit2Authorization.From - // Re-verify before settling - verifyResp, err := VerifyPermit2(ctx, signer, payload, requirements, permit2Payload, facilCtx) + simulate := false + if config != nil { + simulate = config.SimulateInSettle + } + + verifyResp, err := VerifyPermit2(ctx, signer, payload, requirements, permit2Payload, facilCtx, &VerifyPermit2Options{Simulate: &simulate}) if err != nil { ve := &x402.VerifyError{} if errors.As(err, &ve) { @@ -188,56 +228,13 @@ func SettlePermit2( return nil, x402.NewSettleError(ErrVerificationFailed, payer, network, "", err.Error()) } - // Parse values for contract call (validated during verify, but check again for safety) - amount, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Permitted.Amount, 10) - if !ok { - return nil, x402.NewSettleError(ErrInvalidPayload, payer, network, "", "invalid permitted amount") - } - nonce, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Nonce, 10) - if !ok { - return nil, x402.NewSettleError(ErrInvalidPayload, payer, network, "", "invalid nonce") - } - deadline, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Deadline, 10) - if !ok { - return nil, x402.NewSettleError(ErrInvalidPayload, payer, network, "", "invalid deadline") - } - validAfter, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Witness.ValidAfter, 10) - if !ok { - return nil, x402.NewSettleError(ErrInvalidPayload, payer, network, "", "invalid validAfter") - } - signatureBytes, err := evm.HexToBytes(permit2Payload.Signature) - if err != nil { - return nil, x402.NewSettleError(ErrInvalidSignatureFormat, payer, network, "", "invalid signature format") - } - - // Create struct args for the settle call - // The ABI expects: settle(permit, owner, witness, signature) - permitStruct := struct { - Permitted struct { - Token common.Address - Amount *big.Int - } - Nonce *big.Int - Deadline *big.Int - }{ - Permitted: struct { - Token common.Address - Amount *big.Int - }{ - Token: common.HexToAddress(permit2Payload.Permit2Authorization.Permitted.Token), - Amount: amount, - }, - Nonce: nonce, - Deadline: deadline, + args, buildErr := BuildPermit2SettleArgs(permit2Payload) + if buildErr != nil { + return nil, x402.NewSettleError(ErrInvalidPayload, payer, network, "", buildErr.Error()) } - witnessStruct := struct { - To common.Address - ValidAfter *big.Int - }{ - To: common.HexToAddress(permit2Payload.Permit2Authorization.Witness.To), - ValidAfter: validAfter, - } + permitStruct := args.permitStruct() + witnessStruct := args.witnessStruct() eip2612Info, _ := eip2612gassponsor.ExtractEip2612GasSponsoringInfo(payload.Extensions) erc20Info, _ := erc20approvalgassponsor.ExtractInfo(payload.Extensions) @@ -282,10 +279,11 @@ func SettlePermit2( evm.FunctionSettleWithPermit, permit2612Struct, permitStruct, - common.HexToAddress(payer), + args.Owner, witnessStruct, - signatureBytes, + args.Signature, ) + case erc20Info != nil && facilCtx != nil: // Branch: ERC-20 approval gas sponsoring (broadcast approval + settle via extension signer) ext, ok := facilCtx.GetExtension(erc20approvalgassponsor.ERC20ApprovalGasSponsoring.Key()).(*erc20approvalgassponsor.Erc20ApprovalFacilitatorExtension) @@ -298,7 +296,7 @@ func SettlePermit2( Address: evm.X402ExactPermit2ProxyAddress, ABI: evm.X402ExactPermit2ProxySettleABI, Function: evm.FunctionSettle, - Args: []interface{}{permitStruct, common.HexToAddress(payer), witnessStruct, signatureBytes}, + Args: []interface{}{permitStruct, args.Owner, witnessStruct, args.Signature}, } txHashes, sendErr := extensionSigner.SendTransactions(ctx, []erc20approvalgassponsor.TransactionRequest{ {Serialized: erc20Info.SignedTransaction}, @@ -316,11 +314,12 @@ func SettlePermit2( evm.X402ExactPermit2ProxySettleABI, evm.FunctionSettle, permitStruct, - common.HexToAddress(payer), + args.Owner, witnessStruct, - signatureBytes, + args.Signature, ) } + default: txHash, err = signer.WriteContract( ctx, @@ -328,9 +327,9 @@ func SettlePermit2( evm.X402ExactPermit2ProxySettleABI, evm.FunctionSettle, permitStruct, - common.HexToAddress(payer), + args.Owner, witnessStruct, - signatureBytes, + args.Signature, ) } diff --git a/go/mechanisms/evm/exact/facilitator/permit2_helpers.go b/go/mechanisms/evm/exact/facilitator/permit2_helpers.go new file mode 100644 index 0000000000..5bf5abd046 --- /dev/null +++ b/go/mechanisms/evm/exact/facilitator/permit2_helpers.go @@ -0,0 +1,317 @@ +package facilitator + +import ( + "context" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/mechanisms/evm" +) + +// Permit2SettleArgs holds the parsed and typed arguments for settle() / settleWithPermit(). +type Permit2SettleArgs struct { + Permit struct { + Permitted struct { + Token common.Address + Amount *big.Int + } + Nonce *big.Int + Deadline *big.Int + } + Owner common.Address + Witness struct { + To common.Address + ValidAfter *big.Int + } + Signature []byte +} + +// BuildPermit2SettleArgs converts a raw ExactPermit2Payload into typed contract-call +// arguments, deduplicating the struct construction shared by verify simulation and settle. +func BuildPermit2SettleArgs(permit2Payload *evm.ExactPermit2Payload) (*Permit2SettleArgs, error) { + amount, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Permitted.Amount, 10) + if !ok { + return nil, errParse("permitted amount") + } + nonce, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Nonce, 10) + if !ok { + return nil, errParse("nonce") + } + deadline, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Deadline, 10) + if !ok { + return nil, errParse("deadline") + } + validAfter, ok := new(big.Int).SetString(permit2Payload.Permit2Authorization.Witness.ValidAfter, 10) + if !ok { + return nil, errParse("validAfter") + } + signatureBytes, err := evm.HexToBytes(permit2Payload.Signature) + if err != nil { + return nil, err + } + + args := &Permit2SettleArgs{} + args.Permit.Permitted.Token = common.HexToAddress(permit2Payload.Permit2Authorization.Permitted.Token) + args.Permit.Permitted.Amount = amount + args.Permit.Nonce = nonce + args.Permit.Deadline = deadline + args.Owner = common.HexToAddress(permit2Payload.Permit2Authorization.From) + args.Witness.To = common.HexToAddress(permit2Payload.Permit2Authorization.Witness.To) + args.Witness.ValidAfter = validAfter + args.Signature = signatureBytes + return args, nil +} + +// SimulatePermit2Settle runs settle() via eth_call (ReadContract). +// Returns true if the simulation succeeded. +func SimulatePermit2Settle( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + permit2Payload *evm.ExactPermit2Payload, +) (bool, error) { + args, err := BuildPermit2SettleArgs(permit2Payload) + if err != nil { + return false, err + } + + permitStruct := args.permitStruct() + witnessStruct := args.witnessStruct() + + _, err = signer.ReadContract( + ctx, + evm.X402ExactPermit2ProxyAddress, + evm.X402ExactPermit2ProxySettleABI, + evm.FunctionSettle, + permitStruct, + args.Owner, + witnessStruct, + args.Signature, + ) + if err != nil { + return false, err + } + return true, nil +} + +// SimulatePermit2SettleWithPermit runs settleWithPermit() via eth_call. +// The contract atomically calls token.permit() then PERMIT2.permitTransferFrom(), +// so simulation covers allowance + balance + nonces. +func SimulatePermit2SettleWithPermit( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + permit2Payload *evm.ExactPermit2Payload, + eip2612Signature, eip2612Amount, eip2612DeadlineStr string, +) (bool, error) { + args, err := BuildPermit2SettleArgs(permit2Payload) + if err != nil { + return false, err + } + + v, r, s, splitErr := splitEip2612Signature(eip2612Signature) + if splitErr != nil { + return false, splitErr + } + + eip2612Value, ok := new(big.Int).SetString(eip2612Amount, 10) + if !ok { + return false, errParse("eip2612 amount") + } + eip2612Deadline, ok := new(big.Int).SetString(eip2612DeadlineStr, 10) + if !ok { + return false, errParse("eip2612 deadline") + } + + permit2612Struct := struct { + Value *big.Int + Deadline *big.Int + R [32]byte + S [32]byte + V uint8 + }{ + Value: eip2612Value, + Deadline: eip2612Deadline, + R: r, + S: s, + V: v, + } + + permitStruct := args.permitStruct() + witnessStruct := args.witnessStruct() + + _, err = signer.ReadContract( + ctx, + evm.X402ExactPermit2ProxyAddress, + evm.X402ExactPermit2ProxySettleWithPermitABI, + evm.FunctionSettleWithPermit, + permit2612Struct, + permitStruct, + args.Owner, + witnessStruct, + args.Signature, + ) + if err != nil { + return false, err + } + return true, nil +} + +// DiagnosePermit2SimulationFailure runs a multicall diagnostic to return the most +// specific error reason after a simulation failure. +func DiagnosePermit2SimulationFailure( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + tokenAddress string, + permit2Payload *evm.ExactPermit2Payload, + amountRequired string, +) *x402.VerifyResponse { + payer := permit2Payload.Permit2Authorization.From + + results, err := evm.Multicall(ctx, signer, []evm.MulticallCall{ + { + Address: evm.X402ExactPermit2ProxyAddress, + ABI: evm.X402ExactPermit2ProxyPermit2ABI, + FunctionName: "PERMIT2", + }, + { + Address: tokenAddress, + ABI: evm.ERC20BalanceOfABI, + FunctionName: "balanceOf", + Args: []interface{}{common.HexToAddress(payer)}, + }, + { + Address: tokenAddress, + ABI: evm.ERC20AllowanceABI, + FunctionName: "allowance", + Args: []interface{}{common.HexToAddress(payer), common.HexToAddress(evm.PERMIT2Address)}, + }, + }) + if err != nil || len(results) < 3 { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2SimulationFailed, Payer: payer} + } + + if !results[0].Success() { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2ProxyNotDeployed, Payer: payer} + } + + reqAmount, ok := new(big.Int).SetString(amountRequired, 10) + if !ok { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2SimulationFailed, Payer: payer} + } + + if results[1].Success() { + if balance := asBigInt(results[1].Result); balance != nil && balance.Cmp(reqAmount) < 0 { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2InsufficientBalance, Payer: payer} + } + } + + if results[2].Success() { + if allowance := asBigInt(results[2].Result); allowance != nil && allowance.Cmp(reqAmount) < 0 { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2AllowanceRequired, Payer: payer} + } + } + + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2SimulationFailed, Payer: payer} +} + +// CheckPermit2Prerequisites checks proxy deployment, payer token balance and payer ETH balance for gas. +func CheckPermit2Prerequisites( + ctx context.Context, + signer evm.FacilitatorEvmSigner, + tokenAddress string, + payer string, + amountRequired string, +) *x402.VerifyResponse { + results, err := evm.Multicall(ctx, signer, []evm.MulticallCall{ + { + Address: evm.X402ExactPermit2ProxyAddress, + ABI: evm.X402ExactPermit2ProxyPermit2ABI, + FunctionName: "PERMIT2", + }, + { + Address: tokenAddress, + ABI: evm.ERC20BalanceOfABI, + FunctionName: "balanceOf", + Args: []interface{}{common.HexToAddress(payer)}, + }, + { + Address: evm.MULTICALL3Address, + ABI: evm.Multicall3GetEthBalanceABI, + FunctionName: "getEthBalance", + Args: []interface{}{common.HexToAddress(payer)}, + }, + }) + if err != nil || len(results) < 3 { + // Fail open for prerequisites-only check + return &x402.VerifyResponse{IsValid: true, Payer: payer} + } + + if !results[0].Success() { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2ProxyNotDeployed, Payer: payer} + } + + reqAmount, ok := new(big.Int).SetString(amountRequired, 10) + if ok && results[1].Success() { + if balance := asBigInt(results[1].Result); balance != nil && balance.Cmp(reqAmount) < 0 { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrPermit2InsufficientBalance, Payer: payer} + } + } + + if results[2].Success() { + minEthForGas := new(big.Int).Mul( + big.NewInt(int64(evm.ERC20ApproveGasLimit)), + big.NewInt(int64(evm.DefaultMaxFeePerGas)), + ) + if ethBalance := asBigInt(results[2].Result); ethBalance != nil && ethBalance.Cmp(minEthForGas) < 0 { + return &x402.VerifyResponse{IsValid: false, InvalidReason: ErrErc20ApprovalInsufficientEth, Payer: payer} + } + } + + return &x402.VerifyResponse{IsValid: true, Payer: payer} +} + +// permitStruct returns the ABI-compatible tuple for the permit parameter. +func (a *Permit2SettleArgs) permitStruct() interface{} { + return struct { + Permitted struct { + Token common.Address + Amount *big.Int + } + Nonce *big.Int + Deadline *big.Int + }{ + Permitted: struct { + Token common.Address + Amount *big.Int + }{ + Token: a.Permit.Permitted.Token, + Amount: a.Permit.Permitted.Amount, + }, + Nonce: a.Permit.Nonce, + Deadline: a.Permit.Deadline, + } +} + +// witnessStruct returns the ABI-compatible tuple for the witness parameter. +func (a *Permit2SettleArgs) witnessStruct() interface{} { + return struct { + To common.Address + ValidAfter *big.Int + }{ + To: a.Witness.To, + ValidAfter: a.Witness.ValidAfter, + } +} + +func errParse(field string) error { + return &parseError{field: field} +} + +type parseError struct { + field string +} + +func (e *parseError) Error() string { + return "invalid " + e.field +} diff --git a/go/mechanisms/evm/exact/facilitator/scheme.go b/go/mechanisms/evm/exact/facilitator/scheme.go index ce6750b364..2ccc92740d 100644 --- a/go/mechanisms/evm/exact/facilitator/scheme.go +++ b/go/mechanisms/evm/exact/facilitator/scheme.go @@ -81,7 +81,7 @@ func (f *ExactEvmScheme) Verify( if err != nil { return nil, x402.NewVerifyError(ErrInvalidPayload, "", fmt.Sprintf("failed to parse Permit2 payload: %s", err.Error())) } - return VerifyPermit2(ctx, f.signer, payload, requirements, permit2Payload, fctx) + return VerifyPermit2(ctx, f.signer, payload, requirements, permit2Payload, fctx, nil) } return f.verifyEIP3009(ctx, payload, requirements, true) @@ -103,7 +103,9 @@ func (f *ExactEvmScheme) Settle( network := x402.Network(payload.Accepted.Network) return nil, x402.NewSettleError(ErrInvalidPayload, "", network, "", fmt.Sprintf("failed to parse Permit2 payload: %s", err.Error())) } - return SettlePermit2(ctx, f.signer, payload, requirements, permit2Payload, fctx) + return SettlePermit2(ctx, f.signer, payload, requirements, permit2Payload, fctx, &Permit2FacilitatorConfig{ + SimulateInSettle: f.config.SimulateInSettle, + }) } return f.settleEIP3009(ctx, payload, requirements) diff --git a/go/test/unit/evm_client_facilitator_test.go b/go/test/unit/evm_client_facilitator_test.go index f6d865a531..6837e0c13d 100644 --- a/go/test/unit/evm_client_facilitator_test.go +++ b/go/test/unit/evm_client_facilitator_test.go @@ -654,7 +654,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for invalid spender") } @@ -679,7 +679,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for recipient mismatch") } @@ -701,7 +701,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for expired deadline") } @@ -726,7 +726,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for not-yet-valid payment") } @@ -748,7 +748,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for insufficient amount") } @@ -770,7 +770,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for token mismatch") } @@ -792,7 +792,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, validPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for invalid deadline format") } @@ -822,7 +822,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, wrongSchemePayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, wrongSchemePayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for scheme mismatch") } @@ -852,7 +852,7 @@ func TestVerifyPermit2InvalidInputs(t *testing.T) { }, } - _, err := evmfacilitator.VerifyPermit2(ctx, signer, wrongNetworkPayload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.VerifyPermit2(ctx, signer, wrongNetworkPayload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Error("Expected error for network mismatch") } @@ -1467,7 +1467,7 @@ func TestSettlePermit2_EIP2612Routing(t *testing.T) { }, } - _, err := evmfacilitator.SettlePermit2(ctx, signer, payload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.SettlePermit2(ctx, signer, payload, validRequirements, permit2Payload, nil, nil) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -1501,7 +1501,7 @@ func TestSettlePermit2_EIP2612Routing(t *testing.T) { // No extensions } - _, err := evmfacilitator.SettlePermit2(ctx, signer, payload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.SettlePermit2(ctx, signer, payload, validRequirements, permit2Payload, nil, nil) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -1595,7 +1595,7 @@ func TestSettlePermit2_ContractRevertErrors(t *testing.T) { }, } - _, err := evmfacilitator.SettlePermit2(ctx, signer, payload, validRequirements, permit2Payload, nil) + _, err := evmfacilitator.SettlePermit2(ctx, signer, payload, validRequirements, permit2Payload, nil, nil) if err == nil { t.Fatal("Expected error from SettlePermit2") } diff --git a/typescript/.changeset/fifty-doodles-strive.md b/typescript/.changeset/fifty-doodles-strive.md new file mode 100644 index 0000000000..fb8f25d120 --- /dev/null +++ b/typescript/.changeset/fifty-doodles-strive.md @@ -0,0 +1,5 @@ +--- +'@x402/evm': patch +--- + +Added simulation to permit2 verify and (optional) settle diff --git a/typescript/packages/mechanisms/evm/src/exact/extensions.ts b/typescript/packages/mechanisms/evm/src/exact/extensions.ts index f4ddba882d..d3e3fe458b 100644 --- a/typescript/packages/mechanisms/evm/src/exact/extensions.ts +++ b/typescript/packages/mechanisms/evm/src/exact/extensions.ts @@ -38,6 +38,7 @@ export type TransactionRequest = export type Erc20ApprovalGasSponsoringSigner = FacilitatorEvmSigner & { sendTransactions(transactions: TransactionRequest[]): Promise<`0x${string}`[]>; + simulateTransactions?(transactions: TransactionRequest[]): Promise; }; export interface Erc20ApprovalGasSponsoringFacilitatorExtension { diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts index e3d1f25dec..b5c4f384d9 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/errors.ts @@ -33,6 +33,9 @@ export const ErrPermit2AmountMismatch = "permit2_amount_mismatch"; export const ErrPermit2TokenMismatch = "permit2_token_mismatch"; export const ErrPermit2InvalidSignature = "invalid_permit2_signature"; export const ErrPermit2AllowanceRequired = "permit2_allowance_required"; +export const ErrPermit2SimulationFailed = "permit2_simulation_failed"; +export const ErrPermit2InsufficientBalance = "permit2_insufficient_balance"; +export const ErrPermit2ProxyNotDeployed = "permit2_proxy_not_deployed"; // Permit2 settle errors (from contract reverts) export const ErrPermit2InvalidAmount = "permit2_invalid_amount"; @@ -43,6 +46,7 @@ export const ErrPermit2InvalidNonce = "permit2_invalid_nonce"; export const ErrPermit2612AmountMismatch = "permit2_2612_amount_mismatch"; // ERC-20 approval gas sponsoring verify errors +export const ErrErc20ApprovalInsufficientEthForGas = "erc20_approval_insufficient_eth_for_gas"; export const ErrErc20ApprovalInvalidFormat = "invalid_erc20_approval_extension_format"; export const ErrErc20ApprovalFromMismatch = "erc20_approval_from_mismatch"; export const ErrErc20ApprovalAssetMismatch = "erc20_approval_asset_mismatch"; @@ -54,3 +58,15 @@ export const ErrErc20ApprovalTxInvalidCalldata = "erc20_approval_tx_invalid_call export const ErrErc20ApprovalTxSignerMismatch = "erc20_approval_tx_signer_mismatch"; export const ErrErc20ApprovalTxInvalidSignature = "erc20_approval_tx_invalid_signature"; export const ErrErc20ApprovalTxParseFailed = "erc20_approval_tx_parse_failed"; +export const ErrErc20ApprovalTxFailed = "erc20_approval_tx_failed"; + +// EIP-2612 gas sponsoring verify errors +export const ErrInvalidEip2612ExtensionFormat = "invalid_eip2612_extension_format"; +export const ErrEip2612FromMismatch = "eip2612_from_mismatch"; +export const ErrEip2612AssetMismatch = "eip2612_asset_mismatch"; +export const ErrEip2612SpenderNotPermit2 = "eip2612_spender_not_permit2"; +export const ErrEip2612DeadlineExpired = "eip2612_deadline_expired"; + +// Shared settle errors +export const ErrUnsupportedPayloadType = "unsupported_payload_type"; +export const ErrInvalidTransactionState = "invalid_transaction_state"; diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2-utils.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2-utils.ts new file mode 100644 index 0000000000..77ad692b23 --- /dev/null +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2-utils.ts @@ -0,0 +1,442 @@ +import { PaymentPayload, SettleResponse, VerifyResponse } from "@x402/core/types"; +import { encodeFunctionData, getAddress } from "viem"; +import { + eip3009ABI, + erc20AllowanceAbi, + ERC20_APPROVE_GAS_LIMIT, + DEFAULT_MAX_FEE_PER_GAS, + PERMIT2_ADDRESS, + x402ExactPermit2ProxyABI, + x402ExactPermit2ProxyAddress, +} from "../../constants"; +import { + multicall, + ContractCall, + MULTICALL3_ADDRESS, + multicall3GetEthBalanceAbi, +} from "../../multicall"; +import { FacilitatorEvmSigner } from "../../signer"; +import { ExactPermit2Payload } from "../../types"; +import { + validateEip2612GasSponsoringInfo, + type Eip2612GasSponsoringInfo, + type Erc20ApprovalGasSponsoringSigner, +} from "../extensions"; +import * as Errors from "./errors"; + +/** + * Simulates settle() via eth_call (readContract). + * Returns true if simulation succeeded, false if it failed. + * + * @param signer - EVM signer for contract reads + * @param permit2Payload - Permit2 payload with authorization and signature + * @returns true if simulation succeeded, false if it failed + */ +export async function simulatePermit2Settle( + signer: FacilitatorEvmSigner, + permit2Payload: ExactPermit2Payload, +): Promise { + try { + await signer.readContract({ + address: x402ExactPermit2ProxyAddress, + abi: x402ExactPermit2ProxyABI, + functionName: "settle", + args: buildPermit2SettleArgs(permit2Payload), + }); + return true; + } catch { + return false; + } +} + +/** + * Splits a 65-byte EIP-2612 signature into v, r, s components for contract calls. + * Validates length and throws if invalid. + * + * @param signature - The hex-encoded 65-byte signature + * @returns Object with v (uint8), r (bytes32), s (bytes32) + */ +export function splitEip2612Signature(signature: string): { + v: number; + r: `0x${string}`; + s: `0x${string}`; +} { + const sig = signature.startsWith("0x") ? signature.slice(2) : signature; + + if (sig.length !== 130) { + throw new Error( + `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`, + ); + } + + const r = `0x${sig.slice(0, 64)}` as `0x${string}`; + const s = `0x${sig.slice(64, 128)}` as `0x${string}`; + const v = parseInt(sig.slice(128, 130), 16); + + return { v, r, s }; +} + +/** + * Builds the args array for settle() and settleWithPermit() Permit2 calls. + * Shared by simulation and settlement to keep contract ABI shape in one place. + * + * @param permit2Payload - The Permit2 authorization payload + * @returns The args tuple for settle(permit, owner, witness, signature) + */ +export function buildPermit2SettleArgs(permit2Payload: ExactPermit2Payload) { + return [ + { + permitted: { + token: getAddress(permit2Payload.permit2Authorization.permitted.token), + amount: BigInt(permit2Payload.permit2Authorization.permitted.amount), + }, + nonce: BigInt(permit2Payload.permit2Authorization.nonce), + deadline: BigInt(permit2Payload.permit2Authorization.deadline), + }, + getAddress(permit2Payload.permit2Authorization.from), + { + to: getAddress(permit2Payload.permit2Authorization.witness.to), + validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), + }, + permit2Payload.signature, + ] as const; +} + +/** + * Encodes settle() calldata for the x402 Exact Permit2 proxy. + * Used when bundling approve + settle (e.g. ERC-20 approval gas sponsoring). + * + * @param permit2Payload - The Permit2 authorization payload + * @returns Hex-encoded settle calldata + */ +export function encodePermit2SettleCalldata(permit2Payload: ExactPermit2Payload): `0x${string}` { + return encodeFunctionData({ + abi: x402ExactPermit2ProxyABI, + functionName: "settle", + args: buildPermit2SettleArgs(permit2Payload), + }); +} + +/** + * Simulates settleWithPermit() via eth_call (readContract). + * The contract atomically calls token.permit() then PERMIT2.permitTransferFrom(), + * so simulation covers allowance + balance + nonces. + * + * @param signer - EVM signer for contract reads + * @param permit2Payload - Permit2 payload with authorization and signature + * @param eip2612Info - EIP-2612 gas sponsoring info from the payload extension + * @returns true if simulation succeeded, false if it failed + */ +export async function simulatePermit2SettleWithPermit( + signer: FacilitatorEvmSigner, + permit2Payload: ExactPermit2Payload, + eip2612Info: Eip2612GasSponsoringInfo, +): Promise { + try { + const { v, r, s } = splitEip2612Signature(eip2612Info.signature); + + await signer.readContract({ + address: x402ExactPermit2ProxyAddress, + abi: x402ExactPermit2ProxyABI, + functionName: "settleWithPermit", + args: [ + { + value: BigInt(eip2612Info.amount), + deadline: BigInt(eip2612Info.deadline), + r, + s, + v, + }, + ...buildPermit2SettleArgs(permit2Payload), + ], + }); + return true; + } catch { + return false; + } +} + +/** + * Diagnoses a Permit2 simulation failure by performing a multicall to check the proxy deployment, balance and allowance. + * + * @param signer - EVM signer for contract reads + * @param tokenAddress - ERC-20 token contract address + * @param permit2Payload - The Permit2 authorization payload + * @param amountRequired - Required payment amount (as string) + * @returns VerifyResponse with the most specific failure reason + */ +export async function diagnosePermit2SimulationFailure( + signer: FacilitatorEvmSigner, + tokenAddress: `0x${string}`, + permit2Payload: ExactPermit2Payload, + amountRequired: string, +): Promise { + const payer = permit2Payload.permit2Authorization.from; + + const diagnosticCalls: ContractCall[] = [ + { + address: x402ExactPermit2ProxyAddress, + abi: x402ExactPermit2ProxyABI, + functionName: "PERMIT2", + }, + { + address: tokenAddress, + abi: eip3009ABI, + functionName: "balanceOf", + args: [payer], + }, + { + address: tokenAddress, + abi: erc20AllowanceAbi, + functionName: "allowance", + args: [payer, PERMIT2_ADDRESS], + }, + ]; + + try { + const results = await multicall(signer.readContract.bind(signer), diagnosticCalls); + + const [proxyResult, balanceResult, allowanceResult] = results; + + if (proxyResult.status === "failure") { + return { isValid: false, invalidReason: Errors.ErrPermit2ProxyNotDeployed, payer }; + } + + if (balanceResult.status === "success") { + const balance = balanceResult.result as bigint; + if (balance < BigInt(amountRequired)) { + return { isValid: false, invalidReason: Errors.ErrPermit2InsufficientBalance, payer }; + } + } + + if (allowanceResult.status === "success") { + const allowance = allowanceResult.result as bigint; + if (allowance < BigInt(amountRequired)) { + return { isValid: false, invalidReason: Errors.ErrPermit2AllowanceRequired, payer }; + } + } + } catch { + // Diagnostic multicall itself failed β€” fall through to generic error + } + + return { isValid: false, invalidReason: Errors.ErrPermit2SimulationFailed, payer }; +} + +/** + * Targeted multicall for the ERC-20 approval path where simulation cannot be used + * (the approval hasn't been broadcast yet, so settle() would fail for expected reasons). + * Checks proxy deployment, payer token balance and payer ETH balance for gas. + * + * @param signer - EVM signer for contract reads + * @param tokenAddress - ERC-20 token contract address + * @param payer - The payer address + * @param amountRequired - Required payment amount (as string) + * @returns VerifyResponse β€” valid if checks pass, otherwise the most specific failure + */ +export async function checkPermit2Prerequisites( + signer: FacilitatorEvmSigner, + tokenAddress: `0x${string}`, + payer: `0x${string}`, + amountRequired: string, +): Promise { + const diagnosticCalls: ContractCall[] = [ + { + address: x402ExactPermit2ProxyAddress, + abi: x402ExactPermit2ProxyABI, + functionName: "PERMIT2", + }, + { + address: tokenAddress, + abi: eip3009ABI, + functionName: "balanceOf", + args: [payer], + }, + { + address: MULTICALL3_ADDRESS, + abi: multicall3GetEthBalanceAbi, + functionName: "getEthBalance", + args: [payer], + }, + ]; + + try { + const results = await multicall(signer.readContract.bind(signer), diagnosticCalls); + + const [proxyResult, balanceResult, ethBalanceResult] = results; + + if (proxyResult.status === "failure") { + return { isValid: false, invalidReason: Errors.ErrPermit2ProxyNotDeployed, payer }; + } + + if (balanceResult.status === "success") { + const balance = balanceResult.result as bigint; + if (balance < BigInt(amountRequired)) { + return { isValid: false, invalidReason: Errors.ErrPermit2InsufficientBalance, payer }; + } + } + + if (ethBalanceResult.status === "success") { + const minEthForApprovalGas = ERC20_APPROVE_GAS_LIMIT * DEFAULT_MAX_FEE_PER_GAS; + const ethBalance = ethBalanceResult.result as bigint; + if (ethBalance < minEthForApprovalGas) { + return { + isValid: false, + invalidReason: Errors.ErrErc20ApprovalInsufficientEthForGas, + payer, + }; + } + } + } catch { + // Multicall failed β€” fall through to valid (fail open for prerequisites-only check) + } + + return { isValid: true, invalidReason: undefined, payer }; +} + +/** + * Delegates the full approve+settle simulation flow to the extension signer via simulateTransactions. + * The signer owns execution strategy. + * + * @param extensionSigner - The extension signer with simulateTransactions capability + * @param permit2Payload - The Permit2 specific payload + * @param erc20Info - Object containing the signed approval transaction + * @param erc20Info.signedTransaction - The RLP-encoded signed ERC-20 approve transaction + * @returns true if the bundle simulation succeeded, false otherwise + */ +export async function simulatePermit2SettleWithErc20Approval( + extensionSigner: Erc20ApprovalGasSponsoringSigner, + permit2Payload: ExactPermit2Payload, + erc20Info: { signedTransaction: string }, +): Promise { + if (!extensionSigner.simulateTransactions) { + return false; + } + + try { + const settleData = encodePermit2SettleCalldata(permit2Payload); + + return await extensionSigner.simulateTransactions([ + erc20Info.signedTransaction as `0x${string}`, + { to: x402ExactPermit2ProxyAddress, data: settleData, gas: BigInt(300_000) }, + ]); + } catch { + return false; + } +} + +/** + * Waits for tx receipt and returns the appropriate SettleResponse. + * + * @param signer - Signer with waitForTransactionReceipt capability + * @param tx - The transaction hash to wait for + * @param payload - The payment payload (for network info) + * @param payer - The payer address + * @returns Promise resolving to settlement response + */ +export async function waitAndReturn( + signer: Pick, + tx: `0x${string}`, + payload: PaymentPayload, + payer: `0x${string}`, +): Promise { + const receipt = await signer.waitForTransactionReceipt({ hash: tx }); + + if (receipt.status !== "success") { + return { + success: false, + errorReason: Errors.ErrInvalidTransactionState, + transaction: tx, + network: payload.accepted.network, + payer, + }; + } + + return { + success: true, + transaction: tx, + network: payload.accepted.network, + payer, + }; +} + +/** + * Maps contract revert errors to structured SettleResponse error reasons. + * + * @param error - The caught error + * @param payload - The payment payload (for network info) + * @param payer - The payer address + * @returns A failed SettleResponse with mapped error reason + */ +export function mapSettleError( + error: unknown, + payload: PaymentPayload, + payer: `0x${string}`, +): SettleResponse { + let errorReason = Errors.ErrTransactionFailed; + if (error instanceof Error) { + const message = error.message; + if (message.includes("Permit2612AmountMismatch")) { + errorReason = Errors.ErrPermit2612AmountMismatch; + } else if (message.includes("InvalidAmount")) { + errorReason = Errors.ErrPermit2InvalidAmount; + } else if (message.includes("InvalidDestination")) { + errorReason = Errors.ErrPermit2InvalidDestination; + } else if (message.includes("InvalidOwner")) { + errorReason = Errors.ErrPermit2InvalidOwner; + } else if (message.includes("PaymentTooEarly")) { + errorReason = Errors.ErrPermit2PaymentTooEarly; + } else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) { + errorReason = Errors.ErrPermit2InvalidSignature; + } else if (message.includes("InvalidNonce")) { + errorReason = Errors.ErrPermit2InvalidNonce; + } else if (message.includes("erc20_approval_tx_failed")) { + errorReason = Errors.ErrErc20ApprovalTxFailed; + } else { + errorReason = `${Errors.ErrTransactionFailed}: ${message.slice(0, 500)}`; + } + } + return { + success: false, + errorReason, + transaction: "", + network: payload.accepted.network, + payer, + }; +} + +/** + * Validates EIP-2612 permit extension data for a Permit2 payment. + * + * @param info - The EIP-2612 gas sponsoring info + * @param payer - The expected payer address + * @param tokenAddress - The expected token address + * @returns Validation result with optional invalidReason + */ +export function validateEip2612PermitForPayment( + info: Eip2612GasSponsoringInfo, + payer: `0x${string}`, + tokenAddress: `0x${string}`, +): { isValid: boolean; invalidReason?: string } { + if (!validateEip2612GasSponsoringInfo(info)) { + return { isValid: false, invalidReason: Errors.ErrInvalidEip2612ExtensionFormat }; + } + + if (getAddress(info.from as `0x${string}`) !== getAddress(payer)) { + return { isValid: false, invalidReason: Errors.ErrEip2612FromMismatch }; + } + + if (getAddress(info.asset as `0x${string}`) !== tokenAddress) { + return { isValid: false, invalidReason: Errors.ErrEip2612AssetMismatch }; + } + + if (getAddress(info.spender as `0x${string}`) !== getAddress(PERMIT2_ADDRESS)) { + return { isValid: false, invalidReason: Errors.ErrEip2612SpenderNotPermit2 }; + } + + const now = Math.floor(Date.now() / 1000); + if (BigInt(info.deadline) < BigInt(now + 6)) { + return { isValid: false, invalidReason: Errors.ErrEip2612DeadlineExpired }; + } + + return { isValid: true }; +} diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts index feff32e0ff..ecdd51b1d4 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/permit2.ts @@ -7,7 +7,6 @@ import { } from "@x402/core/types"; import { extractEip2612GasSponsoringInfo, - validateEip2612GasSponsoringInfo, extractErc20ApprovalGasSponsoringInfo, ERC20_APPROVAL_GAS_SPONSORING_KEY, resolveErc20ApprovalExtensionSigner, @@ -15,29 +14,46 @@ import { type Erc20ApprovalGasSponsoringFacilitatorExtension, type Erc20ApprovalGasSponsoringSigner, } from "../extensions"; -import { getAddress, encodeFunctionData } from "viem"; +import { getAddress } from "viem"; import { - eip3009ABI, PERMIT2_ADDRESS, permit2WitnessTypes, x402ExactPermit2ProxyABI, x402ExactPermit2ProxyAddress, - erc20AllowanceAbi, } from "../../constants"; -import { - ErrPermit2612AmountMismatch, - ErrPermit2AmountMismatch, - ErrPermit2InvalidAmount, - ErrPermit2InvalidDestination, - ErrPermit2InvalidNonce, - ErrPermit2InvalidOwner, - ErrPermit2InvalidSignature, - ErrPermit2PaymentTooEarly, -} from "./errors"; +import * as Errors from "./errors"; import { FacilitatorEvmSigner } from "../../signer"; import { ExactPermit2Payload } from "../../types"; import { getEvmChainId } from "../../utils"; import { validateErc20ApprovalForPayment } from "./erc20approval"; +import { + simulatePermit2Settle, + simulatePermit2SettleWithPermit, + simulatePermit2SettleWithErc20Approval, + diagnosePermit2SimulationFailure, + checkPermit2Prerequisites, + splitEip2612Signature, + buildPermit2SettleArgs, + encodePermit2SettleCalldata, + waitAndReturn, + mapSettleError, + validateEip2612PermitForPayment, +} from "./permit2-utils"; + +export interface VerifyPermit2Options { + /** Run onchain simulation. Defaults to true. */ + simulate?: boolean; +} + +export interface Permit2FacilitatorConfig { + /** + * If enabled, simulates transaction before settling. Defaults to false, + * i.e. only simulate during verify. + * + * @default false + */ + simulateInSettle?: boolean; +} /** * Verifies a Permit2 payment payload. @@ -52,6 +68,7 @@ import { validateErc20ApprovalForPayment } from "./erc20approval"; * @param requirements - The payment requirements * @param permit2Payload - The Permit2 specific payload * @param context - Optional facilitator context for extension-provided capabilities + * @param options - Optional verification options (e.g. simulate) * @returns Promise resolving to verification response */ export async function verifyPermit2( @@ -60,13 +77,14 @@ export async function verifyPermit2( requirements: PaymentRequirements, permit2Payload: ExactPermit2Payload, context?: FacilitatorContext, + options?: VerifyPermit2Options, ): Promise { const payer = permit2Payload.permit2Authorization.from; if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { return { isValid: false, - invalidReason: "unsupported_scheme", + invalidReason: Errors.ErrUnsupportedPayloadType, payer, }; } @@ -74,7 +92,7 @@ export async function verifyPermit2( if (payload.accepted.network !== requirements.network) { return { isValid: false, - invalidReason: "network_mismatch", + invalidReason: Errors.ErrNetworkMismatch, payer, }; } @@ -88,7 +106,7 @@ export async function verifyPermit2( ) { return { isValid: false, - invalidReason: "invalid_permit2_spender", + invalidReason: Errors.ErrPermit2InvalidSpender, payer, }; } @@ -98,7 +116,7 @@ export async function verifyPermit2( ) { return { isValid: false, - invalidReason: "invalid_permit2_recipient_mismatch", + invalidReason: Errors.ErrPermit2RecipientMismatch, payer, }; } @@ -107,7 +125,7 @@ export async function verifyPermit2( if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) { return { isValid: false, - invalidReason: "permit2_deadline_expired", + invalidReason: Errors.ErrPermit2DeadlineExpired, payer, }; } @@ -115,7 +133,7 @@ export async function verifyPermit2( if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) { return { isValid: false, - invalidReason: "permit2_not_yet_valid", + invalidReason: Errors.ErrPermit2NotYetValid, payer, }; } @@ -126,7 +144,7 @@ export async function verifyPermit2( ) { return { isValid: false, - invalidReason: ErrPermit2AmountMismatch, + invalidReason: Errors.ErrPermit2AmountMismatch, payer, }; } @@ -134,7 +152,7 @@ export async function verifyPermit2( if (getAddress(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) { return { isValid: false, - invalidReason: "permit2_token_mismatch", + invalidReason: Errors.ErrPermit2TokenMismatch, payer, }; } @@ -162,154 +180,114 @@ export async function verifyPermit2( }, }; + // Verify signature + // Note: verifyTypedData is implementation-dependent and pluggable on FacilitatorEvmSigner + // Some implementations only do EOA-style ECDSA recovery (e.g. viem/utils verifyTypedData, ethers.verifyTypedData) + // Viem's publicClient.verifyTypedData supports EOA and Smart Contract Account (ERC-1271 / ERC-6492) signature verification + let signatureValid = false; try { - const isValid = await signer.verifyTypedData({ + signatureValid = await signer.verifyTypedData({ address: payer, ...permit2TypedData, signature: permit2Payload.signature, }); - - if (!isValid) { - return { - isValid: false, - invalidReason: "invalid_permit2_signature", - payer, - }; - } } catch { - return { - isValid: false, - invalidReason: "invalid_permit2_signature", - payer, - }; + signatureValid = false; } - // Check Permit2 allowance β€” if insufficient, try gas sponsoring extensions - const allowanceResult = await _verifyPermit2Allowance( - signer, - payload, - requirements, - payer, - tokenAddress, - context, - ); - if (allowanceResult) { - return allowanceResult; - } + if (!signatureValid) { + // Check if the payer is a deployed smart contract + const bytecode = await signer.getCode({ address: payer }); + const isDeployedContract = bytecode && bytecode !== "0x"; - try { - const balance = (await signer.readContract({ - address: tokenAddress, - abi: eip3009ABI, - functionName: "balanceOf", - args: [payer], - })) as bigint; - - if (balance < BigInt(requirements.amount)) { + if (!isDeployedContract) { return { isValid: false, - invalidReason: "insufficient_funds", - invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`, + invalidReason: Errors.ErrPermit2InvalidSignature, payer, }; } - } catch { - // If we can't check balance, continue + // Deployed smart contract: fall through to simulation } - return { - isValid: true, - invalidReason: undefined, - payer, - }; -} - -/** - * Checks Permit2 allowance and validates gas sponsoring extensions if allowance is insufficient. - * - * @param signer - The facilitator signer for on-chain reads - * @param payload - The payment payload - * @param requirements - The payment requirements - * @param payer - The payer address - * @param tokenAddress - The token contract address - * @param context - Optional facilitator context for extension lookup - * @returns A VerifyResponse if verification should stop (failure), or null to continue - */ -async function _verifyPermit2Allowance( - signer: FacilitatorEvmSigner, - payload: PaymentPayload, - requirements: PaymentRequirements, - payer: `0x${string}`, - tokenAddress: `0x${string}`, - context?: FacilitatorContext, -): Promise { - try { - const allowance = (await signer.readContract({ - address: tokenAddress, - abi: erc20AllowanceAbi, - functionName: "allowance", - args: [payer, PERMIT2_ADDRESS], - })) as bigint; - - if (allowance >= BigInt(requirements.amount)) { - return null; // Sufficient allowance, continue verification - } + // If simulation is disabled, return early + if (options?.simulate === false) { + return { isValid: true, invalidReason: undefined, payer }; + } - // Allowance insufficient β€” try EIP-2612 gas sponsoring first - const eip2612Info = extractEip2612GasSponsoringInfo(payload); - if (eip2612Info) { - const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); - if (!result.isValid) { - return { isValid: false, invalidReason: result.invalidReason!, payer }; - } - return null; // EIP-2612 is valid, allowance will be set atomically during settlement + // Branch: EIP-2612 gas sponsoring (atomic settleWithPermit via contract) + const eip2612Info = extractEip2612GasSponsoringInfo(payload); + if (eip2612Info) { + const fieldResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); + if (!fieldResult.isValid) { + return { isValid: false, invalidReason: fieldResult.invalidReason!, payer }; } - // Try ERC-20 approval gas sponsoring as fallback - const erc20GasSponsorshipExtension = - context?.getExtension( - ERC20_APPROVAL_GAS_SPONSORING_KEY, + const simOk = await simulatePermit2SettleWithPermit(signer, permit2Payload, eip2612Info); + if (!simOk) { + return diagnosePermit2SimulationFailure( + signer, + tokenAddress, + permit2Payload, + requirements.amount, ); - if (erc20GasSponsorshipExtension) { - const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload); - if (erc20Info) { - const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress); - if (!result.isValid) { - return { isValid: false, invalidReason: result.invalidReason!, payer }; - } - return null; // ERC-20 approval is valid, will be broadcast before settlement - } } - return { isValid: false, invalidReason: "permit2_allowance_required", payer }; - } catch { - // Allowance check failed β€” validate extensions if present; fail closed if none valid - const eip2612Info = extractEip2612GasSponsoringInfo(payload); - if (eip2612Info) { - const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); - if (!result.isValid) { - return { isValid: false, invalidReason: result.invalidReason!, payer }; + return { isValid: true, invalidReason: undefined, payer }; + } + + // Branch: ERC-20 approval gas sponsoring (broadcast approval + settle via extension signer) + const erc20GasSponsorshipExtension = + context?.getExtension( + ERC20_APPROVAL_GAS_SPONSORING_KEY, + ); + if (erc20GasSponsorshipExtension) { + const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload); + if (erc20Info) { + const fieldResult = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress); + if (!fieldResult.isValid) { + return { isValid: false, invalidReason: fieldResult.invalidReason!, payer }; } - return null; - } - const erc20GasSponsorshipExtension = - context?.getExtension( - ERC20_APPROVAL_GAS_SPONSORING_KEY, + const extensionSigner = resolveErc20ApprovalExtensionSigner( + erc20GasSponsorshipExtension, + requirements.network, ); - if (erc20GasSponsorshipExtension) { - const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload); - if (erc20Info) { - const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress); - if (!result.isValid) { - return { isValid: false, invalidReason: result.invalidReason!, payer }; + + if (extensionSigner?.simulateTransactions) { + const simOk = await simulatePermit2SettleWithErc20Approval( + extensionSigner, + permit2Payload, + erc20Info, + ); + if (!simOk) { + return diagnosePermit2SimulationFailure( + signer, + tokenAddress, + permit2Payload, + requirements.amount, + ); } - return null; + return { isValid: true, invalidReason: undefined, payer }; } + + // Fallback to prerequisite-only check if simulateTransactions is not available + return checkPermit2Prerequisites(signer, tokenAddress, payer, requirements.amount); } + } - return { isValid: false, invalidReason: "permit2_allowance_required", payer }; + // Branch: standard settle (allowance already on-chain) + const simOk = await simulatePermit2Settle(signer, permit2Payload); + if (!simOk) { + return diagnosePermit2SimulationFailure( + signer, + tokenAddress, + permit2Payload, + requirements.amount, + ); } + + return { isValid: true, invalidReason: undefined, payer }; } /** @@ -324,6 +302,7 @@ async function _verifyPermit2Allowance( * @param requirements - The payment requirements * @param permit2Payload - The Permit2 specific payload * @param context - Optional facilitator context for extension-provided capabilities + * @param config - Optional facilitator config (simulateInSettle) * @returns Promise resolving to settlement response */ export async function settlePermit2( @@ -332,16 +311,19 @@ export async function settlePermit2( requirements: PaymentRequirements, permit2Payload: ExactPermit2Payload, context?: FacilitatorContext, + config?: Permit2FacilitatorConfig, ): Promise { const payer = permit2Payload.permit2Authorization.from; - const valid = await verifyPermit2(signer, payload, requirements, permit2Payload, context); + const valid = await verifyPermit2(signer, payload, requirements, permit2Payload, context, { + simulate: config?.simulateInSettle ?? false, + }); if (!valid.isValid) { return { success: false, network: payload.accepted.network, transaction: "", - errorReason: valid.invalidReason ?? "invalid_scheme", + errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme, payer, }; } @@ -403,26 +385,13 @@ async function _settlePermit2WithEIP2612( s, v, }, - { - permitted: { - token: getAddress(permit2Payload.permit2Authorization.permitted.token), - amount: BigInt(permit2Payload.permit2Authorization.permitted.amount), - }, - nonce: BigInt(permit2Payload.permit2Authorization.nonce), - deadline: BigInt(permit2Payload.permit2Authorization.deadline), - }, - getAddress(payer), - { - to: getAddress(permit2Payload.permit2Authorization.witness.to), - validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), - }, - permit2Payload.signature, + ...buildPermit2SettleArgs(permit2Payload), ], }); - return _waitAndReturn(signer, tx, payload, payer); + return waitAndReturn(signer, tx, payload, payer); } catch (error) { - return _mapSettleError(error, payload, payer); + return mapSettleError(error, payload, payer); } } @@ -446,26 +415,7 @@ async function _settlePermit2WithERC20Approval( const payer = permit2Payload.permit2Authorization.from; try { - const settleData = encodeFunctionData({ - abi: x402ExactPermit2ProxyABI, - functionName: "settle", - args: [ - { - permitted: { - token: getAddress(permit2Payload.permit2Authorization.permitted.token), - amount: BigInt(permit2Payload.permit2Authorization.permitted.amount), - }, - nonce: BigInt(permit2Payload.permit2Authorization.nonce), - deadline: BigInt(permit2Payload.permit2Authorization.deadline), - }, - getAddress(payer), - { - to: getAddress(permit2Payload.permit2Authorization.witness.to), - validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), - }, - permit2Payload.signature, - ], - }); + const settleData = encodePermit2SettleCalldata(permit2Payload); const txHashes = await extensionSigner.sendTransactions([ erc20Info.signedTransaction as `0x${string}`, @@ -473,9 +423,9 @@ async function _settlePermit2WithERC20Approval( ]); const settleTxHash = txHashes[txHashes.length - 1]; - return _waitAndReturn(extensionSigner, settleTxHash, payload, payer); + return waitAndReturn(extensionSigner, settleTxHash, payload, payer); } catch (error) { - return _mapSettleError(error, payload, payer); + return mapSettleError(error, payload, payer); } } @@ -498,169 +448,11 @@ async function _settlePermit2Direct( address: x402ExactPermit2ProxyAddress, abi: x402ExactPermit2ProxyABI, functionName: "settle", - args: [ - { - permitted: { - token: getAddress(permit2Payload.permit2Authorization.permitted.token), - amount: BigInt(permit2Payload.permit2Authorization.permitted.amount), - }, - nonce: BigInt(permit2Payload.permit2Authorization.nonce), - deadline: BigInt(permit2Payload.permit2Authorization.deadline), - }, - getAddress(payer), - { - to: getAddress(permit2Payload.permit2Authorization.witness.to), - validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), - }, - permit2Payload.signature, - ], + args: buildPermit2SettleArgs(permit2Payload), }); - return _waitAndReturn(signer, tx, payload, payer); + return waitAndReturn(signer, tx, payload, payer); } catch (error) { - return _mapSettleError(error, payload, payer); - } -} - -/** - * Waits for tx receipt and returns the appropriate SettleResponse. - * - * @param signer - Signer with waitForTransactionReceipt capability - * @param tx - The transaction hash to wait for - * @param payload - The payment payload (for network info) - * @param payer - The payer address - * @returns Promise resolving to settlement response - */ -async function _waitAndReturn( - signer: Pick, - tx: `0x${string}`, - payload: PaymentPayload, - payer: `0x${string}`, -): Promise { - const receipt = await signer.waitForTransactionReceipt({ hash: tx }); - - if (receipt.status !== "success") { - return { - success: false, - errorReason: "invalid_transaction_state", - transaction: tx, - network: payload.accepted.network, - payer, - }; + return mapSettleError(error, payload, payer); } - - return { - success: true, - transaction: tx, - network: payload.accepted.network, - payer, - }; -} - -/** - * Maps contract revert errors to structured SettleResponse error reasons. - * - * @param error - The caught error - * @param payload - The payment payload (for network info) - * @param payer - The payer address - * @returns A failed SettleResponse with mapped error reason - */ -function _mapSettleError( - error: unknown, - payload: PaymentPayload, - payer: `0x${string}`, -): SettleResponse { - let errorReason = "transaction_failed"; - if (error instanceof Error) { - const message = error.message; - if (message.includes("Permit2612AmountMismatch")) { - errorReason = ErrPermit2612AmountMismatch; - } else if (message.includes("InvalidAmount")) { - errorReason = ErrPermit2InvalidAmount; - } else if (message.includes("InvalidDestination")) { - errorReason = ErrPermit2InvalidDestination; - } else if (message.includes("InvalidOwner")) { - errorReason = ErrPermit2InvalidOwner; - } else if (message.includes("PaymentTooEarly")) { - errorReason = ErrPermit2PaymentTooEarly; - } else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) { - errorReason = ErrPermit2InvalidSignature; - } else if (message.includes("InvalidNonce")) { - errorReason = ErrPermit2InvalidNonce; - } else if (message.includes("erc20_approval_tx_failed")) { - errorReason = "erc20_approval_tx_failed"; - } else { - errorReason = `transaction_failed: ${message.slice(0, 500)}`; - } - } - return { - success: false, - errorReason, - transaction: "", - network: payload.accepted.network, - payer, - }; -} - -/** - * Validates EIP-2612 permit extension data for a Permit2 payment. - * - * @param info - The EIP-2612 gas sponsoring info - * @param payer - The expected payer address - * @param tokenAddress - The expected token address - * @returns Validation result with optional invalidReason - */ -function validateEip2612PermitForPayment( - info: Eip2612GasSponsoringInfo, - payer: `0x${string}`, - tokenAddress: `0x${string}`, -): { isValid: boolean; invalidReason?: string } { - if (!validateEip2612GasSponsoringInfo(info)) { - return { isValid: false, invalidReason: "invalid_eip2612_extension_format" }; - } - - if (getAddress(info.from as `0x${string}`) !== getAddress(payer)) { - return { isValid: false, invalidReason: "eip2612_from_mismatch" }; - } - - if (getAddress(info.asset as `0x${string}`) !== tokenAddress) { - return { isValid: false, invalidReason: "eip2612_asset_mismatch" }; - } - - if (getAddress(info.spender as `0x${string}`) !== getAddress(PERMIT2_ADDRESS)) { - return { isValid: false, invalidReason: "eip2612_spender_not_permit2" }; - } - - const now = Math.floor(Date.now() / 1000); - if (BigInt(info.deadline) < BigInt(now + 6)) { - return { isValid: false, invalidReason: "eip2612_deadline_expired" }; - } - - return { isValid: true }; -} - -/** - * Splits a 65-byte EIP-2612 signature into v, r, s components. - * - * @param signature - The hex-encoded 65-byte signature - * @returns Object with v (uint8), r (bytes32), s (bytes32) - */ -function splitEip2612Signature(signature: string): { - v: number; - r: `0x${string}`; - s: `0x${string}`; -} { - const sig = signature.startsWith("0x") ? signature.slice(2) : signature; - - if (sig.length !== 130) { - throw new Error( - `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`, - ); - } - - const r = `0x${sig.slice(0, 64)}` as `0x${string}`; - const s = `0x${sig.slice(64, 128)}` as `0x${string}`; - const v = parseInt(sig.slice(128, 130), 16); - - return { v, r, s }; } diff --git a/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts b/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts index 833743e760..d5bcd5afc6 100644 --- a/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts +++ b/typescript/packages/mechanisms/evm/src/exact/facilitator/scheme.ts @@ -115,7 +115,9 @@ export class ExactEvmScheme implements SchemeNetworkFacilitator { const isPermit2 = isPermit2Payload(rawPayload); if (isPermit2) { - return settlePermit2(this.signer, payload, requirements, rawPayload, context); + return settlePermit2(this.signer, payload, requirements, rawPayload, context, { + simulateInSettle: this.config.simulateInSettle, + }); } const eip3009Payload: ExactEIP3009Payload = rawPayload; diff --git a/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts b/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts index e7a03d08f0..8f545776ff 100644 --- a/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts +++ b/typescript/packages/mechanisms/evm/test/unit/exact/facilitator.test.ts @@ -262,7 +262,7 @@ describe("ExactEvmScheme (Facilitator)", () => { }); describe("Permit2 payload verification", () => { - it("should verify Permit2 payloads with valid signature and allowance", async () => { + it("should verify Permit2 payloads with valid signature and simulation success", async () => { const requirements: PaymentRequirements = { scheme: "exact", network: "eip155:84532", @@ -273,8 +273,8 @@ describe("ExactEvmScheme (Facilitator)", () => { extra: { name: "USDC", version: "2", assetTransferMethod: "permit2" }, }; - // Mock readContract to return sufficient allowance and balance - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt("10000000000")); + // Simulation of settle() on the proxy succeeds (readContract doesn't throw) + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const permit2Payload: PaymentPayload = { x402Version: 2, @@ -305,7 +305,7 @@ describe("ExactEvmScheme (Facilitator)", () => { expect(result.payer).toBe(mockClientSigner.address); }); - it("should reject Permit2 payloads with insufficient allowance", async () => { + it("should reject Permit2 payloads when simulation fails and allowance is insufficient", async () => { const requirements: PaymentRequirements = { scheme: "exact", network: "eip155:84532", @@ -316,8 +316,31 @@ describe("ExactEvmScheme (Facilitator)", () => { extra: { name: "USDC", version: "2", assetTransferMethod: "permit2" }, }; - // Mock readContract to return zero allowance - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt(0)); + // Simulation fails (settle throws), diagnostic multicall returns proxy OK, balance OK, allowance 0 + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === x402ExactPermit2ProxyAddress) { + return Promise.reject(new Error("execution reverted")); + } + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { + success: true, + returnData: "0x000000000000000000000000000000000022D473030F116dDEE9F6B43aC78BA3", + }, + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000000000000f4240", + }, + { + success: true, + returnData: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + ]); + } + return Promise.resolve(BigInt(0)); + }); const permit2Payload: PaymentPayload = { x402Version: 2, @@ -485,8 +508,8 @@ describe("ExactEvmScheme (Facilitator)", () => { extra: { name: "USDC", version: "2", assetTransferMethod: "permit2" }, }; - // Mock readContract to return sufficient allowance and balance - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt("10000000000")); + // settle's re-verify has simulate=false (default), so no simulation readContract needed + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const permit2Payload: PaymentPayload = { x402Version: 2, @@ -519,7 +542,7 @@ describe("ExactEvmScheme (Facilitator)", () => { expect(mockFacilitatorSigner.writeContract).toHaveBeenCalled(); }); - it("should fail Permit2 settlement when verification fails", async () => { + it("should fail Permit2 settlement when signature verification fails", async () => { const requirements: PaymentRequirements = { scheme: "exact", network: "eip155:84532", @@ -530,8 +553,8 @@ describe("ExactEvmScheme (Facilitator)", () => { extra: { name: "USDC", version: "2", assetTransferMethod: "permit2" }, }; - // Mock readContract to return zero allowance - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt(0)); + // Signature verification fails + mockFacilitatorSigner.verifyTypedData = vi.fn().mockResolvedValue(false); const permit2Payload: PaymentPayload = { x402Version: 2, @@ -559,7 +582,7 @@ describe("ExactEvmScheme (Facilitator)", () => { const result = await facilitator.settle(permit2Payload, requirements); expect(result.success).toBe(false); - expect(result.errorReason).toBe("permit2_allowance_required"); + expect(result.errorReason).toBe("invalid_permit2_signature"); expect(result.payer).toBe(mockClientSigner.address); }); }); @@ -630,12 +653,9 @@ describe("ExactEvmScheme (Facilitator)", () => { }); describe("EIP-2612 Gas Sponsoring - Verify", () => { - it("should accept valid EIP-2612 extension when Permit2 allowance is 0", async () => { - // Mock: allowance returns 0, then balance returns sufficient - mockFacilitatorSigner.readContract = vi - .fn() - .mockResolvedValueOnce(0n) // allowance check = 0 - .mockResolvedValueOnce(BigInt("10000000")); // balance check + it("should accept valid EIP-2612 extension when settleWithPermit simulation succeeds", async () => { + // Simulation of settleWithPermit on proxy succeeds + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const permit2Requirements: PaymentRequirements = { scheme: "exact", @@ -647,7 +667,6 @@ describe("ExactEvmScheme (Facilitator)", () => { extra: { assetTransferMethod: "permit2", name: "USDC", version: "2" }, }; - // Create a Permit2 payload const permit2ClientSigner: ClientEvmSigner = { address: "0x1234567890123456789012345678901234567890", signTypedData: vi.fn().mockResolvedValue("0x" + "ab".repeat(32) + "cd".repeat(32) + "1b"), @@ -656,7 +675,6 @@ describe("ExactEvmScheme (Facilitator)", () => { const permit2Client = new ClientExactEvmScheme(permit2ClientSigner); const paymentPayload = await permit2Client.createPaymentPayload(2, permit2Requirements); - // Add EIP-2612 extension data const now = Math.floor(Date.now() / 1000); const fullPayload: PaymentPayload = { ...paymentPayload, @@ -681,17 +699,38 @@ describe("ExactEvmScheme (Facilitator)", () => { }; const result = await facilitator.verify(fullPayload, permit2Requirements); - // Should pass verify (EIP-2612 extension provides the permit) expect(result).toBeDefined(); - // It may still fail on signature verification (mock), but should NOT fail with permit2_allowance_required if (!result.isValid) { expect(result.invalidReason).not.toBe("permit2_allowance_required"); } }); - it("should reject when allowance is 0 and no EIP-2612 extension", async () => { - // Mock: allowance returns 0 - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); // allowance check = 0 + it("should reject when simulation fails and no extension present (allowance insufficient)", async () => { + // Simulation fails, diagnostic multicall returns low allowance + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === x402ExactPermit2ProxyAddress) { + return Promise.reject(new Error("execution reverted")); + } + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { + success: true, + returnData: "0x000000000000000000000000000000000022D473030F116dDEE9F6B43aC78BA3", + }, + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000000000000f4240", + }, + { + success: true, + returnData: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + ]); + } + return Promise.resolve(BigInt(0)); + }); const permit2Requirements: PaymentRequirements = { scheme: "exact", @@ -715,20 +754,15 @@ describe("ExactEvmScheme (Facilitator)", () => { ...paymentPayload, accepted: permit2Requirements, resource: { url: "https://test.com", description: "", mimeType: "" }, - // NO eip2612GasSponsoring extension }; const result = await facilitator.verify(fullPayload, permit2Requirements); - // Should fail with permit2_allowance_required since there's no EIP-2612 extension expect(result.isValid).toBe(false); expect(result.invalidReason).toBe("permit2_allowance_required"); }); it("should reject EIP-2612 extension with wrong spender", async () => { - mockFacilitatorSigner.readContract = vi - .fn() - .mockResolvedValueOnce(0n) // allowance = 0 - .mockResolvedValueOnce(BigInt("10000000")); // balance + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const permit2Requirements: PaymentRequirements = { scheme: "exact", @@ -1064,14 +1098,8 @@ describe("ExactEvmScheme (Facilitator)", () => { } it("should call settleWithPermit when EIP-2612 extension is present", async () => { - // Mock: allowance=0 (verify), balance=sufficient, allowance=0 (settle re-verify), balance=sufficient - mockFacilitatorSigner.readContract = vi - .fn() - .mockImplementation(({ functionName }: { functionName: string }) => { - if (functionName === "allowance") return Promise.resolve(0n); - if (functionName === "balanceOf") return Promise.resolve(BigInt("10000000")); - return Promise.resolve(0n); - }); + // settle's re-verify has simulate=false, so readContract is not called for simulation + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const payload = makePermit2Payload(makeEip2612Extension()); const result = await facilitator.settle(payload, permit2Requirements); @@ -1079,15 +1107,14 @@ describe("ExactEvmScheme (Facilitator)", () => { expect(result.success).toBe(true); expect(result.transaction).toBe("0xtxhash"); - // Verify writeContract was called with settleWithPermit const writeCall = (mockFacilitatorSigner.writeContract as ReturnType).mock .calls[0][0]; expect(writeCall.functionName).toBe("settleWithPermit"); }); it("should call settle (not settleWithPermit) when no EIP-2612 extension", async () => { - // Mock: allowance=sufficient, balance=sufficient - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt("10000000000")); + // settle's re-verify has simulate=false + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const payload = makePermit2Payload(); const result = await facilitator.settle(payload, permit2Requirements); @@ -1095,14 +1122,13 @@ describe("ExactEvmScheme (Facilitator)", () => { expect(result.success).toBe(true); expect(result.transaction).toBe("0xtxhash"); - // Verify writeContract was called with settle (not settleWithPermit) const writeCall = (mockFacilitatorSigner.writeContract as ReturnType).mock .calls[0][0]; expect(writeCall.functionName).toBe("settle"); }); it("should map Permit2612AmountMismatch contract revert to permit2_2612_amount_mismatch", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt("10000000000")); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); mockFacilitatorSigner.writeContract = vi .fn() .mockRejectedValue(new Error("execution reverted: Permit2612AmountMismatch()")); @@ -1115,7 +1141,7 @@ describe("ExactEvmScheme (Facilitator)", () => { }); it("should map InvalidAmount contract revert to permit2_invalid_amount", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt("10000000000")); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); mockFacilitatorSigner.writeContract = vi .fn() .mockRejectedValue(new Error("execution reverted: InvalidAmount()")); @@ -1128,7 +1154,7 @@ describe("ExactEvmScheme (Facilitator)", () => { }); it("should map InvalidNonce contract revert to permit2_invalid_nonce", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(BigInt("10000000000")); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); mockFacilitatorSigner.writeContract = vi .fn() .mockRejectedValue(new Error("execution reverted: InvalidNonce()")); @@ -1141,13 +1167,8 @@ describe("ExactEvmScheme (Facilitator)", () => { }); it("should pass correct EIP-2612 permit struct to settleWithPermit", async () => { - mockFacilitatorSigner.readContract = vi - .fn() - .mockImplementation(({ functionName }: { functionName: string }) => { - if (functionName === "allowance") return Promise.resolve(0n); - if (functionName === "balanceOf") return Promise.resolve(BigInt("10000000")); - return Promise.resolve(0n); - }); + // settle's re-verify has simulate=false + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const extensions = makeEip2612Extension(); const payload = makePermit2Payload(extensions); @@ -1157,14 +1178,12 @@ describe("ExactEvmScheme (Facilitator)", () => { .calls[0][0]; expect(writeCall.functionName).toBe("settleWithPermit"); - // First arg to settleWithPermit is the EIP-2612 permit struct (value, deadline, r, s, v) const permit2612Struct = writeCall.args[0]; expect(permit2612Struct.value).toBeDefined(); expect(permit2612Struct.deadline).toBeDefined(); expect(permit2612Struct.r).toBeDefined(); expect(permit2612Struct.s).toBeDefined(); expect(permit2612Struct.v).toBeDefined(); - // v should be a number (27 or 28) expect(typeof permit2612Struct.v).toBe("number"); }); }); @@ -1245,8 +1264,32 @@ describe("ExactEvmScheme (Facilitator)", () => { }; } - it("should reject when allowance is 0 and no ERC-20 extension (no context)", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); + it("should reject when simulation fails and no ERC-20 extension (no context)", async () => { + // Simulation of settle() fails, diagnostic multicall shows low allowance + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === x402ExactPermit2ProxyAddress) { + return Promise.reject(new Error("execution reverted")); + } + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { + success: true, + returnData: "0x000000000000000000000000000000000022D473030F116dDEE9F6B43aC78BA3", + }, + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000000000000f4240", + }, + { + success: true, + returnData: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + ]); + } + return Promise.resolve(BigInt(0)); + }); const payload = makeErc20Permit2Payload(); const result = await facilitator.verify(payload, erc20Requirements); @@ -1256,7 +1299,7 @@ describe("ExactEvmScheme (Facilitator)", () => { }); it("should reject when ERC-20 extension has invalid format (bad address)", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const payload = makeErc20Permit2Payload({ erc20ApprovalGasSponsoring: { @@ -1279,7 +1322,7 @@ describe("ExactEvmScheme (Facilitator)", () => { }); it("should reject when ERC-20 extension `from` doesn't match payer", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const payload = makeErc20Permit2Payload({ erc20ApprovalGasSponsoring: { @@ -1302,7 +1345,7 @@ describe("ExactEvmScheme (Facilitator)", () => { }); it("should reject when ERC-20 extension `asset` doesn't match token", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const payload = makeErc20Permit2Payload({ erc20ApprovalGasSponsoring: { @@ -1325,7 +1368,7 @@ describe("ExactEvmScheme (Facilitator)", () => { }); it("should reject when ERC-20 extension spender is not PERMIT2_ADDRESS", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const payload = makeErc20Permit2Payload({ erc20ApprovalGasSponsoring: { @@ -1347,11 +1390,31 @@ describe("ExactEvmScheme (Facilitator)", () => { expect(result.invalidReason).toBe("erc20_approval_spender_not_permit2"); }); - it("should accept when allowance insufficient but valid ERC-20 extension present", async () => { - // allowance=0 (verifyPermit2 returns permit2_allowance_required, scheme handles it) - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); + it("should accept when valid ERC-20 extension present and prerequisites pass", async () => { + // checkPermit2Prerequisites multicall: proxy deployed + sufficient token balance + sufficient ETH for gas + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { + success: true, + returnData: "0x000000000000000000000000000000000022D473030F116dDEE9F6B43aC78BA3", + }, + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000000000000f4240", + }, + // ETH balance: 0.001 ETH (well above the gas floor of 70_000 * 1 gwei) + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000038D7EA4C68000", + }, + ]); + } + return Promise.resolve(undefined); + }); - // Mock viem functions used in validateErc20ApprovalForPayment const { parseTransaction, recoverTransactionAddress } = await import("viem"); vi.mocked(parseTransaction).mockReturnValue({ to: TOKEN_ADDRESS, @@ -1362,14 +1425,13 @@ describe("ExactEvmScheme (Facilitator)", () => { const payload = makeErc20Permit2Payload(makeValidErc20Extension()); const result = await facilitator.verify(payload, erc20Requirements, makeErc20Context()); - // Should NOT fail with permit2_allowance_required if (!result.isValid) { expect(result.invalidReason).not.toBe("permit2_allowance_required"); } }); it("should reject when calldata targets wrong address (not PERMIT2_ADDRESS)", async () => { - mockFacilitatorSigner.readContract = vi.fn().mockResolvedValueOnce(0n); + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const wrongSpenderCalldata = "0x095ea7b3" + @@ -1389,6 +1451,155 @@ describe("ExactEvmScheme (Facilitator)", () => { expect(result.isValid).toBe(false); expect(result.invalidReason).toBe("erc20_approval_tx_wrong_spender"); }); + + it("Path 2 simulation: should accept when extension signer simulateTransactions returns true", async () => { + const { parseTransaction, recoverTransactionAddress } = await import("viem"); + vi.mocked(parseTransaction).mockReturnValue({ + to: TOKEN_ADDRESS, + data: APPROVE_CALLDATA as `0x${string}`, + } as any); + vi.mocked(recoverTransactionAddress).mockResolvedValue(PAYER); + + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); + + const mockSimulateTransactions = vi.fn().mockResolvedValue(true); + + const mockContext = { + getExtension: vi.fn().mockImplementation((key: string) => { + if (key === ERC20_APPROVAL_GAS_SPONSORING_KEY) { + return { + key: ERC20_APPROVAL_GAS_SPONSORING_KEY, + signer: { + ...mockFacilitatorSigner, + sendTransactions: vi.fn(), + simulateTransactions: mockSimulateTransactions, + }, + }; + } + return undefined; + }), + }; + + const payload = makeErc20Permit2Payload(makeValidErc20Extension()); + const result = await facilitator.verify(payload, erc20Requirements, mockContext); + + expect(mockSimulateTransactions).toHaveBeenCalledOnce(); + const bundle = mockSimulateTransactions.mock.calls[0][0]; + expect(bundle[0]).toBe(MOCK_SIGNED_TX); + expect(bundle[1]).toHaveProperty("to"); + expect(bundle[1]).toHaveProperty("data"); + expect(result.isValid).toBe(true); + }); + + it("Path 2 simulation: should reject with diagnostic reason when simulateTransactions returns false", async () => { + const { parseTransaction, recoverTransactionAddress } = await import("viem"); + vi.mocked(parseTransaction).mockReturnValue({ + to: TOKEN_ADDRESS, + data: APPROVE_CALLDATA as `0x${string}`, + } as any); + vi.mocked(recoverTransactionAddress).mockResolvedValue(PAYER); + + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + // diagnostic multicall: proxy deployed, balance insufficient + return Promise.resolve([ + { + success: true, + returnData: "0x000000000000000000000000000000000022D473030F116dDEE9F6B43aC78BA3", + }, + { + success: true, + returnData: "0x0000000000000000000000000000000000000000000000000000000000000001", + }, + { + success: true, + returnData: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + ]); + } + return Promise.resolve(undefined); + }); + + const mockSimulateTransactions = vi.fn().mockResolvedValue(false); + + const mockContext = { + getExtension: vi.fn().mockImplementation((key: string) => { + if (key === ERC20_APPROVAL_GAS_SPONSORING_KEY) { + return { + key: ERC20_APPROVAL_GAS_SPONSORING_KEY, + signer: { + ...mockFacilitatorSigner, + sendTransactions: vi.fn(), + simulateTransactions: mockSimulateTransactions, + }, + }; + } + return undefined; + }), + }; + + const payload = makeErc20Permit2Payload(makeValidErc20Extension()); + const result = await facilitator.verify(payload, erc20Requirements, mockContext); + + expect(result.isValid).toBe(false); + expect(result.invalidReason).toBe(Errors.ErrPermit2InsufficientBalance); + }); + + it("Path 2 simulation: should fall back to checkPermit2Prerequisites when simulateTransactions is absent", async () => { + const { parseTransaction, recoverTransactionAddress } = await import("viem"); + vi.mocked(parseTransaction).mockReturnValue({ + to: TOKEN_ADDRESS, + data: APPROVE_CALLDATA as `0x${string}`, + } as any); + vi.mocked(recoverTransactionAddress).mockResolvedValue(PAYER); + + // prerequisites pass: proxy deployed + sufficient token balance + sufficient ETH for gas + mockFacilitatorSigner.readContract = vi + .fn() + .mockImplementation(({ address }: { address: string }) => { + if (address === MULTICALL3_ADDRESS) { + return Promise.resolve([ + { + success: true, + returnData: "0x000000000000000000000000000000000022D473030F116dDEE9F6B43aC78BA3", + }, + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000000000000f4240", + }, + // ETH balance: 0.001 ETH (well above the gas floor of 70_000 * 1 gwei) + { + success: true, + returnData: "0x00000000000000000000000000000000000000000000000000038D7EA4C68000", + }, + ]); + } + return Promise.resolve(undefined); + }); + + // signer has sendTransactions but no simulateTransactions (legacy) + const mockContext = { + getExtension: vi.fn().mockImplementation((key: string) => { + if (key === ERC20_APPROVAL_GAS_SPONSORING_KEY) { + return { + key: ERC20_APPROVAL_GAS_SPONSORING_KEY, + signer: { + ...mockFacilitatorSigner, + sendTransactions: vi.fn(), + }, + }; + } + return undefined; + }), + }; + + const payload = makeErc20Permit2Payload(makeValidErc20Extension()); + const result = await facilitator.verify(payload, erc20Requirements, mockContext); + + expect(result.isValid).toBe(true); + }); }); describe("ERC-20 Approval Gas Sponsoring - Settlement", () => { @@ -1462,14 +1673,8 @@ describe("ExactEvmScheme (Facilitator)", () => { } as any); vi.mocked(recoverTransactionAddress).mockResolvedValue(PAYER); - // Base signer: allowance=0 (re-verify sees ERC-20 extension in context and accepts it) - mockFacilitatorSigner.readContract = vi - .fn() - .mockImplementation(({ functionName }: { functionName: string }) => { - if (functionName === "allowance") return Promise.resolve(0n); - if (functionName === "balanceOf") return Promise.resolve(BigInt("10000000")); - return Promise.resolve(0n); - }); + // settle's re-verify has simulate=false, so no simulation calls + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const SETTLE_TX_HASH = "0xsettle_tx_hash_mock" as `0x${string}`; const mockSendTransactions = vi.fn().mockResolvedValue([SETTLE_TX_HASH]); @@ -1521,13 +1726,8 @@ describe("ExactEvmScheme (Facilitator)", () => { } as any); vi.mocked(recoverTransactionAddress).mockResolvedValue(PAYER); - mockFacilitatorSigner.readContract = vi - .fn() - .mockImplementation(({ functionName }: { functionName: string }) => { - if (functionName === "allowance") return Promise.resolve(0n); - if (functionName === "balanceOf") return Promise.resolve(BigInt("10000000")); - return Promise.resolve(0n); - }); + // settle's re-verify has simulate=false + mockFacilitatorSigner.readContract = vi.fn().mockResolvedValue(undefined); const selectedSignerSendTransactions = vi .fn() From 26ed19296dbd12bb5c39915151f1484f5c134e8d Mon Sep 17 00:00:00 2001 From: phdargen Date: Tue, 17 Mar 2026 00:30:18 +0900 Subject: [PATCH 072/129] chore: version typescript packages (#1636) --- typescript/.changeset/fifty-doodles-strive.md | 5 ----- typescript/.changeset/fifty-feet-cut.md | 5 ----- .../.changeset/improve-permit2-gas-sponsoring.md | 6 ------ typescript/.changeset/offer-receipt-extension.md | 5 ----- typescript/.changeset/slimy-baths-marry.md | 5 ----- .../support-express-style-route-params.md | 5 ----- typescript/.changeset/ten-knives-trade.md | 5 ----- typescript/.changeset/wise-rivers-film.md | 5 ----- typescript/packages/core/CHANGELOG.md | 6 ++++++ typescript/packages/core/package.json | 2 +- typescript/packages/extensions/CHANGELOG.md | 13 +++++++++++++ typescript/packages/extensions/package.json | 2 +- typescript/packages/http/axios/CHANGELOG.md | 7 +++++++ typescript/packages/http/axios/package.json | 2 +- typescript/packages/http/express/CHANGELOG.md | 13 +++++++++++++ typescript/packages/http/express/package.json | 2 +- typescript/packages/http/fetch/CHANGELOG.md | 7 +++++++ typescript/packages/http/fetch/package.json | 2 +- typescript/packages/http/hono/CHANGELOG.md | 13 +++++++++++++ typescript/packages/http/hono/package.json | 2 +- typescript/packages/http/next/CHANGELOG.md | 13 +++++++++++++ typescript/packages/http/next/package.json | 2 +- typescript/packages/http/paywall/CHANGELOG.md | 8 ++++++++ typescript/packages/http/paywall/package.json | 2 +- typescript/packages/mcp/CHANGELOG.md | 7 +++++++ typescript/packages/mcp/package.json | 2 +- typescript/packages/mechanisms/aptos/CHANGELOG.md | 7 +++++++ typescript/packages/mechanisms/aptos/package.json | 2 +- typescript/packages/mechanisms/evm/CHANGELOG.md | 13 +++++++++++++ typescript/packages/mechanisms/evm/package.json | 2 +- typescript/packages/mechanisms/stellar/CHANGELOG.md | 8 ++++++++ typescript/packages/mechanisms/stellar/package.json | 2 +- typescript/packages/mechanisms/svm/CHANGELOG.md | 7 +++++++ typescript/packages/mechanisms/svm/package.json | 2 +- 34 files changed, 135 insertions(+), 54 deletions(-) delete mode 100644 typescript/.changeset/fifty-doodles-strive.md delete mode 100644 typescript/.changeset/fifty-feet-cut.md delete mode 100644 typescript/.changeset/improve-permit2-gas-sponsoring.md delete mode 100644 typescript/.changeset/offer-receipt-extension.md delete mode 100644 typescript/.changeset/slimy-baths-marry.md delete mode 100644 typescript/.changeset/support-express-style-route-params.md delete mode 100644 typescript/.changeset/ten-knives-trade.md delete mode 100644 typescript/.changeset/wise-rivers-film.md diff --git a/typescript/.changeset/fifty-doodles-strive.md b/typescript/.changeset/fifty-doodles-strive.md deleted file mode 100644 index fb8f25d120..0000000000 --- a/typescript/.changeset/fifty-doodles-strive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/evm': patch ---- - -Added simulation to permit2 verify and (optional) settle diff --git a/typescript/.changeset/fifty-feet-cut.md b/typescript/.changeset/fifty-feet-cut.md deleted file mode 100644 index 7d84f3f38f..0000000000 --- a/typescript/.changeset/fifty-feet-cut.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/extensions': patch ---- - -Removed dependencie on node’s crypto module diff --git a/typescript/.changeset/improve-permit2-gas-sponsoring.md b/typescript/.changeset/improve-permit2-gas-sponsoring.md deleted file mode 100644 index 612cb95178..0000000000 --- a/typescript/.changeset/improve-permit2-gas-sponsoring.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@x402/evm': minor -'@x402/extensions': minor ---- - -Replaced `sendRawApprovalAndSettle` with a generic `sendTransactions` signer method that accepts an array of pre-signed serialized transactions or unsigned call intents. The signer owns execution strategy (sequential, batched, or atomic bundling). Closed fail-open verification paths, aligned Permit2 amount check to exact match, and added `signerForNetwork` to the extensions package. diff --git a/typescript/.changeset/offer-receipt-extension.md b/typescript/.changeset/offer-receipt-extension.md deleted file mode 100644 index 851ab4bb1a..0000000000 --- a/typescript/.changeset/offer-receipt-extension.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/extensions': minor ---- - -Added offer-receipt extension to enable signed offers and receipts in x402 payment flows diff --git a/typescript/.changeset/slimy-baths-marry.md b/typescript/.changeset/slimy-baths-marry.md deleted file mode 100644 index f62e5261e2..0000000000 --- a/typescript/.changeset/slimy-baths-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/evm': patch ---- - -Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling to prevent facilitator grieving and account for implementation dependent verifyTypedData diff --git a/typescript/.changeset/support-express-style-route-params.md b/typescript/.changeset/support-express-style-route-params.md deleted file mode 100644 index 449fc73d09..0000000000 --- a/typescript/.changeset/support-express-style-route-params.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@x402/core": patch ---- - -Added support for Express-style `:param` dynamic route parameters in route matching. Routes like `/api/users/:id` and `/api/chapters/:seriesId/:chapterId` now match correctly alongside the existing `[param]` (Next.js) and `*` (wildcard) patterns. diff --git a/typescript/.changeset/ten-knives-trade.md b/typescript/.changeset/ten-knives-trade.md deleted file mode 100644 index 45e4be2dae..0000000000 --- a/typescript/.changeset/ten-knives-trade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/stellar': patch ---- - -Bump "@stellar/stellar-sdk" dependency and refactor API call for better performance diff --git a/typescript/.changeset/wise-rivers-film.md b/typescript/.changeset/wise-rivers-film.md deleted file mode 100644 index e0d9af184a..0000000000 --- a/typescript/.changeset/wise-rivers-film.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@x402/paywall': patch ---- - -Fixed encoding of characters outside of the Latin1 range diff --git a/typescript/packages/core/CHANGELOG.md b/typescript/packages/core/CHANGELOG.md index fe72eea1e5..62a7473dbd 100644 --- a/typescript/packages/core/CHANGELOG.md +++ b/typescript/packages/core/CHANGELOG.md @@ -1,5 +1,11 @@ # @x402/core Changelog +## 2.7.0 + +### Minor Changes + +- 8931cb3: Added support for Express-style `:param` dynamic route parameters in route matching. Routes like `/api/users/:id` and `/api/chapters/:seriesId/:chapterId` now match correctly alongside the existing `[param]` (Next.js) and `*` (wildcard) patterns. + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/core/package.json b/typescript/packages/core/package.json index 2153ab4ff2..fe8e702d9c 100644 --- a/typescript/packages/core/package.json +++ b/typescript/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@x402/core", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/extensions/CHANGELOG.md b/typescript/packages/extensions/CHANGELOG.md index 899ed31e03..55431015ba 100644 --- a/typescript/packages/extensions/CHANGELOG.md +++ b/typescript/packages/extensions/CHANGELOG.md @@ -1,5 +1,18 @@ # @x402/extensions Changelog +## 2.7.0 + +### Minor Changes + +- 8b731cb: Replaced `sendRawApprovalAndSettle` with a generic `sendTransactions` signer method that accepts an array of pre-signed serialized transactions or unsigned call intents. The signer owns execution strategy (sequential, batched, or atomic bundling). Closed fail-open verification paths, aligned Permit2 amount check to exact match, and added `signerForNetwork` to the extensions package. +- f2bbb5c: Added offer-receipt extension to enable signed offers and receipts in x402 payment flows + +### Patch Changes + +- 34d2442: Removed dependencie on node’s crypto module +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/extensions/package.json b/typescript/packages/extensions/package.json index e7377d126f..0f546cbc19 100644 --- a/typescript/packages/extensions/package.json +++ b/typescript/packages/extensions/package.json @@ -1,6 +1,6 @@ { "name": "@x402/extensions", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/http/axios/CHANGELOG.md b/typescript/packages/http/axios/CHANGELOG.md index 1de2ded144..6af267bca5 100644 --- a/typescript/packages/http/axios/CHANGELOG.md +++ b/typescript/packages/http/axios/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/axios Changelog +## 2.7.0 + +### Minor Changes + +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/http/axios/package.json b/typescript/packages/http/axios/package.json index ebd6d0fd90..726f6e4585 100644 --- a/typescript/packages/http/axios/package.json +++ b/typescript/packages/http/axios/package.json @@ -1,6 +1,6 @@ { "name": "@x402/axios", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/express/CHANGELOG.md b/typescript/packages/http/express/CHANGELOG.md index 155288ac55..863d72bbe2 100644 --- a/typescript/packages/http/express/CHANGELOG.md +++ b/typescript/packages/http/express/CHANGELOG.md @@ -1,5 +1,18 @@ # @x402/express Changelog +## 2.7.0 + +### Minor Changes + +- Updated dependencies [34d2442] +- Updated dependencies [8b731cb] +- Updated dependencies [f2bbb5c] +- Updated dependencies [8931cb3] +- Updated dependencies [34d2442] + - @x402/extensions@2.7.0 + - @x402/core@2.7.0 + - @x402/paywall@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/http/express/package.json b/typescript/packages/http/express/package.json index a733f9e1b3..7f2182c04a 100644 --- a/typescript/packages/http/express/package.json +++ b/typescript/packages/http/express/package.json @@ -1,6 +1,6 @@ { "name": "@x402/express", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/fetch/CHANGELOG.md b/typescript/packages/http/fetch/CHANGELOG.md index 4e530af0dd..b76bd761d8 100644 --- a/typescript/packages/http/fetch/CHANGELOG.md +++ b/typescript/packages/http/fetch/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/fetch Changelog +## 2.7.0 + +### Minor Changes + +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/http/fetch/package.json b/typescript/packages/http/fetch/package.json index 5d47a02b27..7ada139ac8 100644 --- a/typescript/packages/http/fetch/package.json +++ b/typescript/packages/http/fetch/package.json @@ -1,6 +1,6 @@ { "name": "@x402/fetch", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/hono/CHANGELOG.md b/typescript/packages/http/hono/CHANGELOG.md index cb43832902..ff19cd8e13 100644 --- a/typescript/packages/http/hono/CHANGELOG.md +++ b/typescript/packages/http/hono/CHANGELOG.md @@ -1,5 +1,18 @@ # @x402/hono Changelog +## 2.7.0 + +### Minor Changes + +- Updated dependencies [34d2442] +- Updated dependencies [8b731cb] +- Updated dependencies [f2bbb5c] +- Updated dependencies [8931cb3] +- Updated dependencies [34d2442] + - @x402/extensions@2.7.0 + - @x402/core@2.7.0 + - @x402/paywall@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/http/hono/package.json b/typescript/packages/http/hono/package.json index 95f49f7733..adb82038d1 100644 --- a/typescript/packages/http/hono/package.json +++ b/typescript/packages/http/hono/package.json @@ -1,6 +1,6 @@ { "name": "@x402/hono", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/next/CHANGELOG.md b/typescript/packages/http/next/CHANGELOG.md index 6738d2183a..256a872e93 100644 --- a/typescript/packages/http/next/CHANGELOG.md +++ b/typescript/packages/http/next/CHANGELOG.md @@ -1,5 +1,18 @@ # @x402/next Changelog +## 2.7.0 + +### Minor Changes + +- Updated dependencies [34d2442] +- Updated dependencies [8b731cb] +- Updated dependencies [f2bbb5c] +- Updated dependencies [8931cb3] +- Updated dependencies [34d2442] + - @x402/extensions@2.7.0 + - @x402/core@2.7.0 + - @x402/paywall@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/http/next/package.json b/typescript/packages/http/next/package.json index d9a14168bf..aa1f7f645c 100644 --- a/typescript/packages/http/next/package.json +++ b/typescript/packages/http/next/package.json @@ -1,6 +1,6 @@ { "name": "@x402/next", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/http/paywall/CHANGELOG.md b/typescript/packages/http/paywall/CHANGELOG.md index 6d73bf3ec3..b507251ea3 100644 --- a/typescript/packages/http/paywall/CHANGELOG.md +++ b/typescript/packages/http/paywall/CHANGELOG.md @@ -1,5 +1,13 @@ # @x402/paywall Changelog +## 2.7.0 + +### Minor Changes + +- 34d2442: Fixed encoding of characters outside of the Latin1 range +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/http/paywall/package.json b/typescript/packages/http/paywall/package.json index f44301b143..fb62753479 100644 --- a/typescript/packages/http/paywall/package.json +++ b/typescript/packages/http/paywall/package.json @@ -1,6 +1,6 @@ { "name": "@x402/paywall", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/index.d.ts", diff --git a/typescript/packages/mcp/CHANGELOG.md b/typescript/packages/mcp/CHANGELOG.md index a430aa321b..5d8b907d0e 100644 --- a/typescript/packages/mcp/CHANGELOG.md +++ b/typescript/packages/mcp/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/mcp Changelog +## 2.7.0 + +### Minor Changes + +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/mcp/package.json b/typescript/packages/mcp/package.json index c06e6ebb68..0029cedd81 100644 --- a/typescript/packages/mcp/package.json +++ b/typescript/packages/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@x402/mcp", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/aptos/CHANGELOG.md b/typescript/packages/mechanisms/aptos/CHANGELOG.md index 19521f2fa5..bfb453de5a 100644 --- a/typescript/packages/mechanisms/aptos/CHANGELOG.md +++ b/typescript/packages/mechanisms/aptos/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/aptos +## 2.7.0 + +### Minor Changes + +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/mechanisms/aptos/package.json b/typescript/packages/mechanisms/aptos/package.json index 5385734f2f..a86fa2274b 100644 --- a/typescript/packages/mechanisms/aptos/package.json +++ b/typescript/packages/mechanisms/aptos/package.json @@ -1,6 +1,6 @@ { "name": "@x402/aptos", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/evm/CHANGELOG.md b/typescript/packages/mechanisms/evm/CHANGELOG.md index 310ccccdaa..710487b017 100644 --- a/typescript/packages/mechanisms/evm/CHANGELOG.md +++ b/typescript/packages/mechanisms/evm/CHANGELOG.md @@ -1,5 +1,18 @@ # @x402/evm Changelog +## 2.7.0 + +### Minor Changes + +- 8b731cb: Replaced `sendRawApprovalAndSettle` with a generic `sendTransactions` signer method that accepts an array of pre-signed serialized transactions or unsigned call intents. The signer owns execution strategy (sequential, batched, or atomic bundling). Closed fail-open verification paths, aligned Permit2 amount check to exact match, and added `signerForNetwork` to the extensions package. + +### Patch Changes + +- d8e9f3f: Added simulation to permit2 verify and (optional) settle +- 1a6e08b: Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling to prevent facilitator grieving and account for implementation dependent verifyTypedData +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/mechanisms/evm/package.json b/typescript/packages/mechanisms/evm/package.json index c8efeba7ac..9c9045d26e 100644 --- a/typescript/packages/mechanisms/evm/package.json +++ b/typescript/packages/mechanisms/evm/package.json @@ -1,6 +1,6 @@ { "name": "@x402/evm", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/stellar/CHANGELOG.md b/typescript/packages/mechanisms/stellar/CHANGELOG.md index e6ac674090..cbdd3a4856 100644 --- a/typescript/packages/mechanisms/stellar/CHANGELOG.md +++ b/typescript/packages/mechanisms/stellar/CHANGELOG.md @@ -1,5 +1,13 @@ # @x402/stellar Changelog +## 2.7.0 + +### Minor Changes + +- c92c0d1: Bump "@stellar/stellar-sdk" dependency and refactor API call for better performance +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 - Implement x402 v2 protocol support for the Stellar mechanism (exact scheme). diff --git a/typescript/packages/mechanisms/stellar/package.json b/typescript/packages/mechanisms/stellar/package.json index af03da5b1a..4588806bb7 100644 --- a/typescript/packages/mechanisms/stellar/package.json +++ b/typescript/packages/mechanisms/stellar/package.json @@ -1,6 +1,6 @@ { "name": "@x402/stellar", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", diff --git a/typescript/packages/mechanisms/svm/CHANGELOG.md b/typescript/packages/mechanisms/svm/CHANGELOG.md index 525d6ebd55..f06f3f720a 100644 --- a/typescript/packages/mechanisms/svm/CHANGELOG.md +++ b/typescript/packages/mechanisms/svm/CHANGELOG.md @@ -1,5 +1,12 @@ # @x402/svm Changelog +## 2.7.0 + +### Minor Changes + +- Updated dependencies [8931cb3] + - @x402/core@2.7.0 + ## 2.6.0 ### Minor Changes diff --git a/typescript/packages/mechanisms/svm/package.json b/typescript/packages/mechanisms/svm/package.json index cd7d777b59..ec07b0f53b 100644 --- a/typescript/packages/mechanisms/svm/package.json +++ b/typescript/packages/mechanisms/svm/package.json @@ -1,6 +1,6 @@ { "name": "@x402/svm", - "version": "2.6.0", + "version": "2.7.0", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "types": "./dist/cjs/index.d.ts", From 4c1e44fb2f84898fcc5e4622cb689b3c4e82ef1e Mon Sep 17 00:00:00 2001 From: Ziyang Liu <71600334+ziyangliu-666@users.noreply.github.com> Date: Tue, 17 Mar 2026 00:24:38 +0800 Subject: [PATCH 073/129] fix(python): handle invalid facilitator responses (#1506) * fix(python): handle invalid facilitator responses * fix(go,typescript): handle invalid facilitator responses * fix(go): preserve empty supported responses * fix(typescript): address core CI failures * fix(http): address review feedback * fix(typescript): address lint and format check failures --- go/.changeset/facilitator-response-errors.md | 5 + go/http/facilitator_client.go | 191 +++++++++++++++--- go/http/facilitator_client_test.go | 85 +++++++- python/x402/changelog.d/545.bugfix.md | 1 + python/x402/http/facilitator_client.py | 58 +++++- python/x402/http/facilitator_client_base.py | 4 + python/x402/http/middleware/fastapi.py | 21 +- python/x402/http/middleware/flask.py | 27 ++- .../unit/http/middleware/test_fastapi.py | 97 +++++++++ .../tests/unit/http/middleware/test_flask.py | 83 ++++++++ .../unit/http/test_facilitator_client.py | 117 +++++++++++ .../.changeset/facilitator-response-errors.md | 8 + .../core/src/http/httpFacilitatorClient.ts | 140 +++++++++++-- typescript/packages/core/src/http/index.ts | 1 + .../core/src/http/x402HTTPResourceServer.ts | 7 + typescript/packages/core/src/server/index.ts | 1 + .../core/src/server/x402ResourceServer.ts | 15 +- .../packages/core/src/types/facilitator.ts | 34 ++++ typescript/packages/core/src/types/index.ts | 7 +- .../unit/http/httpFacilitatorClient.test.ts | 112 ++++++++++ .../x402HTTPResourceServer.errors.test.ts | 116 +++++++++++ .../packages/http/express/src/index.test.ts | 161 +++++++++++++++ typescript/packages/http/express/src/index.ts | 64 +++++- .../packages/http/hono/src/index.test.ts | 62 ++++++ typescript/packages/http/hono/src/index.ts | 63 +++++- .../packages/http/next/src/index.test.ts | 21 ++ typescript/packages/http/next/src/index.ts | 23 ++- .../packages/http/next/src/utils.test.ts | 48 ++++- typescript/packages/http/next/src/utils.ts | 40 +++- .../packages/mechanisms/aptos/.prettierignore | 3 + typescript/tsconfig.base.json | 4 +- 31 files changed, 1536 insertions(+), 83 deletions(-) create mode 100644 go/.changeset/facilitator-response-errors.md create mode 100644 python/x402/changelog.d/545.bugfix.md create mode 100644 python/x402/tests/unit/http/test_facilitator_client.py create mode 100644 typescript/.changeset/facilitator-response-errors.md create mode 100644 typescript/packages/core/test/unit/http/httpFacilitatorClient.test.ts create mode 100644 typescript/packages/core/test/unit/http/x402HTTPResourceServer.errors.test.ts create mode 100644 typescript/packages/mechanisms/aptos/.prettierignore diff --git a/go/.changeset/facilitator-response-errors.md b/go/.changeset/facilitator-response-errors.md new file mode 100644 index 0000000000..d6a01891c5 --- /dev/null +++ b/go/.changeset/facilitator-response-errors.md @@ -0,0 +1,5 @@ +--- +'github.com/coinbase/x402/go': patch +--- + +Treat malformed facilitator success payloads as facilitator boundary errors in the Go HTTP client instead of surfacing them as verification or settlement failures. diff --git a/go/http/facilitator_client.go b/go/http/facilitator_client.go index d48eb22cec..1ca017c3cc 100644 --- a/go/http/facilitator_client.go +++ b/go/http/facilitator_client.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "net/http" + "strings" "time" x402 "github.com/coinbase/x402/go" @@ -67,6 +68,146 @@ const getSupportedRetries = 3 // getSupportedRetryBaseDelay is the base delay for exponential backoff on retries const getSupportedRetryBaseDelay = 1 * time.Second +// FacilitatorResponseError indicates a facilitator returned malformed success payload data. +type FacilitatorResponseError struct { + message string + cause error +} + +func (e *FacilitatorResponseError) Error() string { + return e.message +} + +func (e *FacilitatorResponseError) Unwrap() error { + return e.cause +} + +type verifyResponseEnvelope struct { + IsValid *bool `json:"isValid"` + InvalidReason string `json:"invalidReason,omitempty"` + InvalidMessage string `json:"invalidMessage,omitempty"` + Payer string `json:"payer,omitempty"` +} + +type settleResponseEnvelope struct { + Success *bool `json:"success"` + ErrorReason string `json:"errorReason,omitempty"` + ErrorMessage string `json:"errorMessage,omitempty"` + Payer string `json:"payer,omitempty"` + Transaction *string `json:"transaction"` + Network *x402.Network `json:"network"` +} + +type supportedKindEnvelope struct { + X402Version *int `json:"x402Version"` + Scheme string `json:"scheme"` + Network string `json:"network"` + Extra map[string]interface{} `json:"extra,omitempty"` +} + +type supportedResponseEnvelope struct { + Kinds []supportedKindEnvelope `json:"kinds"` + Extensions []string `json:"extensions"` + Signers map[string][]string `json:"signers"` +} + +func responseExcerpt(body []byte, limit int) string { + text := strings.TrimSpace(string(body)) + if text == "" { + return "" + } + + compact := strings.Join(strings.Fields(text), " ") + if len(compact) <= limit { + return compact + } + + return compact[:limit-3] + "..." +} + +func newFacilitatorResponseError(operation string, kind string, body []byte, cause error) error { + return &FacilitatorResponseError{ + message: fmt.Sprintf("facilitator %s returned invalid %s: %s", operation, kind, responseExcerpt(body, 200)), + cause: cause, + } +} + +func parseVerifySuccessResponse(body []byte) (*x402.VerifyResponse, error) { + var response verifyResponseEnvelope + if err := json.Unmarshal(body, &response); err != nil { + return nil, newFacilitatorResponseError("verify", "JSON", body, err) + } + if response.IsValid == nil { + return nil, newFacilitatorResponseError("verify", "data", body, fmt.Errorf("missing isValid")) + } + + return &x402.VerifyResponse{ + IsValid: *response.IsValid, + InvalidReason: response.InvalidReason, + InvalidMessage: response.InvalidMessage, + Payer: response.Payer, + }, nil +} + +func parseSettleSuccessResponse(body []byte) (*x402.SettleResponse, error) { + var response settleResponseEnvelope + if err := json.Unmarshal(body, &response); err != nil { + return nil, newFacilitatorResponseError("settle", "JSON", body, err) + } + if response.Success == nil || response.Transaction == nil || response.Network == nil { + return nil, newFacilitatorResponseError("settle", "data", body, fmt.Errorf("missing required fields")) + } + + return &x402.SettleResponse{ + Success: *response.Success, + ErrorReason: response.ErrorReason, + ErrorMessage: response.ErrorMessage, + Payer: response.Payer, + Transaction: *response.Transaction, + Network: *response.Network, + }, nil +} + +func parseSupportedSuccessResponse(body []byte) (x402.SupportedResponse, error) { + var response supportedResponseEnvelope + if err := json.Unmarshal(body, &response); err != nil { + return x402.SupportedResponse{}, newFacilitatorResponseError("getSupported", "JSON", body, err) + } + kinds := make([]x402.SupportedKind, 0, len(response.Kinds)) + for _, kind := range response.Kinds { + if kind.X402Version == nil || kind.Scheme == "" || kind.Network == "" { + return x402.SupportedResponse{}, newFacilitatorResponseError( + "getSupported", + "data", + body, + fmt.Errorf("invalid supported response fields"), + ) + } + kinds = append(kinds, x402.SupportedKind{ + X402Version: *kind.X402Version, + Scheme: kind.Scheme, + Network: kind.Network, + Extra: kind.Extra, + }) + } + + extensions := response.Extensions + if extensions == nil { + extensions = []string{} + } + + signers := response.Signers + if signers == nil { + signers = map[string][]string{} + } + + return x402.SupportedResponse{ + Kinds: kinds, + Extensions: extensions, + Signers: signers, + }, nil +} + // NewHTTPFacilitatorClient creates a new HTTP facilitator client func NewHTTPFacilitatorClient(config *FacilitatorConfig) *HTTPFacilitatorClient { if config == nil { @@ -183,14 +324,14 @@ func (c *HTTPFacilitatorClient) GetSupported(ctx context.Context) (x402.Supporte // Success if resp.StatusCode == http.StatusOK { - var supportedResponse x402.SupportedResponse - if err := json.Unmarshal(responseBody, &supportedResponse); err != nil { - return x402.SupportedResponse{}, fmt.Errorf("failed to decode supported response: %w", err) - } - return supportedResponse, nil + return parseSupportedSuccessResponse(responseBody) } - lastErr = fmt.Errorf("facilitator supported failed (%d): %s", resp.StatusCode, string(responseBody)) + lastErr = fmt.Errorf( + "facilitator supported failed (%d): %s", + resp.StatusCode, + responseExcerpt(responseBody, 200), + ) // Retry on 429 with exponential backoff, except on the last attempt if resp.StatusCode == http.StatusTooManyRequests && attempt < getSupportedRetries-1 { @@ -266,18 +407,9 @@ func (c *HTTPFacilitatorClient) verifyHTTP(ctx context.Context, version int, pay return nil, fmt.Errorf("failed to read response body: %w", err) } - var verifyResponse x402.VerifyResponse - if err := json.Unmarshal(responseBody, &verifyResponse); err != nil { - return nil, x402.NewVerifyError( - x402.ErrInvalidResponse, - "", - fmt.Sprintf("failed to unmarshal verify response: %s", err.Error()), - ) - } - - // For non-200 responses, return an error with the details from the response if resp.StatusCode != http.StatusOK { - if verifyResponse.InvalidReason != "" { + var verifyResponse verifyResponseEnvelope + if err := json.Unmarshal(responseBody, &verifyResponse); err == nil && verifyResponse.InvalidReason != "" { return nil, x402.NewVerifyError( verifyResponse.InvalidReason, verifyResponse.Payer, @@ -287,7 +419,7 @@ func (c *HTTPFacilitatorClient) verifyHTTP(ctx context.Context, version int, pay return nil, fmt.Errorf("facilitator verify failed (%d): %s", resp.StatusCode, string(responseBody)) } - return &verifyResponse, nil + return parseVerifySuccessResponse(responseBody) } func (c *HTTPFacilitatorClient) settleHTTP(ctx context.Context, version int, payloadBytes, requirementsBytes []byte) (*x402.SettleResponse, error) { @@ -342,24 +474,27 @@ func (c *HTTPFacilitatorClient) settleHTTP(ctx context.Context, version int, pay return nil, fmt.Errorf("failed to read response body: %w", err) } - var settleResponse x402.SettleResponse - if err := json.Unmarshal(responseBody, &settleResponse); err != nil { - return nil, fmt.Errorf("facilitator settle failed (%d): %s", resp.StatusCode, string(responseBody)) - } - - // For non-200 responses, return an error with the details from the response if resp.StatusCode != http.StatusOK { - if settleResponse.ErrorReason != "" { + var settleResponse settleResponseEnvelope + if err := json.Unmarshal(responseBody, &settleResponse); err == nil && settleResponse.ErrorReason != "" { + network := x402.Network("") + if settleResponse.Network != nil { + network = *settleResponse.Network + } + transaction := "" + if settleResponse.Transaction != nil { + transaction = *settleResponse.Transaction + } return nil, x402.NewSettleError( settleResponse.ErrorReason, settleResponse.Payer, - settleResponse.Network, - settleResponse.Transaction, + network, + transaction, fmt.Sprintf("facilitator returned %d", resp.StatusCode), ) } return nil, fmt.Errorf("facilitator settle failed (%d): %s", resp.StatusCode, string(responseBody)) } - return &settleResponse, nil + return parseSettleSuccessResponse(responseBody) } diff --git a/go/http/facilitator_client_test.go b/go/http/facilitator_client_test.go index bd9d4f61f0..2cb610ba69 100644 --- a/go/http/facilitator_client_test.go +++ b/go/http/facilitator_client_test.go @@ -7,6 +7,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "strings" "sync/atomic" "testing" "time" @@ -249,15 +250,12 @@ func TestHTTPFacilitatorClientVerifyInvalidResponse(t *testing.T) { t.Fatal("Expected error for invalid verify response") } - var verifyErr *x402.VerifyError - if !errors.As(err, &verifyErr) { - t.Fatalf("Expected VerifyError, got: %T (%v)", err, err) - } - if verifyErr.InvalidReason != x402.ErrInvalidResponse { - t.Errorf("Expected InvalidReason %q, got %q", x402.ErrInvalidResponse, verifyErr.InvalidReason) + var responseErr *FacilitatorResponseError + if !errors.As(err, &responseErr) { + t.Fatalf("Expected FacilitatorResponseError, got: %T (%v)", err, err) } - if verifyErr.InvalidMessage == "" { - t.Error("Expected InvalidMessage to be set for invalid response") + if !strings.Contains(responseErr.Error(), "facilitator verify returned invalid JSON") { + t.Errorf("Expected invalid JSON message, got %q", responseErr.Error()) } } @@ -317,6 +315,50 @@ func TestHTTPFacilitatorClientSettle(t *testing.T) { } } +func TestHTTPFacilitatorClientSettleInvalidResponse(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"success": true}`)) + })) + defer server.Close() + + client := NewHTTPFacilitatorClient(&FacilitatorConfig{ + URL: server.URL, + }) + + requirements := x402.PaymentRequirements{ + Scheme: "exact", + Network: "eip155:1", + Asset: "USDC", + Amount: "1000000", + PayTo: "0xrecipient", + } + + payload := x402.PaymentPayload{ + X402Version: 2, + Accepted: requirements, + Payload: map[string]interface{}{"sig": "test"}, + } + + payloadBytes, _ := json.Marshal(payload) + requirementsBytes, _ := json.Marshal(requirements) + + _, err := client.Settle(ctx, payloadBytes, requirementsBytes) + if err == nil { + t.Fatal("Expected error for invalid settle response") + } + + var responseErr *FacilitatorResponseError + if !errors.As(err, &responseErr) { + t.Fatalf("Expected FacilitatorResponseError, got: %T (%v)", err, err) + } + if !strings.Contains(responseErr.Error(), "facilitator settle returned invalid data") { + t.Errorf("Expected invalid data message, got %q", responseErr.Error()) + } +} + func TestHTTPFacilitatorClientGetSupported(t *testing.T) { ctx := context.Background() @@ -373,6 +415,33 @@ func TestHTTPFacilitatorClientGetSupported(t *testing.T) { } } +func TestHTTPFacilitatorClientGetSupportedInvalidResponse(t *testing.T) { + ctx := context.Background() + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"kinds":[{"scheme":"exact"}]}`)) + })) + defer server.Close() + + client := NewHTTPFacilitatorClient(&FacilitatorConfig{ + URL: server.URL, + }) + + _, err := client.GetSupported(ctx) + if err == nil { + t.Fatal("Expected error for invalid supported response") + } + + var responseErr *FacilitatorResponseError + if !errors.As(err, &responseErr) { + t.Fatalf("Expected FacilitatorResponseError, got: %T (%v)", err, err) + } + if !strings.Contains(responseErr.Error(), "facilitator getSupported returned invalid data") { + t.Errorf("Expected invalid data message, got %q", responseErr.Error()) + } +} + func TestHTTPFacilitatorClientWithAuth(t *testing.T) { ctx := context.Background() diff --git a/python/x402/changelog.d/545.bugfix.md b/python/x402/changelog.d/545.bugfix.md new file mode 100644 index 0000000000..b3e011de17 --- /dev/null +++ b/python/x402/changelog.d/545.bugfix.md @@ -0,0 +1 @@ +Fixed Python HTTP middleware to return `502` instead of `500` when the facilitator responds with invalid JSON or schema-invalid data. diff --git a/python/x402/http/facilitator_client.py b/python/x402/http/facilitator_client.py index 0f0440fc87..7d762dfec2 100644 --- a/python/x402/http/facilitator_client.py +++ b/python/x402/http/facilitator_client.py @@ -7,7 +7,9 @@ from __future__ import annotations import json -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, TypeVar + +from pydantic import ValidationError from ..schemas import ( PaymentPayload, @@ -24,6 +26,7 @@ FacilitatorClient, FacilitatorClientSync, FacilitatorConfig, + FacilitatorResponseError, HTTPFacilitatorClientBase, ) @@ -35,6 +38,7 @@ "HTTPFacilitatorClient", "HTTPFacilitatorClientSync", "FacilitatorConfig", + "FacilitatorResponseError", "FacilitatorClient", "FacilitatorClientSync", "AuthProvider", @@ -42,6 +46,46 @@ "CreateHeadersAuthProvider", ] +_ResponseModelT = TypeVar( + "_ResponseModelT", + VerifyResponse, + SettleResponse, + SupportedResponse, +) + + +def _response_excerpt(response: Any, limit: int = 200) -> str: + """Build a compact response preview for parse errors.""" + text = str(getattr(response, "text", "") or "").strip() + if not text: + return "" + + compact = " ".join(text.split()) + if len(compact) <= limit: + return compact + return f"{compact[: limit - 3]}..." + + +def _parse_facilitator_response( + response: Any, + model_cls: type[_ResponseModelT], + operation: str, +) -> _ResponseModelT: + """Parse facilitator JSON into a validated response model.""" + try: + response_data = response.json() + except (json.JSONDecodeError, ValueError, TypeError) as exc: + raise FacilitatorResponseError( + f"Facilitator {operation} returned invalid JSON: {_response_excerpt(response)}" + ) from exc + + try: + return model_cls.model_validate(response_data) + except (ValidationError, ValueError, TypeError) as exc: + raise FacilitatorResponseError( + f"Facilitator {operation} returned invalid data: {_response_excerpt(response)}" + ) from exc + # ============================================================================ # Async HTTP Facilitator Client (Default) @@ -167,7 +211,7 @@ def get_supported(self) -> SupportedResponse: f"Facilitator get_supported failed ({response.status_code}): {response.text}" ) - return SupportedResponse.model_validate(response.json()) + return _parse_facilitator_response(response, SupportedResponse, "supported") # ========================================================================= # Bytes-Based Methods (Network Boundary) @@ -244,7 +288,7 @@ async def _verify_http( if response.status_code != 200: raise ValueError(f"Facilitator verify failed ({response.status_code}): {response.text}") - return VerifyResponse.model_validate(response.json()) + return _parse_facilitator_response(response, VerifyResponse, "verify") async def _settle_http( self, @@ -265,7 +309,7 @@ async def _settle_http( if response.status_code != 200: raise ValueError(f"Facilitator settle failed ({response.status_code}): {response.text}") - return SettleResponse.model_validate(response.json()) + return _parse_facilitator_response(response, SettleResponse, "settle") # ============================================================================ @@ -383,7 +427,7 @@ def get_supported(self) -> SupportedResponse: f"Facilitator get_supported failed ({response.status_code}): {response.text}" ) - return SupportedResponse.model_validate(response.json()) + return _parse_facilitator_response(response, SupportedResponse, "supported") # ========================================================================= # Bytes-Based Methods (Network Boundary) @@ -460,7 +504,7 @@ def _verify_http( if response.status_code != 200: raise ValueError(f"Facilitator verify failed ({response.status_code}): {response.text}") - return VerifyResponse.model_validate(response.json()) + return _parse_facilitator_response(response, VerifyResponse, "verify") def _settle_http( self, @@ -481,4 +525,4 @@ def _settle_http( if response.status_code != 200: raise ValueError(f"Facilitator settle failed ({response.status_code}): {response.text}") - return SettleResponse.model_validate(response.json()) + return _parse_facilitator_response(response, SettleResponse, "settle") diff --git a/python/x402/http/facilitator_client_base.py b/python/x402/http/facilitator_client_base.py index aaab9ab797..9926f8b12c 100644 --- a/python/x402/http/facilitator_client_base.py +++ b/python/x402/http/facilitator_client_base.py @@ -66,6 +66,10 @@ def get_auth_headers(self) -> AuthHeaders: ) +class FacilitatorResponseError(ValueError): + """Facilitator returned malformed or schema-invalid response data.""" + + # ============================================================================ # FacilitatorClient Protocols # ============================================================================ diff --git a/python/x402/http/middleware/fastapi.py b/python/x402/http/middleware/fastapi.py index a7b02d494a..24341bc2bb 100644 --- a/python/x402/http/middleware/fastapi.py +++ b/python/x402/http/middleware/fastapi.py @@ -18,6 +18,7 @@ "FastAPI middleware requires fastapi and starlette. Install with: uv add x402[fastapi]" ) from e +from ..facilitator_client_base import FacilitatorResponseError from ..types import ( HTTPAdapter, HTTPRequestContext, @@ -187,6 +188,14 @@ def get_body(self) -> Any: # ============================================================================ +def _facilitator_error_response(error: FacilitatorResponseError) -> JSONResponse: + """Map invalid facilitator responses to a stable HTTP error.""" + return JSONResponse( + content={"error": str(error)}, + status_code=502, + ) + + def payment_middleware( routes: RoutesConfig, server: x402ResourceServer, @@ -274,11 +283,17 @@ async def middleware( # Initialize on first protected request if sync_facilitator_on_start and not init_done: - http_server.initialize() + try: + http_server.initialize() + except FacilitatorResponseError as error: + return _facilitator_error_response(error) init_done = True # Process payment request - result = await http_server.process_http_request(context, paywall_config) + try: + result = await http_server.process_http_request(context, paywall_config) + except FacilitatorResponseError as error: + return _facilitator_error_response(error) if result.type == "no-payment-required": return await call_next(request) @@ -360,6 +375,8 @@ async def middleware( media_type=response.media_type, ) + except FacilitatorResponseError as error: + return _facilitator_error_response(error) except Exception: return JSONResponse(content={}, status_code=402) diff --git a/python/x402/http/middleware/flask.py b/python/x402/http/middleware/flask.py index 47eed5f503..1e37d146b3 100644 --- a/python/x402/http/middleware/flask.py +++ b/python/x402/http/middleware/flask.py @@ -17,6 +17,7 @@ "Flask middleware requires the flask package. Install with: uv add x402[flask]" ) from e +from ..facilitator_client_base import FacilitatorResponseError from ..types import ( HTTPAdapter, HTTPRequestContext, @@ -186,6 +187,19 @@ def get_body(self) -> Any: # ============================================================================ +def _facilitator_error_wsgi_response( + start_response: Callable[..., Any], + error: FacilitatorResponseError, +) -> list[bytes]: + """Map invalid facilitator responses to a stable HTTP error.""" + body = json.dumps({"error": str(error)}).encode("utf-8") + start_response( + "502 Bad Gateway", + [("Content-Type", "application/json")], + ) + return [body] + + class ResponseWrapper: """Wrapper to capture and buffer WSGI response for settlement. @@ -360,11 +374,17 @@ def _wsgi_middleware( # Initialize on first protected request if self._sync_on_start and not self._init_done: - self._http_server.initialize() + try: + self._http_server.initialize() + except FacilitatorResponseError as error: + return _facilitator_error_wsgi_response(start_response, error) self._init_done = True # Process payment request synchronously (no asyncio overhead) - result = self._http_server.process_http_request(context, self._paywall_config) + try: + result = self._http_server.process_http_request(context, self._paywall_config) + except FacilitatorResponseError as error: + return _facilitator_error_wsgi_response(start_response, error) if result.type == "no-payment-required": return self._original_wsgi(environ, start_response) @@ -447,6 +467,9 @@ def _wsgi_middleware( start_response(status, headers) return [body] + except FacilitatorResponseError as error: + return _facilitator_error_wsgi_response(start_response, error) + except Exception: # Settlement error - return empty body with 402 start_response( diff --git a/python/x402/tests/unit/http/middleware/test_fastapi.py b/python/x402/tests/unit/http/middleware/test_fastapi.py index f8ad826b51..07f476177f 100644 --- a/python/x402/tests/unit/http/middleware/test_fastapi.py +++ b/python/x402/tests/unit/http/middleware/test_fastapi.py @@ -12,6 +12,7 @@ from fastapi.testclient import TestClient from starlette.datastructures import Headers, QueryParams +from x402.http.facilitator_client_base import FacilitatorResponseError from x402.http.middleware.fastapi import ( FastAPIAdapter, PaymentMiddlewareASGI, @@ -447,6 +448,102 @@ async def x402_middleware(request: Request, call_next): assert response.json() == {} assert "PAYMENT-RESPONSE" in response.headers + def test_invalid_facilitator_verify_response_returns_502(self): + """Test that invalid facilitator data during verify returns 502 instead of 500.""" + app = FastAPI() + + @app.get("/api/protected") + def protected_route(): + return {"data": "Protected content"} + + mock_server = MagicMock() + routes = { + "GET /api/protected": RouteConfig( + accepts=PaymentOption( + scheme="exact", + pay_to="0x1234567890123456789012345678901234567890", + price="$0.01", + network="eip155:8453", + ), + ) + } + + with patch("x402.http.middleware.fastapi.x402HTTPResourceServer") as mock_http_server: + mock_http_server_instance = MagicMock() + mock_http_server_instance.requires_payment.return_value = True + mock_http_server_instance.process_http_request = AsyncMock( + side_effect=FacilitatorResponseError( + "Facilitator verify returned invalid JSON: not-json" + ) + ) + mock_http_server.return_value = mock_http_server_instance + + @app.middleware("http") + async def x402_middleware(request: Request, call_next): + return await payment_middleware( + routes, mock_server, sync_facilitator_on_start=False + )(request, call_next) + + with TestClient(app) as client: + response = client.get("/api/protected") + assert response.status_code == 502 + assert response.json() == { + "error": "Facilitator verify returned invalid JSON: not-json" + } + + def test_invalid_facilitator_settlement_response_returns_502(self): + """Test that invalid facilitator data during settlement returns 502.""" + app = FastAPI() + + @app.get("/api/protected") + def protected_route(): + return {"data": "Protected content"} + + mock_server = MagicMock() + routes = { + "GET /api/protected": RouteConfig( + accepts=PaymentOption( + scheme="exact", + pay_to="0x1234567890123456789012345678901234567890", + price="$0.01", + network="eip155:8453", + ), + ) + } + + payment_payload = make_v2_payload() + payment_requirements = make_payment_requirements() + + with patch("x402.http.middleware.fastapi.x402HTTPResourceServer") as mock_http_server: + mock_http_server_instance = MagicMock() + mock_http_server_instance.requires_payment.return_value = True + mock_http_server_instance.process_http_request = AsyncMock( + return_value=HTTPProcessResult( + type="payment-verified", + payment_payload=payment_payload, + payment_requirements=payment_requirements, + ) + ) + mock_http_server_instance.process_settlement = AsyncMock( + side_effect=FacilitatorResponseError( + "Facilitator settle returned invalid data: {'success': true}" + ) + ) + mock_http_server.return_value = mock_http_server_instance + + @app.middleware("http") + async def x402_middleware(request: Request, call_next): + return await payment_middleware( + routes, mock_server, sync_facilitator_on_start=False + )(request, call_next) + + with TestClient(app) as client: + response = client.get("/api/protected") + assert response.status_code == 502 + assert response.json() == { + "error": "Facilitator settle returned invalid data: {'success': true}" + } + # ============================================================================= # ASGI Middleware Class Tests diff --git a/python/x402/tests/unit/http/middleware/test_flask.py b/python/x402/tests/unit/http/middleware/test_flask.py index 6999b21a57..5336860067 100644 --- a/python/x402/tests/unit/http/middleware/test_flask.py +++ b/python/x402/tests/unit/http/middleware/test_flask.py @@ -13,6 +13,7 @@ from flask import Flask from werkzeug.datastructures import Headers, ImmutableMultiDict +from x402.http.facilitator_client_base import FacilitatorResponseError from x402.http.middleware.flask import ( FlaskAdapter, PaymentMiddleware, @@ -565,3 +566,85 @@ def protected_route(): data = json.loads(response.data) assert data == {} assert "PAYMENT-RESPONSE" in response.headers + + def test_invalid_facilitator_verify_response_returns_502(self): + """Test that invalid facilitator data during verify returns 502 instead of 500.""" + app = Flask(__name__) + + @app.route("/api/protected") + def protected_route(): + return "Protected content" + + mock_server = MagicMock() + routes = { + "GET /api/protected": RouteConfig( + accepts=PaymentOption( + scheme="exact", + pay_to="0x1234567890123456789012345678901234567890", + price="$0.01", + network="eip155:8453", + ), + ) + } + + with patch("x402.http.middleware.flask.x402HTTPResourceServerSync") as mock_http_server: + mock_http_server_instance = MagicMock() + mock_http_server_instance.requires_payment.return_value = True + mock_http_server_instance.process_http_request.side_effect = FacilitatorResponseError( + "Facilitator verify returned invalid JSON: not-json" + ) + mock_http_server.return_value = mock_http_server_instance + + PaymentMiddleware(app, routes, mock_server, sync_facilitator_on_start=False) + + with app.test_client() as client: + response = client.get("/api/protected") + assert response.status_code == 502 + assert response.get_json() == { + "error": "Facilitator verify returned invalid JSON: not-json" + } + + def test_invalid_facilitator_settlement_response_returns_502(self): + """Test that invalid facilitator data during settlement returns 502.""" + app = Flask(__name__) + + @app.route("/api/protected") + def protected_route(): + return "Protected content" + + mock_server = MagicMock() + routes = { + "GET /api/protected": RouteConfig( + accepts=PaymentOption( + scheme="exact", + pay_to="0x1234567890123456789012345678901234567890", + price="$0.01", + network="eip155:8453", + ), + ) + } + + payment_payload = make_v2_payload() + payment_requirements = make_payment_requirements() + + with patch("x402.http.middleware.flask.x402HTTPResourceServerSync") as mock_http_server: + mock_http_server_instance = MagicMock() + mock_http_server_instance.requires_payment.return_value = True + mock_http_server_instance.process_http_request.return_value = HTTPProcessResult( + type="payment-verified", + payment_payload=payment_payload, + payment_requirements=payment_requirements, + ) + mock_http_server_instance.process_settlement.side_effect = FacilitatorResponseError( + "Facilitator settle returned invalid data: {'success': true}" + ) + mock_http_server.return_value = mock_http_server_instance + + PaymentMiddleware(app, routes, mock_server, sync_facilitator_on_start=False) + + with app.test_client() as client: + response = client.get("/api/protected") + assert response.status_code == 502 + assert response.get_json() == { + "error": "Facilitator settle returned invalid data: {'success': true}" + } diff --git a/python/x402/tests/unit/http/test_facilitator_client.py b/python/x402/tests/unit/http/test_facilitator_client.py new file mode 100644 index 0000000000..03d3ef5b58 --- /dev/null +++ b/python/x402/tests/unit/http/test_facilitator_client.py @@ -0,0 +1,117 @@ +"""Unit tests for x402.http.facilitator_client.""" + +from __future__ import annotations + +import json +from unittest.mock import AsyncMock, MagicMock + +import pytest + +from x402.http.facilitator_client import ( + HTTPFacilitatorClient, + HTTPFacilitatorClientSync, +) +from x402.http.facilitator_client_base import ( + FacilitatorConfig, + FacilitatorResponseError, +) +from x402.schemas import PaymentPayload, PaymentRequirements + + +def make_payment_requirements() -> PaymentRequirements: + """Helper to create valid PaymentRequirements.""" + return PaymentRequirements( + scheme="exact", + network="eip155:8453", + asset="0x0000000000000000000000000000000000000000", + amount="1000000", + pay_to="0x1234567890123456789012345678901234567890", + max_timeout_seconds=300, + ) + + +def make_v2_payload(signature: str = "0xmock") -> PaymentPayload: + """Helper to create valid V2 PaymentPayload.""" + return PaymentPayload( + x402_version=2, + payload={"signature": signature}, + accepted=make_payment_requirements(), + ) + + +@pytest.mark.asyncio +async def test_async_verify_raises_facilitator_response_error_for_invalid_json(): + """Async verify should surface invalid JSON as facilitator boundary error.""" + response = MagicMock(status_code=200, text="not-json") + response.json.side_effect = json.JSONDecodeError("Expecting value", "not-json", 0) + + http_client = MagicMock() + http_client.post = AsyncMock(return_value=response) + + client = HTTPFacilitatorClient( + FacilitatorConfig(url="https://facilitator.test", http_client=http_client) + ) + + with pytest.raises( + FacilitatorResponseError, + match="Facilitator verify returned invalid JSON", + ): + await client.verify(make_v2_payload(), make_payment_requirements()) + + +@pytest.mark.asyncio +async def test_async_settle_raises_facilitator_response_error_for_invalid_schema(): + """Async settle should surface schema drift as facilitator boundary error.""" + response = MagicMock(status_code=200, text='{"success": true}') + response.json.return_value = {"success": True} + + http_client = MagicMock() + http_client.post = AsyncMock(return_value=response) + + client = HTTPFacilitatorClient( + FacilitatorConfig(url="https://facilitator.test", http_client=http_client) + ) + + with pytest.raises( + FacilitatorResponseError, + match="Facilitator settle returned invalid data", + ): + await client.settle(make_v2_payload(), make_payment_requirements()) + + +def test_sync_verify_raises_facilitator_response_error_for_invalid_json(): + """Sync verify should surface invalid JSON as facilitator boundary error.""" + response = MagicMock(status_code=200, text="not-json") + response.json.side_effect = json.JSONDecodeError("Expecting value", "not-json", 0) + + http_client = MagicMock() + http_client.post.return_value = response + + client = HTTPFacilitatorClientSync( + FacilitatorConfig(url="https://facilitator.test", http_client=http_client) + ) + + with pytest.raises( + FacilitatorResponseError, + match="Facilitator verify returned invalid JSON", + ): + client.verify(make_v2_payload(), make_payment_requirements()) + + +def test_sync_settle_raises_facilitator_response_error_for_invalid_schema(): + """Sync settle should surface schema drift as facilitator boundary error.""" + response = MagicMock(status_code=200, text='{"success": true}') + response.json.return_value = {"success": True} + + http_client = MagicMock() + http_client.post.return_value = response + + client = HTTPFacilitatorClientSync( + FacilitatorConfig(url="https://facilitator.test", http_client=http_client) + ) + + with pytest.raises( + FacilitatorResponseError, + match="Facilitator settle returned invalid data", + ): + client.settle(make_v2_payload(), make_payment_requirements()) diff --git a/typescript/.changeset/facilitator-response-errors.md b/typescript/.changeset/facilitator-response-errors.md new file mode 100644 index 0000000000..f00020883b --- /dev/null +++ b/typescript/.changeset/facilitator-response-errors.md @@ -0,0 +1,8 @@ +--- +'@x402/core': patch +'@x402/express': patch +'@x402/hono': patch +'@x402/next': patch +--- + +Treat malformed facilitator success payloads as upstream facilitator errors and return 502 responses from framework middleware instead of flattening them into payment failures. diff --git a/typescript/packages/core/src/http/httpFacilitatorClient.ts b/typescript/packages/core/src/http/httpFacilitatorClient.ts index 29ce532e5a..653ea439e2 100644 --- a/typescript/packages/core/src/http/httpFacilitatorClient.ts +++ b/typescript/packages/core/src/http/httpFacilitatorClient.ts @@ -5,7 +5,9 @@ import { SupportedResponse, VerifyError, SettleError, + FacilitatorResponseError, } from "../types/facilitator"; +import { z } from "../schemas"; const DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator"; @@ -60,6 +62,94 @@ const GET_SUPPORTED_RETRIES = 3; /** Base delay in ms for exponential backoff on retries */ const GET_SUPPORTED_RETRY_DELAY_MS = 1000; +const verifyResponseSchema: z.ZodType = z.object({ + isValid: z.boolean(), + invalidReason: z.string().optional(), + invalidMessage: z.string().optional(), + payer: z.string().optional(), + extensions: z.record(z.string(), z.unknown()).optional(), +}); + +const settleResponseSchema: z.ZodType = z.object({ + success: z.boolean(), + errorReason: z.string().optional(), + errorMessage: z.string().optional(), + payer: z.string().optional(), + transaction: z.string(), + network: z.custom(value => typeof value === "string"), + extensions: z.record(z.string(), z.unknown()).optional(), +}); + +const supportedKindSchema: z.ZodType = + z.object({ + x402Version: z.number(), + scheme: z.string(), + network: z.custom( + value => typeof value === "string", + ), + extra: z.record(z.string(), z.unknown()).optional(), + }); + +const supportedResponseSchema: z.ZodType = z.object({ + kinds: z.array(supportedKindSchema), + extensions: z.array(z.string()).default([]), + signers: z.record(z.string(), z.array(z.string())).default({}), +}); + +/** + * Produces a compact excerpt of a facilitator response body for error messages. + * + * @param text - The raw response body text + * @param limit - The maximum number of characters to include + * @returns A normalized excerpt suitable for logs and thrown errors + */ +function responseExcerpt(text: string, limit: number = 200): string { + const compact = text.trim().replace(/\s+/g, " "); + if (!compact) { + return ""; + } + + if (compact.length <= limit) { + return compact; + } + + return `${compact.slice(0, limit - 3)}...`; +} + +/** + * Parses and validates a successful facilitator response body. + * + * @param response - The HTTP response returned by the facilitator + * @param schema - The schema used to validate the response payload + * @param operation - The facilitator operation name for error reporting + * @returns The validated facilitator payload + */ +async function parseSuccessResponse( + response: Response, + schema: z.ZodType, + operation: string, +): Promise { + const text = await response.text(); + + let data: unknown; + try { + data = JSON.parse(text); + } catch { + throw new FacilitatorResponseError( + `Facilitator ${operation} returned invalid JSON: ${responseExcerpt(text)}`, + ); + } + + const parsed = schema.safeParse(data); + if (!parsed.success) { + throw new FacilitatorResponseError( + `Facilitator ${operation} returned invalid data: ${responseExcerpt(text)}`, + ); + } + + return parsed.data; +} + /** * HTTP-based client for interacting with x402 facilitator services * Handles HTTP communication with facilitator endpoints @@ -108,17 +198,25 @@ export class HTTPFacilitatorClient implements FacilitatorClient { }), }); - const data = await response.json(); + if (!response.ok) { + const text = await response.text(); + let data: unknown; + try { + data = JSON.parse(text); + } catch { + throw new Error(`Facilitator verify failed (${response.status}): ${responseExcerpt(text)}`); + } - if (typeof data === "object" && data !== null && "isValid" in data) { - const verifyResponse = data as VerifyResponse; - if (!response.ok) { - throw new VerifyError(response.status, verifyResponse); + if (typeof data === "object" && data !== null && "isValid" in data) { + throw new VerifyError(response.status, data as VerifyResponse); } - return verifyResponse; + + throw new Error( + `Facilitator verify failed (${response.status}): ${responseExcerpt(JSON.stringify(data))}`, + ); } - throw new Error(`Facilitator verify failed (${response.status}): ${JSON.stringify(data)}`); + return parseSuccessResponse(response, verifyResponseSchema, "verify"); } /** @@ -151,17 +249,25 @@ export class HTTPFacilitatorClient implements FacilitatorClient { }), }); - const data = await response.json(); + if (!response.ok) { + const text = await response.text(); + let data: unknown; + try { + data = JSON.parse(text); + } catch { + throw new Error(`Facilitator settle failed (${response.status}): ${responseExcerpt(text)}`); + } - if (typeof data === "object" && data !== null && "success" in data) { - const settleResponse = data as SettleResponse; - if (!response.ok) { - throw new SettleError(response.status, settleResponse); + if (typeof data === "object" && data !== null && "success" in data) { + throw new SettleError(response.status, data as SettleResponse); } - return settleResponse; + + throw new Error( + `Facilitator settle failed (${response.status}): ${responseExcerpt(JSON.stringify(data))}`, + ); } - throw new Error(`Facilitator settle failed (${response.status}): ${JSON.stringify(data)}`); + return parseSuccessResponse(response, settleResponseSchema, "settle"); } /** @@ -188,11 +294,13 @@ export class HTTPFacilitatorClient implements FacilitatorClient { }); if (response.ok) { - return (await response.json()) as SupportedResponse; + return parseSuccessResponse(response, supportedResponseSchema, "supported"); } const errorText = await response.text().catch(() => response.statusText); - lastError = new Error(`Facilitator getSupported failed (${response.status}): ${errorText}`); + lastError = new Error( + `Facilitator getSupported failed (${response.status}): ${responseExcerpt(errorText)}`, + ); // Retry on 429 rate limit errors with exponential backoff if (response.status === 429 && attempt < GET_SUPPORTED_RETRIES - 1) { diff --git a/typescript/packages/core/src/http/index.ts b/typescript/packages/core/src/http/index.ts index 8ff5882aa7..1b156719bd 100644 --- a/typescript/packages/core/src/http/index.ts +++ b/typescript/packages/core/src/http/index.ts @@ -108,4 +108,5 @@ export { FacilitatorClient, FacilitatorConfig, } from "./httpFacilitatorClient"; +export { FacilitatorResponseError, getFacilitatorResponseError } from "../types"; export { x402HTTPClient, PaymentRequiredContext, PaymentRequiredHook } from "./x402HTTPClient"; diff --git a/typescript/packages/core/src/http/x402HTTPResourceServer.ts b/typescript/packages/core/src/http/x402HTTPResourceServer.ts index 4d95371e89..151c778429 100644 --- a/typescript/packages/core/src/http/x402HTTPResourceServer.ts +++ b/typescript/packages/core/src/http/x402HTTPResourceServer.ts @@ -9,6 +9,7 @@ import { PaymentRequired, SettleResponse, SettleError, + FacilitatorResponseError, Price, Network, PaymentRequirements, @@ -542,6 +543,9 @@ export class x402HTTPResourceServer { declaredExtensions: routeConfig.extensions, }; } catch (error) { + if (error instanceof FacilitatorResponseError) { + throw error; + } const errorResponse = await this.ResourceServer.createPaymentRequiredResponse( requirements, resourceInfo, @@ -599,6 +603,9 @@ export class x402HTTPResourceServer { requirements, }; } catch (error) { + if (error instanceof FacilitatorResponseError) { + throw error; + } if (error instanceof SettleError) { const errorReason = error.errorReason || error.message; const settleResponse: SettleResponse = { diff --git a/typescript/packages/core/src/server/index.ts b/typescript/packages/core/src/server/index.ts index 412c94d733..87d5c3ac5b 100644 --- a/typescript/packages/core/src/server/index.ts +++ b/typescript/packages/core/src/server/index.ts @@ -3,6 +3,7 @@ export type { ResourceConfig, SettleResultContext } from "./x402ResourceServer"; export { HTTPFacilitatorClient } from "../http/httpFacilitatorClient"; export type { FacilitatorClient, FacilitatorConfig } from "../http/httpFacilitatorClient"; +export { FacilitatorResponseError, getFacilitatorResponseError } from "../types"; export { x402HTTPResourceServer, RouteConfigurationError } from "../http/x402HTTPResourceServer"; export type { diff --git a/typescript/packages/core/src/server/x402ResourceServer.ts b/typescript/packages/core/src/server/x402ResourceServer.ts index e1459fd65c..f25c3b0a0c 100644 --- a/typescript/packages/core/src/server/x402ResourceServer.ts +++ b/typescript/packages/core/src/server/x402ResourceServer.ts @@ -299,6 +299,7 @@ export class x402ResourceServer { // Clear existing mappings this.supportedResponsesMap.clear(); this.facilitatorClientsMap.clear(); + let lastError: Error | undefined; // Fetch supported kinds from all facilitator clients // Process in order to give precedence to earlier facilitators @@ -341,15 +342,23 @@ export class x402ResourceServer { } } } catch (error) { + lastError = error as Error; // Log error but continue with other facilitators console.warn(`Failed to fetch supported kinds from facilitator: ${error}`); } } if (this.supportedResponsesMap.size === 0) { - throw new Error( - "Failed to initialize: no supported payment kinds loaded from any facilitator.", - ); + throw lastError + ? new Error( + "Failed to initialize: no supported payment kinds loaded from any facilitator.", + { + cause: lastError, + }, + ) + : new Error( + "Failed to initialize: no supported payment kinds loaded from any facilitator.", + ); } } diff --git a/typescript/packages/core/src/types/facilitator.ts b/typescript/packages/core/src/types/facilitator.ts index 3b6adc07cc..8f975a5ff1 100644 --- a/typescript/packages/core/src/types/facilitator.ts +++ b/typescript/packages/core/src/types/facilitator.ts @@ -101,3 +101,37 @@ export class SettleError extends Error { this.network = response.network; } } + +/** + * Error thrown when a facilitator returns malformed success payload data. + */ +export class FacilitatorResponseError extends Error { + /** + * Creates a FacilitatorResponseError for malformed facilitator responses. + * + * @param message - The boundary error message + */ + constructor(message: string) { + super(message); + this.name = "FacilitatorResponseError"; + } +} + +/** + * Walks an error cause chain to find the first facilitator response error. + * + * @param error - The thrown value to inspect + * @returns The nested facilitator response error, if present + */ +export function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null { + let current = error; + + while (current instanceof Error) { + if (current instanceof FacilitatorResponseError) { + return current; + } + current = current.cause; + } + + return null; +} diff --git a/typescript/packages/core/src/types/index.ts b/typescript/packages/core/src/types/index.ts index 35a4425ed2..6ef8e7fe37 100644 --- a/typescript/packages/core/src/types/index.ts +++ b/typescript/packages/core/src/types/index.ts @@ -5,7 +5,12 @@ export type { SettleResponse, SupportedResponse, } from "./facilitator"; -export { VerifyError, SettleError } from "./facilitator"; +export { + VerifyError, + SettleError, + FacilitatorResponseError, + getFacilitatorResponseError, +} from "./facilitator"; export type { PaymentRequirements, PaymentPayload, diff --git a/typescript/packages/core/test/unit/http/httpFacilitatorClient.test.ts b/typescript/packages/core/test/unit/http/httpFacilitatorClient.test.ts new file mode 100644 index 0000000000..f5ebcadf83 --- /dev/null +++ b/typescript/packages/core/test/unit/http/httpFacilitatorClient.test.ts @@ -0,0 +1,112 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { HTTPFacilitatorClient } from "../../../src/http/httpFacilitatorClient"; +import { FacilitatorResponseError, SettleError, VerifyError } from "../../../src/types"; +import { PaymentPayload, PaymentRequirements } from "../../../src/types/payments"; + +const paymentRequirements: PaymentRequirements = { + scheme: "exact", + network: "eip155:8453", + asset: "0x0000000000000000000000000000000000000000", + amount: "1000000", + payTo: "0x1234567890123456789012345678901234567890", + maxTimeoutSeconds: 300, + extra: {}, +}; + +const paymentPayload: PaymentPayload = { + x402Version: 2, + accepted: paymentRequirements, + payload: { signature: "0xmock" }, +}; + +describe("HTTPFacilitatorClient", () => { + afterEach(() => { + vi.restoreAllMocks(); + vi.unstubAllGlobals(); + }); + + it("throws FacilitatorResponseError for invalid verify JSON on success", async () => { + vi.stubGlobal("fetch", vi.fn().mockResolvedValue(new Response("not-json", { status: 200 }))); + + const client = new HTTPFacilitatorClient({ url: "https://facilitator.test" }); + const error = await client + .verify(paymentPayload, paymentRequirements) + .catch(caught => caught as Error); + + expect(error).toBeInstanceOf(FacilitatorResponseError); + expect(error.message).toContain("Facilitator verify returned invalid JSON"); + }); + + it("throws FacilitatorResponseError for invalid settle data on success", async () => { + vi.stubGlobal( + "fetch", + vi.fn().mockResolvedValue(new Response(JSON.stringify({ success: true }), { status: 200 })), + ); + + const client = new HTTPFacilitatorClient({ url: "https://facilitator.test" }); + const error = await client + .settle(paymentPayload, paymentRequirements) + .catch(caught => caught as Error); + + expect(error).toBeInstanceOf(FacilitatorResponseError); + expect(error.message).toContain("Facilitator settle returned invalid data"); + }); + + it("throws FacilitatorResponseError for invalid supported data on success", async () => { + vi.stubGlobal( + "fetch", + vi + .fn() + .mockResolvedValue( + new Response(JSON.stringify({ kinds: [{ scheme: "exact" }] }), { status: 200 }), + ), + ); + + const client = new HTTPFacilitatorClient({ url: "https://facilitator.test" }); + const error = await client.getSupported().catch(caught => caught as Error); + + expect(error).toBeInstanceOf(FacilitatorResponseError); + expect(error.message).toContain("Facilitator supported returned invalid data"); + }); + + it("preserves VerifyError semantics for valid non-200 verify responses", async () => { + vi.stubGlobal( + "fetch", + vi.fn().mockResolvedValue( + new Response( + JSON.stringify({ + isValid: false, + invalidReason: "invalid_signature", + invalidMessage: "signature mismatch", + }), + { status: 400 }, + ), + ), + ); + + const client = new HTTPFacilitatorClient({ url: "https://facilitator.test" }); + + await expect(client.verify(paymentPayload, paymentRequirements)).rejects.toThrow(VerifyError); + }); + + it("preserves SettleError semantics for valid non-200 settle responses", async () => { + vi.stubGlobal( + "fetch", + vi.fn().mockResolvedValue( + new Response( + JSON.stringify({ + success: false, + errorReason: "insufficient_allowance", + transaction: "", + network: "eip155:8453", + }), + { status: 400 }, + ), + ), + ); + + const client = new HTTPFacilitatorClient({ url: "https://facilitator.test" }); + + await expect(client.settle(paymentPayload, paymentRequirements)).rejects.toThrow(SettleError); + }); +}); diff --git a/typescript/packages/core/test/unit/http/x402HTTPResourceServer.errors.test.ts b/typescript/packages/core/test/unit/http/x402HTTPResourceServer.errors.test.ts new file mode 100644 index 0000000000..0d7e3c1c6d --- /dev/null +++ b/typescript/packages/core/test/unit/http/x402HTTPResourceServer.errors.test.ts @@ -0,0 +1,116 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import { x402HTTPResourceServer, HTTPAdapter } from "../../../src/http/x402HTTPResourceServer"; +import { x402ResourceServer } from "../../../src/server/x402ResourceServer"; +import { FacilitatorResponseError, Network } from "../../../src/types"; +import { + MockFacilitatorClient, + MockSchemeNetworkServer, + buildPaymentPayload, + buildPaymentRequirements, + buildSupportedResponse, +} from "../../mocks"; +import { encodePaymentSignatureHeader } from "../../../src/http"; + +class MockHTTPAdapter implements HTTPAdapter { + constructor(private readonly headers: Record = {}) {} + + getHeader(name: string): string | undefined { + return this.headers[name.toLowerCase()]; + } + + getMethod(): string { + return "GET"; + } + + getPath(): string { + return "/api/test"; + } + + getUrl(): string { + return "https://example.com/api/test"; + } + + getAcceptHeader(): string { + return "application/json"; + } + + getUserAgent(): string { + return "Vitest"; + } +} + +describe("x402HTTPResourceServer facilitator response errors", () => { + let resourceServer: x402ResourceServer; + let facilitator: MockFacilitatorClient; + let httpServer: x402HTTPResourceServer; + const network = "eip155:8453" as Network; + + beforeEach(async () => { + facilitator = new MockFacilitatorClient( + buildSupportedResponse({ + kinds: [{ x402Version: 2, scheme: "exact", network }], + }), + ); + + resourceServer = new x402ResourceServer(facilitator); + resourceServer.register(network, new MockSchemeNetworkServer("exact")); + await resourceServer.initialize(); + + httpServer = new x402HTTPResourceServer(resourceServer, { + "/api/test": { + accepts: { + scheme: "exact", + payTo: "0xabc", + price: "$1.00", + network, + }, + }, + }); + }); + + it("rethrows FacilitatorResponseError during verification", async () => { + facilitator.setVerifyResponse( + new FacilitatorResponseError("Facilitator verify returned invalid JSON: not-json"), + ); + + const accepted = buildPaymentRequirements({ + scheme: "exact", + network, + payTo: "0xabc", + asset: "USDC", + amount: "1000000", + }); + const payload = buildPaymentPayload({ + x402Version: 2, + accepted, + }); + + await expect( + httpServer.processHTTPRequest({ + adapter: new MockHTTPAdapter({ + "payment-signature": encodePaymentSignatureHeader(payload), + }), + path: "/api/test", + method: "GET", + paymentHeader: encodePaymentSignatureHeader(payload), + }), + ).rejects.toThrow(FacilitatorResponseError); + }); + + it("rethrows FacilitatorResponseError during settlement", async () => { + facilitator.setSettleResponse( + new FacilitatorResponseError('Facilitator settle returned invalid data: {"success":true}'), + ); + + const accepted = buildPaymentRequirements({ + scheme: "exact", + network, + payTo: "0xabc", + asset: "USDC", + amount: "1000000", + }); + await expect( + httpServer.processSettlement(buildPaymentPayload({ x402Version: 2, accepted }), accepted), + ).rejects.toThrow(FacilitatorResponseError); + }); +}); diff --git a/typescript/packages/http/express/src/index.test.ts b/typescript/packages/http/express/src/index.test.ts index 98c1c6be67..464d62e2eb 100644 --- a/typescript/packages/http/express/src/index.test.ts +++ b/typescript/packages/http/express/src/index.test.ts @@ -7,6 +7,7 @@ import type { FacilitatorClient, } from "@x402/core/server"; import { + FacilitatorResponseError, x402ResourceServer, x402HTTPResourceServer as HTTPResourceServer, } from "@x402/core/server"; @@ -40,6 +41,27 @@ let mockRegisterPaywallProvider: ReturnType; let mockRequiresPayment: ReturnType; vi.mock("@x402/core/server", () => ({ + FacilitatorResponseError: class FacilitatorResponseError extends Error { + /** + * Creates a mock facilitator response error. + * + * @param message - Error message. + */ + constructor(message: string) { + super(message); + this.name = "FacilitatorResponseError"; + } + }, + getFacilitatorResponseError: (error: unknown) => { + let current = error; + while (current instanceof Error) { + if (current.name === "FacilitatorResponseError") { + return current; + } + current = (current as Error & { cause?: unknown }).cause; + } + return null; + }, x402ResourceServer: vi.fn().mockImplementation(() => ({ initialize: vi.fn().mockResolvedValue(undefined), registerExtension: vi.fn(), @@ -394,6 +416,145 @@ describe("paymentMiddleware", () => { expect(res.json).toHaveBeenCalledWith({}); }); + it("returns 502 when facilitator init fails during protected request", async () => { + const initialize = vi.fn().mockRejectedValue( + new Error("Failed to initialize: no supported payment kinds loaded from any facilitator.", { + cause: new FacilitatorResponseError( + "Facilitator supported returned invalid JSON: not-json", + ), + }), + ); + + vi.mocked(HTTPResourceServer).mockImplementation( + (server, routes) => + ({ + initialize, + processHTTPRequest: mockProcessHTTPRequest, + processSettlement: mockProcessSettlement, + registerPaywallProvider: mockRegisterPaywallProvider, + requiresPayment: mockRequiresPayment, + routes, + server: server || { + hasExtension: vi.fn().mockReturnValue(false), + registerExtension: vi.fn(), + }, + }) as unknown as x402HTTPResourceServer, + ); + + const middleware = paymentMiddleware(mockRoutes, {} as unknown as x402ResourceServer); + const req = createMockRequest(); + const res = createMockResponse(); + const next = vi.fn(); + + await middleware(req, res, next); + + expect(mockProcessHTTPRequest).not.toHaveBeenCalled(); + expect(res.status).toHaveBeenCalledWith(502); + expect(res.json).toHaveBeenCalledWith({ + error: "Facilitator supported returned invalid JSON: not-json", + }); + }); + + it("retries initialization after a facilitator init failure", async () => { + const initialize = vi + .fn() + .mockRejectedValueOnce( + new Error("Failed to initialize: no supported payment kinds loaded from any facilitator.", { + cause: new FacilitatorResponseError( + "Facilitator supported returned invalid JSON: not-json", + ), + }), + ) + .mockResolvedValueOnce(undefined); + + vi.mocked(HTTPResourceServer).mockImplementation( + (server, routes) => + ({ + initialize, + processHTTPRequest: mockProcessHTTPRequest, + processSettlement: mockProcessSettlement, + registerPaywallProvider: mockRegisterPaywallProvider, + requiresPayment: mockRequiresPayment, + routes, + server: server || { + hasExtension: vi.fn().mockReturnValue(false), + registerExtension: vi.fn(), + }, + }) as unknown as x402HTTPResourceServer, + ); + mockProcessHTTPRequest.mockResolvedValue({ type: "no-payment-required" }); + + const middleware = paymentMiddleware(mockRoutes, {} as unknown as x402ResourceServer); + const firstRes = createMockResponse(); + const secondRes = createMockResponse(); + const next = vi.fn(); + + await middleware(createMockRequest(), firstRes, next); + await middleware(createMockRequest(), secondRes, next); + + expect(firstRes.status).toHaveBeenCalledWith(502); + expect(initialize).toHaveBeenCalledTimes(2); + expect(mockProcessHTTPRequest).toHaveBeenCalledTimes(1); + expect(next).toHaveBeenCalledTimes(1); + }); + + it("returns 502 when processHTTPRequest surfaces FacilitatorResponseError", async () => { + mockProcessHTTPRequest.mockRejectedValue( + new FacilitatorResponseError("Facilitator verify returned invalid JSON: not-json"), + ); + + const middleware = paymentMiddleware( + mockRoutes, + {} as unknown as x402ResourceServer, + undefined, + undefined, + false, + ); + const req = createMockRequest(); + const res = createMockResponse(); + const next = vi.fn(); + + await middleware(req, res, next); + + expect(res.status).toHaveBeenCalledWith(502); + expect(res.json).toHaveBeenCalledWith({ + error: "Facilitator verify returned invalid JSON: not-json", + }); + expect(next).not.toHaveBeenCalled(); + }); + + it("returns 502 when settlement surfaces FacilitatorResponseError", async () => { + setupMockHttpServer({ + type: "payment-verified", + paymentPayload: mockPaymentPayload, + paymentRequirements: mockPaymentRequirements, + }); + mockProcessSettlement.mockRejectedValue( + new FacilitatorResponseError('Facilitator settle returned invalid data: {"success":true}'), + ); + + const middleware = paymentMiddleware( + mockRoutes, + {} as unknown as x402ResourceServer, + undefined, + undefined, + false, + ); + const req = createMockRequest(); + const res = createMockResponse(); + const next = vi.fn(() => { + res.statusCode = 200; + res.end(); + }); + + await middleware(req, res, next); + + expect(res.status).toHaveBeenCalledWith(502); + expect(res.json).toHaveBeenCalledWith({ + error: 'Facilitator settle returned invalid data: {"success":true}', + }); + }); + it("returns 402 when settlement returns success: false", async () => { setupMockHttpServer( { diff --git a/typescript/packages/http/express/src/index.ts b/typescript/packages/http/express/src/index.ts index 74b67b7767..9f0e03231e 100644 --- a/typescript/packages/http/express/src/index.ts +++ b/typescript/packages/http/express/src/index.ts @@ -6,6 +6,8 @@ import { x402ResourceServer, RoutesConfig, FacilitatorClient, + FacilitatorResponseError, + getFacilitatorResponseError, } from "@x402/core/server"; import { SchemeNetworkServer, Network } from "@x402/core/types"; import { NextFunction, Request, Response } from "express"; @@ -44,6 +46,16 @@ export interface SchemeRegistration { server: SchemeNetworkServer; } +/** + * Sends a normalized 502 response for facilitator boundary failures. + * + * @param res - The Express response to write to + * @param error - The facilitator response error to surface + */ +function sendFacilitatorError(res: Response, error: FacilitatorResponseError): void { + res.status(502).json({ error: error.message }); +} + /** * Express payment middleware for x402 protocol (direct HTTP server instance). * @@ -82,6 +94,28 @@ export function paymentMiddlewareFromHTTPServer( // Store initialization promise (not the result) // httpServer.initialize() fetches facilitator support and validates routes let initPromise: Promise | null = syncFacilitatorOnStart ? httpServer.initialize() : null; + let isInitialized = false; + + /** + * Ensures facilitator initialization succeeds once, while allowing retries after failures. + */ + async function initializeHttpServer(): Promise { + if (!syncFacilitatorOnStart || isInitialized) { + return; + } + + if (!initPromise) { + initPromise = httpServer.initialize(); + } + + try { + await initPromise; + isInitialized = true; + } catch (error) { + initPromise = null; + throw error; + } + } // Dynamically register bazaar extension if routes declare it and not already registered // Skip if pre-registered (e.g., in serverless environments where static imports are used) @@ -112,9 +146,17 @@ export function paymentMiddlewareFromHTTPServer( } // Only initialize when processing a protected route - if (initPromise) { - await initPromise; - initPromise = null; // Clear after first await + if (syncFacilitatorOnStart && !isInitialized) { + try { + await initializeHttpServer(); + } catch (error) { + const facilitatorError = getFacilitatorResponseError(error); + if (facilitatorError) { + sendFacilitatorError(res, facilitatorError); + return; + } + return next(error); + } } // Await bazaar extension loading if needed @@ -124,7 +166,16 @@ export function paymentMiddlewareFromHTTPServer( } // Process payment requirement check - const result = await httpServer.processHTTPRequest(context, paywallConfig); + let result: Awaited>; + try { + result = await httpServer.processHTTPRequest(context, paywallConfig); + } catch (error) { + if (error instanceof FacilitatorResponseError) { + sendFacilitatorError(res, error); + return; + } + return next(error); + } // Handle the different result types switch (result.type) { @@ -265,6 +316,11 @@ export function paymentMiddlewareFromHTTPServer( res.setHeader(key, value); }); } catch (error) { + if (error instanceof FacilitatorResponseError) { + bufferedCalls = []; + sendFacilitatorError(res, error); + return; + } console.error(error); // If settlement fails, don't send the buffered response bufferedCalls = []; diff --git a/typescript/packages/http/hono/src/index.test.ts b/typescript/packages/http/hono/src/index.test.ts index 809a000584..7c280cc456 100644 --- a/typescript/packages/http/hono/src/index.test.ts +++ b/typescript/packages/http/hono/src/index.test.ts @@ -7,6 +7,7 @@ import type { FacilitatorClient, } from "@x402/core/server"; import { + FacilitatorResponseError, x402ResourceServer, x402HTTPResourceServer as HTTPResourceServer, } from "@x402/core/server"; @@ -40,6 +41,27 @@ let mockRegisterPaywallProvider: ReturnType; let mockRequiresPayment: ReturnType; vi.mock("@x402/core/server", () => ({ + FacilitatorResponseError: class FacilitatorResponseError extends Error { + /** + * Creates a mock facilitator response error. + * + * @param message - Error message. + */ + constructor(message: string) { + super(message); + this.name = "FacilitatorResponseError"; + } + }, + getFacilitatorResponseError: (error: unknown) => { + let current = error; + while (current instanceof Error) { + if (current.name === "FacilitatorResponseError") { + return current; + } + current = (current as Error & { cause?: unknown }).cause; + } + return null; + }, x402ResourceServer: vi.fn().mockImplementation(() => ({ initialize: vi.fn().mockResolvedValue(undefined), registerExtension: vi.fn(), @@ -396,6 +418,46 @@ describe("paymentMiddleware", () => { expect(context.json).toHaveBeenCalledWith({}, 402); }); + it("retries initialization after a facilitator init failure", async () => { + const initialize = vi + .fn() + .mockRejectedValueOnce( + new Error("Failed to initialize: no supported payment kinds loaded from any facilitator.", { + cause: new FacilitatorResponseError( + "Facilitator supported returned invalid JSON: not-json", + ), + }), + ) + .mockResolvedValueOnce(undefined); + + vi.mocked(HTTPResourceServer).mockImplementation( + (server, routes) => + ({ + initialize, + processHTTPRequest: mockProcessHTTPRequest, + processSettlement: mockProcessSettlement, + registerPaywallProvider: mockRegisterPaywallProvider, + requiresPayment: mockRequiresPayment, + routes, + server: server || { + hasExtension: vi.fn().mockReturnValue(false), + registerExtension: vi.fn(), + }, + }) as unknown as x402HTTPResourceServer, + ); + mockProcessHTTPRequest.mockResolvedValue({ type: "no-payment-required" }); + + const middleware = paymentMiddleware(mockRoutes, {} as unknown as x402ResourceServer); + const next = vi.fn().mockResolvedValue(undefined); + + await middleware(createMockContext(), next); + await middleware(createMockContext(), next); + + expect(initialize).toHaveBeenCalledTimes(2); + expect(mockProcessHTTPRequest).toHaveBeenCalledTimes(1); + expect(next).toHaveBeenCalledTimes(1); + }); + it("returns 402 when settlement returns success: false", async () => { setupMockHttpServer( { diff --git a/typescript/packages/http/hono/src/index.ts b/typescript/packages/http/hono/src/index.ts index 22ef837f45..8b3f42c070 100644 --- a/typescript/packages/http/hono/src/index.ts +++ b/typescript/packages/http/hono/src/index.ts @@ -6,6 +6,8 @@ import { x402ResourceServer, RoutesConfig, FacilitatorClient, + FacilitatorResponseError, + getFacilitatorResponseError, } from "@x402/core/server"; import { SchemeNetworkServer, Network } from "@x402/core/types"; import { Context, MiddlewareHandler } from "hono"; @@ -44,6 +46,17 @@ export interface SchemeRegistration { server: SchemeNetworkServer; } +/** + * Builds a normalized 502 response for facilitator boundary failures. + * + * @param c - The current Hono context + * @param error - The facilitator response error to surface + * @returns A JSON 502 response + */ +function facilitatorErrorResponse(c: Context, error: FacilitatorResponseError): Response { + return c.json({ error: error.message }, 502); +} + /** * Hono payment middleware for x402 protocol (direct HTTP server instance). * @@ -82,6 +95,28 @@ export function paymentMiddlewareFromHTTPServer( // Store initialization promise (not the result) // httpServer.initialize() fetches facilitator support and validates routes let initPromise: Promise | null = syncFacilitatorOnStart ? httpServer.initialize() : null; + let isInitialized = false; + + /** + * Ensures facilitator initialization succeeds once, while allowing retries after failures. + */ + async function initializeHttpServer(): Promise { + if (!syncFacilitatorOnStart || isInitialized) { + return; + } + + if (!initPromise) { + initPromise = httpServer.initialize(); + } + + try { + await initPromise; + isInitialized = true; + } catch (error) { + initPromise = null; + throw error; + } + } // Dynamically register bazaar extension if routes declare it and not already registered // Skip if pre-registered (e.g., in serverless environments where static imports are used) @@ -112,9 +147,16 @@ export function paymentMiddlewareFromHTTPServer( } // Only initialize when processing a protected route - if (initPromise) { - await initPromise; - initPromise = null; // Clear after first await + if (syncFacilitatorOnStart && !isInitialized) { + try { + await initializeHttpServer(); + } catch (error) { + const facilitatorError = getFacilitatorResponseError(error); + if (facilitatorError) { + return facilitatorErrorResponse(c, facilitatorError); + } + throw error; + } } // Await bazaar extension loading if needed @@ -124,7 +166,15 @@ export function paymentMiddlewareFromHTTPServer( } // Process payment requirement check - const result = await httpServer.processHTTPRequest(context, paywallConfig); + let result: Awaited>; + try { + result = await httpServer.processHTTPRequest(context, paywallConfig); + } catch (error) { + if (error instanceof FacilitatorResponseError) { + return facilitatorErrorResponse(c, error); + } + throw error; + } // Handle the different result types switch (result.type) { @@ -190,6 +240,11 @@ export function paymentMiddlewareFromHTTPServer( }); } } catch (error) { + if (error instanceof FacilitatorResponseError) { + res = facilitatorErrorResponse(c, error); + c.res = res; + return; + } console.error(error); // If settlement fails, return an error response res = c.json({}, 402); diff --git a/typescript/packages/http/next/src/index.test.ts b/typescript/packages/http/next/src/index.test.ts index 3c7b6c498f..3d1ded9ed6 100644 --- a/typescript/packages/http/next/src/index.test.ts +++ b/typescript/packages/http/next/src/index.test.ts @@ -30,6 +30,27 @@ const mockFunctions = { // Mock @x402/core/server vi.mock("@x402/core/server", () => ({ + FacilitatorResponseError: class FacilitatorResponseError extends Error { + /** + * Creates a mock facilitator response error. + * + * @param message - Error message. + */ + constructor(message: string) { + super(message); + this.name = "FacilitatorResponseError"; + } + }, + getFacilitatorResponseError: (error: unknown) => { + let current = error; + while (current instanceof Error) { + if (current.name === "FacilitatorResponseError") { + return current; + } + current = (current as Error & { cause?: unknown }).cause; + } + return null; + }, x402ResourceServer: vi.fn().mockImplementation(() => ({ initialize: vi.fn().mockResolvedValue(undefined), registerExtension: vi.fn(), diff --git a/typescript/packages/http/next/src/index.ts b/typescript/packages/http/next/src/index.ts index b29589e8d9..aab58e9d26 100644 --- a/typescript/packages/http/next/src/index.ts +++ b/typescript/packages/http/next/src/index.ts @@ -5,6 +5,7 @@ import { RoutesConfig, RouteConfig, FacilitatorClient, + FacilitatorResponseError, } from "@x402/core/server"; import { SchemeNetworkServer, Network } from "@x402/core/types"; import { NextRequest, NextResponse } from "next/server"; @@ -13,6 +14,8 @@ import { createRequestContext, handlePaymentError, handleSettlement, + createFacilitatorErrorResponse, + getFacilitatorResponseError, } from "./utils"; import { x402HTTPResourceServer } from "@x402/core/server"; @@ -85,7 +88,15 @@ export function paymentProxyFromHTTPServer( } // Only initialize when processing a protected route - await init(); + try { + await init(); + } catch (error) { + const facilitatorError = getFacilitatorResponseError(error); + if (facilitatorError) { + return createFacilitatorErrorResponse(facilitatorError); + } + throw error; + } // Await bazaar extension loading if needed if (bazaarPromise) { @@ -94,7 +105,15 @@ export function paymentProxyFromHTTPServer( } // Process payment requirement check - const result = await httpServer.processHTTPRequest(context, paywallConfig); + let result: Awaited>; + try { + result = await httpServer.processHTTPRequest(context, paywallConfig); + } catch (error) { + if (error instanceof FacilitatorResponseError) { + return createFacilitatorErrorResponse(error); + } + throw error; + } // Handle the different result types switch (result.type) { diff --git a/typescript/packages/http/next/src/utils.test.ts b/typescript/packages/http/next/src/utils.test.ts index d2d4a2797a..2b0167b008 100644 --- a/typescript/packages/http/next/src/utils.test.ts +++ b/typescript/packages/http/next/src/utils.test.ts @@ -13,15 +13,38 @@ import { handleSettlement, } from "./utils"; +let mockInitialize: ReturnType; + // Mock @x402/core/server vi.mock("@x402/core/server", () => { const MockHTTPResourceServer = vi.fn().mockImplementation(() => ({ - initialize: vi.fn().mockResolvedValue(undefined), + initialize: mockInitialize, registerPaywallProvider: vi.fn(), processSettlement: vi.fn(), requiresPayment: vi.fn().mockReturnValue(true), })); return { + FacilitatorResponseError: class FacilitatorResponseError extends Error { + /** + * Creates a mock facilitator response error. + * + * @param message - Error message. + */ + constructor(message: string) { + super(message); + this.name = "FacilitatorResponseError"; + } + }, + getFacilitatorResponseError: (error: unknown) => { + let current = error; + while (current instanceof Error) { + if (current.name === "FacilitatorResponseError") { + return current; + } + current = (current as Error & { cause?: unknown }).cause; + } + return null; + }, x402HTTPResourceServer: MockHTTPResourceServer, x402ResourceServer: vi.fn(), }; @@ -62,6 +85,10 @@ function createMockResourceServer(): x402ResourceServer { } describe("createHttpServer", () => { + beforeEach(() => { + mockInitialize = vi.fn().mockResolvedValue(undefined); + }); + it("creates server and initializes on start by default", async () => { const routes = { "/api/*": { @@ -107,6 +134,25 @@ describe("createHttpServer", () => { await init(); expect(httpServer.registerPaywallProvider).toHaveBeenCalledWith(paywall); }); + + it("retries initialization after a facilitator init failure", async () => { + mockInitialize = vi + .fn() + .mockRejectedValueOnce(new Error("not-json")) + .mockResolvedValueOnce(undefined); + const routes = { + "/api/*": { + accepts: { scheme: "exact", payTo: "0x123", price: "$0.01", network: "eip155:84532" }, + }, + } as const; + const server = createMockResourceServer(); + + const { init } = createHttpServer(routes, server); + + await expect(init()).rejects.toThrow("not-json"); + await expect(init()).resolves.toBeUndefined(); + expect(mockInitialize).toHaveBeenCalledTimes(2); + }); }); describe("createRequestContext", () => { diff --git a/typescript/packages/http/next/src/utils.ts b/typescript/packages/http/next/src/utils.ts index 84fc5d4a1d..11b634a66c 100644 --- a/typescript/packages/http/next/src/utils.ts +++ b/typescript/packages/http/next/src/utils.ts @@ -6,6 +6,8 @@ import { x402HTTPResourceServer, x402ResourceServer, RoutesConfig, + FacilitatorResponseError, + getFacilitatorResponseError as getCoreFacilitatorResponseError, } from "@x402/core/server"; import { PaymentPayload, PaymentRequirements } from "@x402/core/types"; import { NextAdapter } from "./adapter"; @@ -18,6 +20,21 @@ export interface HttpServerInstance { init: () => Promise; } +export const getFacilitatorResponseError = getCoreFacilitatorResponseError; + +/** + * Builds a normalized 502 response for facilitator boundary failures. + * + * @param error - The facilitator response error to surface + * @returns A JSON 502 response + */ +export function createFacilitatorErrorResponse(error: FacilitatorResponseError): NextResponse { + return new NextResponse(JSON.stringify({ error: error.message }), { + status: 502, + headers: { "Content-Type": "application/json" }, + }); +} + /** * Prepares an existing x402HTTPResourceServer with initialization logic * @@ -39,14 +56,28 @@ export function prepareHttpServer( // Store initialization promise (not the result) // httpServer.initialize() fetches facilitator support and validates routes let initPromise: Promise | null = syncFacilitatorOnStart ? httpServer.initialize() : null; + let isInitialized = false; return { httpServer, + /** + * Ensures facilitator initialization succeeds once, while allowing retries after failures. + */ async init() { - // Ensure initialization completes before processing - if (initPromise) { + if (!syncFacilitatorOnStart || isInitialized) { + return; + } + + if (!initPromise) { + initPromise = httpServer.initialize(); + } + + try { await initPromise; - initPromise = null; // Clear after first await + isInitialized = true; + } catch (error) { + initPromise = null; + throw error; } }, }; @@ -165,6 +196,9 @@ export async function handleSettlement( return response; } catch (error) { + if (error instanceof FacilitatorResponseError) { + return createFacilitatorErrorResponse(error); + } console.error("Settlement failed:", error); // If settlement fails, return an error response return new NextResponse(JSON.stringify({}), { diff --git a/typescript/packages/mechanisms/aptos/.prettierignore b/typescript/packages/mechanisms/aptos/.prettierignore new file mode 100644 index 0000000000..0510cefc24 --- /dev/null +++ b/typescript/packages/mechanisms/aptos/.prettierignore @@ -0,0 +1,3 @@ +# build output +dist/ +node_modules/ diff --git a/typescript/tsconfig.base.json b/typescript/tsconfig.base.json index 24872017fa..5a8cf39404 100644 --- a/typescript/tsconfig.base.json +++ b/typescript/tsconfig.base.json @@ -3,7 +3,7 @@ "target": "ES2020", "module": "ES2020", "lib": [ - "ES2020" + "ES2022" ], "moduleResolution": "bundler", "declaration": true, @@ -15,4 +15,4 @@ "forceConsistentCasingInFileNames": true, "resolveJsonModule": true } -} \ No newline at end of file +} From 7123ea47a6b6cffea76dd2e44b18f1f5ae624349 Mon Sep 17 00:00:00 2001 From: phdargen Date: Tue, 17 Mar 2026 01:30:37 +0900 Subject: [PATCH 074/129] chore(go): release v2.6.0 (#1637) --- go/.changes/unreleased/added-20260313-141700.yaml | 3 --- go/.changes/unreleased/changed-20260310-170850.yaml | 3 --- go/.changes/unreleased/fixed-20260310-221203.yaml | 3 --- .../unreleased/improved-permit2-gas-sponsoring.yaml | 3 --- go/CHANGELOG.md | 9 +++++++++ go/constants.go | 2 +- 6 files changed, 10 insertions(+), 13 deletions(-) delete mode 100644 go/.changes/unreleased/added-20260313-141700.yaml delete mode 100644 go/.changes/unreleased/changed-20260310-170850.yaml delete mode 100644 go/.changes/unreleased/fixed-20260310-221203.yaml delete mode 100644 go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml diff --git a/go/.changes/unreleased/added-20260313-141700.yaml b/go/.changes/unreleased/added-20260313-141700.yaml deleted file mode 100644 index a309dad93b..0000000000 --- a/go/.changes/unreleased/added-20260313-141700.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: added -body: Added simulation to permit2 verify and (optional) settle -time: 2026-03-13T14:17:00.280905+09:00 diff --git a/go/.changes/unreleased/changed-20260310-170850.yaml b/go/.changes/unreleased/changed-20260310-170850.yaml deleted file mode 100644 index 1dd67b4d45..0000000000 --- a/go/.changes/unreleased/changed-20260310-170850.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: changed -body: Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling -time: 2026-03-10T17:08:50.404017+09:00 diff --git a/go/.changes/unreleased/fixed-20260310-221203.yaml b/go/.changes/unreleased/fixed-20260310-221203.yaml deleted file mode 100644 index 75dd360069..0000000000 --- a/go/.changes/unreleased/fixed-20260310-221203.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: fixed -body: Fixed paywall config injection targeting `` causing SVG parse errors in the browser -time: 2026-03-10T22:12:03.806859+09:00 diff --git a/go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml b/go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml deleted file mode 100644 index 15b5c015d5..0000000000 --- a/go/.changes/unreleased/improved-permit2-gas-sponsoring.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: changed -body: Replaced SendRawApprovalAndSettle with a generic SendTransactions signer method that accepts an array of transaction requests (pre-signed or unsigned intents). Closed fail-open verification paths, aligned Permit2 amount check to exact match, and improved client extension fallback error handling -time: 2026-03-06T12:00:00.000000-08:00 diff --git a/go/CHANGELOG.md b/go/CHANGELOG.md index 47ab393174..dd66eea3b4 100644 --- a/go/CHANGELOG.md +++ b/go/CHANGELOG.md @@ -1,3 +1,12 @@ +## v2.6.0 - 2026-03-17 +### Added +- Added simulation to permit2 verify and (optional) settle +### Changed +- Replaced SendRawApprovalAndSettle with a generic SendTransactions signer method that accepts an array of transaction requests (pre-signed or unsigned intents). Closed fail-open verification paths, aligned Permit2 amount check to exact match, and improved client extension fallback error handling +- Simulate transaction in verify and (optional) settle; Added multicall utility for efficient rpc calls; Fixed undeployed smart wallet handling +### Fixed +- Fixed paywall config injection targeting `` causing SVG parse errors in the browser + ## v2.5.0 - 2026-03-06 ### Added - Add route configuration validation during Initialize() to catch scheme/facilitator mismatches at startup diff --git a/go/constants.go b/go/constants.go index 27cda41c8f..3b8a7a5b23 100644 --- a/go/constants.go +++ b/go/constants.go @@ -3,7 +3,7 @@ package x402 // Version constants const ( // Version is the SDK version - Version = "2.4.0" + Version = "2.6.0" // ProtocolVersion is the current x402 protocol version ProtocolVersion = 2 From 920c54471193a2b6f49e8d531bdd4b35c62a1881 Mon Sep 17 00:00:00 2001 From: Carson Roscoe Date: Mon, 16 Mar 2026 12:41:54 -0700 Subject: [PATCH 075/129] feat: update e2e tests (#1641) * feat: update e2e tests * feat: added wait --- e2e/README.md | 24 ++++++- e2e/servers/express/index.ts | 2 + e2e/servers/gin/main.go | 14 +++- e2e/test.ts | 126 +++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 5 deletions(-) diff --git a/e2e/README.md b/e2e/README.md index c704cbcb0b..9a54295429 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -85,12 +85,32 @@ Add the `-v` flag to any command for verbose output: Useful for debugging test failures or understanding the payment flow. +## Wallet Safety Warning + +**Use dedicated test wallets only. Do NOT use wallets that hold real funds.** + +The test suite moves ETH between the configured wallets during a run. Funds stay +within the set of wallets defined in `.env`, but individual wallet balances will +change unpredictably: + +- **ETH is transferred** from the facilitator wallet to the client wallet so the + client can pay gas for granting and revoking Permit2 approvals between tests. +- **ETH is swept** from the client wallet back to the facilitator after revocation + to create a zero-balance state, which is required to exercise the facilitator's + gasless funding step. +- **Token approvals are granted and revoked** on the client wallet as part of + normal test flow. + +While no funds leave the configured wallet set, the client wallet's ETH balance +will be drained to near-zero between tests. Do not rely on any particular wallet +having a stable balance during or after a run. + ## Environment Variables Required environment variables (set in `.env` file): ```bash -# Client wallets +# Client wallets (⚠️ TEST WALLETS ONLY β€” balances will be swept during runs) CLIENT_EVM_PRIVATE_KEY=0x... # EVM private key for client payments CLIENT_SVM_PRIVATE_KEY=... # Solana private key for client payments CLIENT_APTOS_PRIVATE_KEY=... # Aptos private key for client payments (hex string) @@ -102,7 +122,7 @@ SERVER_SVM_ADDRESS=... # Where servers receive Solana payments SERVER_APTOS_ADDRESS=0x... # Where servers receive Aptos payments SERVER_STELLAR_ADDRESS=... # Where servers receive Stellar payments -# Facilitator wallets (for payment verification/settlement) +# Facilitator wallets (⚠️ TEST WALLETS ONLY β€” used to fund/drain client between tests) FACILITATOR_EVM_PRIVATE_KEY=0x... # EVM private key for facilitator FACILITATOR_SVM_PRIVATE_KEY=... # Solana private key for facilitator FACILITATOR_APTOS_PRIVATE_KEY=... # Aptos private key for facilitator (hex string) diff --git a/e2e/servers/express/index.ts b/e2e/servers/express/index.ts index d798d8cfdb..7a451622a9 100644 --- a/e2e/servers/express/index.ts +++ b/e2e/servers/express/index.ts @@ -222,6 +222,8 @@ app.use( asset: EVM_PERMIT2_ASSET, extra: { assetTransferMethod: "permit2", + name: EVM_NETWORK == "eip155:84532" ? "USDC" : "USD Coin", + version: "2", }, }, }, diff --git a/e2e/servers/gin/main.go b/e2e/servers/gin/main.go index b413d59d61..b83a63c6fc 100644 --- a/e2e/servers/gin/main.go +++ b/e2e/servers/gin/main.go @@ -178,9 +178,17 @@ func main() { Price: map[string]interface{}{ "amount": "1000", "asset": evmPermit2Asset, - "extra": map[string]interface{}{ - "assetTransferMethod": "permit2", - }, + "extra": func() map[string]interface{} { + name := "USD Coin" + if evmNetworkStr == "eip155:84532" { + name = "USDC" + } + return map[string]interface{}{ + "assetTransferMethod": "permit2", + "name": name, + "version": "2", + } + }(), }, }, }, diff --git a/e2e/test.ts b/e2e/test.ts index dd46c65a47..1f5740901f 100644 --- a/e2e/test.ts +++ b/e2e/test.ts @@ -1,6 +1,9 @@ import { config } from 'dotenv'; import { spawn, execSync } from 'child_process'; import { writeFileSync } from 'fs'; +import { createWalletClient, createPublicClient, http, parseEther, formatEther } from 'viem'; +import { privateKeyToAccount } from 'viem/accounts'; +import { base, baseSepolia } from 'viem/chains'; import { TestDiscovery } from './src/discovery'; import { ClientConfig, ScenarioResult, ServerConfig, TestScenario } from './src/types'; import { config as loggerConfig, log, verboseLog, errorLog, close as closeLogger, createComboLogger } from './src/logger'; @@ -120,6 +123,123 @@ async function revokePermit2Approval(tokenAddress?: string): Promise { }); } +/** + * Shared EVM clients for the ETH sandwich helpers. + * Lazily initialised on first use so that missing env vars don't blow up + * non-EVM test runs. + */ +function getEvmClients() { + const evmNetwork = process.env.EVM_NETWORK || 'eip155:84532'; + const evmRpcUrl = process.env.EVM_RPC_URL; + const evmChain = evmNetwork === 'eip155:8453' ? base : baseSepolia; + + const facilitatorKey = process.env.FACILITATOR_EVM_PRIVATE_KEY; + const clientKey = process.env.CLIENT_EVM_PRIVATE_KEY; + if (!facilitatorKey || !clientKey) { + throw new Error('FACILITATOR_EVM_PRIVATE_KEY and CLIENT_EVM_PRIVATE_KEY must be set'); + } + + const facilitatorAccount = privateKeyToAccount(facilitatorKey as `0x${string}`); + const clientAccount = privateKeyToAccount(clientKey as `0x${string}`); + + const publicClient = createPublicClient({ + chain: evmChain, + transport: http(evmRpcUrl), + }); + const facilitatorWallet = createWalletClient({ + account: facilitatorAccount, + chain: evmChain, + transport: http(evmRpcUrl), + }); + const clientWallet = createWalletClient({ + account: clientAccount, + chain: evmChain, + transport: http(evmRpcUrl), + }); + + return { publicClient, facilitatorWallet, clientWallet, facilitatorAccount, clientAccount }; +} + +const REVOKE_FUND_AMOUNT = parseEther('0.001'); + +/** + * Send a small amount of ETH from the facilitator wallet to the client wallet + * so the client can pay gas for Permit2 revocation transactions. + */ +async function fundClientForRevoke(): Promise { + try { + const { publicClient, facilitatorWallet, facilitatorAccount, clientAccount } = getEvmClients(); + + const clientBalance = await publicClient.getBalance({ address: clientAccount.address }); + if (clientBalance >= REVOKE_FUND_AMOUNT) { + verboseLog(` ℹ️ Client already has ${formatEther(clientBalance)} ETH, skipping fund`); + return true; + } + + const facilitatorBalance = await publicClient.getBalance({ address: facilitatorAccount.address }); + if (facilitatorBalance < REVOKE_FUND_AMOUNT) { + errorLog(` ❌ Facilitator wallet ${facilitatorAccount.address} has insufficient ETH (${formatEther(facilitatorBalance)}) to fund client for revoke.`); + errorLog(` Please fund the facilitator wallet with testnet ETH (need at least ${formatEther(REVOKE_FUND_AMOUNT)} ETH).`); + return false; + } + + verboseLog(` πŸ’Έ Funding client ${clientAccount.address} with ${formatEther(REVOKE_FUND_AMOUNT)} ETH for revoke...`); + const hash = await facilitatorWallet.sendTransaction({ + to: clientAccount.address, + value: REVOKE_FUND_AMOUNT, + }); + await publicClient.waitForTransactionReceipt({ hash }); + verboseLog(` βœ… Funded client (tx: ${hash})`); + return true; + } catch (err) { + errorLog(` ❌ Failed to fund client for revoke: ${err instanceof Error ? err.message : err}`); + return false; + } +} + +/** + * Drain all ETH from the client wallet back to the facilitator wallet, + * leaving the client with ~0 ETH so the gas sponsoring funding step is + * exercised during the test. + */ +async function drainClientETH(): Promise { + try { + const { publicClient, clientWallet, facilitatorAccount, clientAccount } = getEvmClients(); + + const balance = await publicClient.getBalance({ address: clientAccount.address }); + if (balance === 0n) { + verboseLog(' ℹ️ Client ETH balance is already 0'); + return true; + } + + // Reserve enough for gas. On L2s getGasPrice() returns a tiny value but + // viem's sendTransaction uses a higher maxFeePerGas with safety margin. + // Use a generous fixed buffer to avoid "insufficient funds" from the + // estimateGas pre-check. + const GAS_RESERVE = parseEther('0.0001'); + const sendAmount = balance - GAS_RESERVE; + + if (sendAmount <= 0n) { + verboseLog(` ℹ️ Client balance (${formatEther(balance)} ETH) too small to drain, leaving as dust`); + return true; + } + + verboseLog(` πŸ’Έ Draining ${formatEther(sendAmount)} ETH from client back to facilitator...`); + const hash = await clientWallet.sendTransaction({ + to: facilitatorAccount.address, + value: sendAmount, + }); + await publicClient.waitForTransactionReceipt({ hash }); + + const remaining = await publicClient.getBalance({ address: clientAccount.address }); + verboseLog(` βœ… Drained client ETH (tx: ${hash}, remaining: ${formatEther(remaining)} ETH)`); + return true; + } catch (err) { + errorLog(` ❌ Failed to drain client ETH: ${err instanceof Error ? err.message : err}`); + return false; + } +} + // Load environment variables config(); @@ -704,12 +824,18 @@ async function runTest() { if (scenario.endpoint.permit2Direct) { await approvePermit2Approval(USDC_BASE_SEPOLIA); } else { + await fundClientForRevoke(); const token = scenario.endpoint.extensions?.includes('erc20ApprovalGasSponsoring') ? MOCK_ERC20_BASE_SEPOLIA : USDC_BASE_SEPOLIA; await revokePermit2Approval(token); + await new Promise(resolve => setTimeout(resolve, 2000)); + await drainClientETH(); } + // Wait for RPC nonce propagation across load-balanced nodes before the + // test client (which may use a separate RPC connection) queries the nonce. + await new Promise(resolve => setTimeout(resolve, 2000)); } if (isEvm && facilitatorName && evmLock) { From 169796a339869e470558394cadceed160b04ccdf Mon Sep 17 00:00:00 2001 From: Pablo <72654865+moonshot-cyber@users.noreply.github.com> Date: Tue, 17 Mar 2026 01:21:17 +0000 Subject: [PATCH 076/129] ecosystem: update Agent Health Monitor description (#1644) - Update endpoint count from 10 to 11 - Rewrite description to be agent-first, highlighting AHS composite scoring, wash scans, and gas optimisation - No changes to logo, URL, or category Co-authored-by: Claude Opus 4.6 --- .../ecosystem/partners-data/agent-health-monitor/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json b/typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json index 2ff2937c07..5327b83902 100644 --- a/typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json +++ b/typescript/site/app/ecosystem/partners-data/agent-health-monitor/metadata.json @@ -1,6 +1,6 @@ { "name": "Agent Health Monitor", - "description": "10-endpoint wallet intelligence API enriched with Nansen blockchain analytics. Risk scores, health checks, counterparty analysis, wallet network mapping, PnL summaries, and autonomous protection β€” all pay-per-call via x402 on Base.", + "description": "Pay-per-call diagnostic infrastructure for autonomous agents on Base. 11 x402 endpoints delivering health scores, risk analysis, gas optimisation, wash scans, and AHS composite scoring. The mechanic layer for the agent economy.", "logoUrl": "/logos/agent-health-monitor.png", "websiteUrl": "https://agenthealthmonitor.xyz", "category": "Services/Endpoints" From cae3a216073da32111d189666eeab8b462af7b50 Mon Sep 17 00:00:00 2001 From: Marcelo Salloum dos Santos Date: Mon, 16 Mar 2026 18:22:45 -0700 Subject: [PATCH 077/129] docs: make /verify required in Stellar exact scheme spec (#1640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The protocol flow previously sent directly to /settle and declared /verify as optional. Per maintainer feedback on PR #1575, verify is required β€” it prevents the resource server from doing unnecessary work for invalid payloads. This aligns the Stellar spec with the SVM and Hedera exact scheme specs. --- specs/schemes/exact/scheme_exact_stellar.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/specs/schemes/exact/scheme_exact_stellar.md b/specs/schemes/exact/scheme_exact_stellar.md index 6eeecbccd8..87a6980b8f 100644 --- a/specs/schemes/exact/scheme_exact_stellar.md +++ b/specs/schemes/exact/scheme_exact_stellar.md @@ -28,14 +28,16 @@ The protocol flow for `exact` on Stellar is client-driven with facilitator-spons 4. **Client** signs the authorization entries (not the full transaction) with their wallet, setting expiration to `currentLedger + ledgerTimeout`, where `ledgerTimeout = ceil(maxTimeoutSeconds / estimatedLedgerSeconds)`; implementations should use the current network estimate for `estimatedLedgerSeconds` when available (fallback to `5` seconds). 5. **Client** serializes the transaction with signed auth entries and encodes it as XDR (base64). 6. **Client** sends a new request to the resource server with the `PaymentPayload` containing the base64-encoded transaction. -7. **Resource Server** forwards the `PaymentPayload` and `PaymentRequirements` to the **Facilitator Server's** `/settle` endpoint. - - NOTE: `/verify` is optional and intended for pre-flight checks only. `/settle` MUST perform full verification independently and MUST NOT assume prior verification. +7. **Resource Server** forwards the `PaymentPayload` and `PaymentRequirements` to the **Facilitator Server's** `/verify` endpoint. 8. **Facilitator** decodes the transaction XDR and validates the transaction's: structure, auth entries, signature expiration, amount, payer, and recipient. -9. **Facilitator** rebuilds the transaction with its own account as the source, preserving all operations and auth entries. -10. **Facilitator** simulates the transaction to verify it succeeds and emits the expected transfer events. -11. **Facilitator** signs the rebuilt transaction with its own key and submits it to the Stellar network via RPC `sendTransaction`. -12. **Facilitator** polls for transaction confirmation and responds with a `SettlementResponse` to the **Resource Server**. -13. **Resource Server** grants the **Client** access to the resource in its response upon successful settlement. +9. **Facilitator** returns a `VerifyResponse` to the **Resource Server**. +10. **Resource Server**, upon successful verification, forwards the payload to the facilitator's `/settle` endpoint. + - NOTE: `/settle` MUST perform full verification independently and MUST NOT assume prior verification. +11. **Facilitator** rebuilds the transaction with its own account as the source, preserving all operations and auth entries. +12. **Facilitator** simulates the transaction to verify it succeeds and emits the expected transfer events. +13. **Facilitator** signs the rebuilt transaction with its own key and submits it to the Stellar network via RPC `sendTransaction`. +14. **Facilitator** polls for transaction confirmation and responds with a `SettlementResponse` to the **Resource Server**. +15. **Resource Server** grants the **Client** access to the resource in its response upon successful settlement. ## `PaymentRequirements` for `exact` From 4f2f4f33daaf244acfe07a6d67f52ce2d80907f3 Mon Sep 17 00:00:00 2001 From: Sam Ragsdale <65786432+sragss@users.noreply.github.com> Date: Tue, 17 Mar 2026 05:06:08 -0400 Subject: [PATCH 078/129] fix(siwx): generate nonce/issuedAt in declareSIWxExtension for auth-only endpoints (#1140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(siwx): generate nonce/issuedAt in declareSIWxExtension for auth-only endpoints `declareSIWxExtension()` now generates `nonce`, `issuedAt`, and `expirationTime` directly. Previously these were only populated by the enrichment pipeline, which doesn't run for auth-only endpoints (`accepts: []`). Clients detecting the SIWX extension couldn't sign a valid proof without these fields. Safe for the enrichment pipeline β€” it builds a fresh info object per-request, overwriting the pre-generated values. Also adds convenience functions for the auth-only flow: - `signSIWxChallenge(extension, signer)` β†’ header string - `verifySIWxHeader(header, resourceUri)` β†’ { valid, address } And an auth-only `/profile` endpoint in the SIWX example. * refactor(siwx): separate createSIWxChallenge from declareSIWxExtension Revert declareSIWxExtension to static-only. Add createSIWxChallenge for auth-only endpoints that need per-request nonce/issuedAt. * feat(siwx): auth-only routes through the enrichment pipeline accepts: [] routes now go through the same pipeline as paid routes. createSIWxRequestHook detects auth-only via routeConfig and grants access on valid SIWX alone. nonce replay protection included. server example /profile moved from manual handler to declarative config. * chore: add changeset for siwx auth-only pipeline * fix(siwx): address review feedback on auth-only examples Server: replace verifySIWxHeader with parseSIWxHeader in /profile handler β€” the SIWX hook already verified the signature, so the handler only needs to decode the header to extract the wallet address. Client: replace manual two-step challenge flow with fetchWithPayment, which handles auth-only routes transparently through the same hook pipeline as paid routes. This demonstrates the key design point: callers don't need to distinguish between paid and auth-only endpoints. * refactor(siwx): remove standalone utilities, keep PR focused Remove createSIWxChallenge, signSIWxChallenge, and verifySIWxHeader β€” convenience wrappers that aren't needed now that auth-only routes go through the existing enrichment pipeline via accepts: []. The core change is the isAuthOnly check in createSIWxRequestHook. Everything else (challenge generation, nonce tracking, signature verification) is already handled by the pipeline and hooks. * fix: add JSDoc to test helper to satisfy lint * docs(siwx): align auth-only docs and examples * docs(siwx): clarify server example prerequisites --- .../clients/sign-in-with-x/README.md | 34 +- .../clients/sign-in-with-x/index.ts | 26 +- .../servers/sign-in-with-x/README.md | 52 +++- .../servers/sign-in-with-x/index.ts | 18 +- typescript/.changeset/auth-only-pipeline.md | 5 + typescript/packages/extensions/README.md | 49 +-- .../extensions/src/sign-in-with-x/hooks.ts | 24 +- .../extensions/src/sign-in-with-x/index.ts | 61 +--- .../extensions/test/sign-in-with-x.test.ts | 291 ++++++++++++++---- 9 files changed, 380 insertions(+), 180 deletions(-) create mode 100644 typescript/.changeset/auth-only-pipeline.md diff --git a/examples/typescript/clients/sign-in-with-x/README.md b/examples/typescript/clients/sign-in-with-x/README.md index e5dc2f0db5..08db11a13a 100644 --- a/examples/typescript/clients/sign-in-with-x/README.md +++ b/examples/typescript/clients/sign-in-with-x/README.md @@ -1,6 +1,8 @@ # Sign-In-With-X (SIWX) Client Example -Client demonstrating how to use Sign-In-With-X authentication with x402, allowing wallet signatures to prove prior payment and skip re-payment on subsequent requests. +Client demonstrating both SIWX flows supported by x402: +- Auth-only access for routes that require a wallet signature but no payment +- Paid-once access where SIWX proves a wallet has already paid ```typescript import { x402Client, x402HTTPClient, wrapFetchWithPayment } from "@x402/fetch"; @@ -24,19 +26,22 @@ const httpClient = new x402HTTPClient(client).onPaymentRequired( const fetchWithPayment = wrapFetchWithPayment(fetch, httpClient); -// First request: pays for access -const response1 = await fetchWithPayment("http://localhost:4021/weather"); +// Auth-only route: 402 challenge -> sign -> retry, no payment +const profile = await fetchWithPayment("http://localhost:4021/profile"); -// Second request: SIWX proves we already paid, no payment needed -const response2 = await fetchWithPayment("http://localhost:4021/weather"); +// Paid route: first request pays for access +const weather1 = await fetchWithPayment("http://localhost:4021/weather"); + +// Paid route: second request uses SIWX to prove prior payment +const weather2 = await fetchWithPayment("http://localhost:4021/weather"); ``` ## How It Works -1. **First request** β€” Client pays for resource access -2. **Server remembers** β€” Payment is recorded against wallet address -3. **Second request** β€” Client signs SIWX message proving wallet ownership -4. **Server grants access** β€” No payment required, authenticated via signature +1. **Auth-only route** β€” Client receives a SIWX challenge, signs it, and retries without payment +2. **Paid route, first request** β€” Client pays for resource access +3. **Server remembers** β€” Payment is recorded against wallet address +4. **Paid route, later request** β€” Client signs SIWX message proving wallet ownership instead of paying again ## Prerequisites @@ -59,7 +64,7 @@ and provide at least one private key: - `SVM_PRIVATE_KEY` - (Optional) Solana private key for SVM payments and SIWX authentication - `RESOURCE_SERVER_URL` - (Optional) Server URL (defaults to `http://localhost:4021`) -**Note:** At least one private key (EVM or SVM) is required. SIWX supports both EVM signatures (EIP-191) and Solana signatures (Ed25519), so authentication works with either key type. +**Note:** At least one private key (EVM or SVM) is required. The `/profile` auth-only example and the paid `/weather` and `/joke` routes all work with either signer type. 2. Install and build from typescript examples root: @@ -87,8 +92,13 @@ pnpm start ``` Client EVM address: 0x... +Client SVM address: ... Server: http://localhost:4021 +--- /profile (auth-only, no payment) --- + βœ“ Authenticated via SIWX (no payment required) + Response: { address: '0x...', data: 'Your profile data' } + --- /weather --- 1. First request... βœ“ Paid via payment settlement @@ -110,4 +120,6 @@ Server: http://localhost:4021 2. Second request... βœ“ Authenticated via SIWX (previously paid) ... -``` \ No newline at end of file + +Done. /profile used auth-only SIWX. /weather and /joke used payment + SIWX. +``` diff --git a/examples/typescript/clients/sign-in-with-x/index.ts b/examples/typescript/clients/sign-in-with-x/index.ts index 29fd94cc4f..a8b1b31cfe 100644 --- a/examples/typescript/clients/sign-in-with-x/index.ts +++ b/examples/typescript/clients/sign-in-with-x/index.ts @@ -102,6 +102,27 @@ async function demonstrateResource(path: string): Promise { } } +/** + * Demonstrates auth-only SIWX flow (no payment required). + * The client hook handles the 402 β†’ sign β†’ retry cycle automatically. + */ +async function demonstrateAuthOnly(): Promise { + const url = `${baseURL}/profile`; + console.log("\n--- /profile (auth-only, no payment) ---"); + + // fetchWithPayment handles auth-only routes the same way as paid routes: + // 402 β†’ SIWX client hook signs the challenge β†’ retry with signature + const response = await fetchWithPayment(url); + const body = await response.json(); + + if (response.ok) { + console.log(" βœ“ Authenticated via SIWX (no payment required)"); + console.log(" Response:", body); + } else { + console.log(" βœ— Auth failed:", body); + } +} + /** * Main entry point - demonstrates SIWX authentication flow. */ @@ -114,6 +135,9 @@ async function main(): Promise { } console.log(`Server: ${baseURL}`); + // Auth-only: SIWX signature without payment + await demonstrateAuthOnly(); + await demonstrateResource("/weather"); // Small delay to avoid facilitator race condition with rapid payments @@ -121,7 +145,7 @@ async function main(): Promise { await demonstrateResource("/joke"); - console.log("\nDone. Each resource required payment once, then SIWX auth worked."); + console.log("\nDone. /profile used auth-only SIWX. /weather and /joke used payment + SIWX."); } main().catch(err => { diff --git a/examples/typescript/servers/sign-in-with-x/README.md b/examples/typescript/servers/sign-in-with-x/README.md index 61cf87879f..dc37bc16af 100644 --- a/examples/typescript/servers/sign-in-with-x/README.md +++ b/examples/typescript/servers/sign-in-with-x/README.md @@ -1,6 +1,8 @@ # Sign-In-With-X (SIWX) Server Example -Express.js server demonstrating how to implement Sign-In-With-X authentication, allowing clients to prove prior payment via wallet signatures instead of paying again on subsequent requests. +Express.js server demonstrating both SIWX patterns supported by x402: +- Auth-only routes that require a wallet signature but no payment +- Paid routes where a wallet can pay once, then authenticate with SIWX on later requests ```typescript import express from "express"; @@ -31,16 +33,16 @@ app.use(paymentMiddlewareFromHTTPServer(httpServer)); ## How It Works -1. **Client pays** β€” First request requires payment -2. **Server records** β€” Payment recorded against wallet address in storage -3. **Client signs** β€” Subsequent requests include SIWX signature -4. **Server verifies** β€” Signature proves wallet ownership, grants access without payment +1. **Auth-only route** β€” Server returns a SIWX challenge and grants access on a valid signature alone +2. **Paid route** β€” First request requires payment +3. **Server records** β€” Payment is recorded against the wallet address in storage +4. **Later paid-route request** β€” Signature proves wallet ownership and grants access without re-payment ## 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 address (SVM optional) +- At least one payout address: EVM, SVM, or both - Facilitator URL (see [facilitator list](https://www.x402.org/ecosystem?category=facilitators)) ## Setup @@ -54,9 +56,11 @@ cp .env-local .env and fill required environment variables: - `FACILITATOR_URL` - Facilitator endpoint URL -- `EVM_ADDRESS` - Ethereum address to receive payments +- `EVM_ADDRESS` - (Optional) Ethereum address to receive payments - `SVM_ADDRESS` - (Optional) Solana address for SVM payments +At least one of `EVM_ADDRESS` or `SVM_ADDRESS` is required. + 2. Install and build from typescript examples root: ```bash @@ -77,22 +81,24 @@ Start the SIWX client to test: ```bash cd ../../clients/sign-in-with-x -# Ensure .env is setup with EVM_PRIVATE_KEY +# Ensure .env is setup with EVM_PRIVATE_KEY or SVM_PRIVATE_KEY pnpm start ``` The client will: -1. Make first request and pay for `/weather` -2. Make second request with SIWX signature (no payment) -3. Make first request and pay for `/joke` -4. Make second request with SIWX signature (no payment) +1. Access `/profile` with SIWX and no payment +2. Make first request and pay for `/weather` +3. Make second request to `/weather` with SIWX instead of payment +4. Make first request and pay for `/joke` +5. Make second request to `/joke` with SIWX instead of payment ## Example Endpoints +- `GET /profile` β€” Auth-only wallet-gated profile data (no payment) - `GET /weather` β€” Weather data ($0.001 USDC) - `GET /joke` β€” Joke content ($0.001 USDC) -Each endpoint requires payment once per wallet address. Subsequent requests from the same wallet authenticate via SIWX signature. +`/profile` requires only a valid SIWX signature. `/weather` and `/joke` require payment once per wallet address, then accept SIWX on later requests. ## SIWX Extension Configuration @@ -108,6 +114,15 @@ const routes = { mimeType: "application/json", extensions: declareSIWxExtension(), // Announces SIWX support }, + "GET /profile": { + accepts: [], + description: "Auth-only: wallet signature required", + extensions: declareSIWxExtension({ + network: ["eip155:84532", "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"], + statement: "Sign in to view your profile", + expirationSeconds: 300, + }), + }, }; ``` @@ -127,6 +142,8 @@ const httpServer = new x402HTTPResourceServer(resourceServer, routes) .onProtectedRequest(createSIWxRequestHook({ storage })); // Checks SIWX auth ``` +For routes declared with `accepts: []`, the request hook grants access on valid SIWX alone. For paid routes, it also checks whether that wallet has already paid. + ## Storage Backend This example uses in-memory storage (`InMemorySIWxStorage`). For production, implement persistent storage: @@ -135,11 +152,11 @@ This example uses in-memory storage (`InMemorySIWxStorage`). For production, imp import { SIWxStorage } from "@x402/extensions/sign-in-with-x"; class RedisSIWxStorage implements SIWxStorage { - async recordPayment(address: string, resource: string): Promise { + async recordPayment(resource: string, address: string): Promise { // Store in Redis/database } - async hasAccess(address: string, resource: string): Promise { + async hasPaid(resource: string, address: string): Promise { // Check Redis/database } } @@ -171,5 +188,6 @@ createSIWxRequestHook({ storage, onEvent }); Event types: - `payment_recorded` β€” Wallet paid for resource -- `access_granted` β€” SIWX signature verified -- `access_denied` β€” Invalid or missing signature \ No newline at end of file +- `access_granted` β€” SIWX signature verified and access granted +- `validation_failed` β€” Header parsing, message validation, or signature verification failed +- `nonce_reused` β€” A previously used SIWX nonce was replayed diff --git a/examples/typescript/servers/sign-in-with-x/index.ts b/examples/typescript/servers/sign-in-with-x/index.ts index 2801fa8728..0bfdaa6d91 100644 --- a/examples/typescript/servers/sign-in-with-x/index.ts +++ b/examples/typescript/servers/sign-in-with-x/index.ts @@ -14,6 +14,7 @@ import { createSIWxSettleHook, createSIWxRequestHook, InMemorySIWxStorage, + parseSIWxHeader, } from "@x402/extensions/sign-in-with-x"; config(); @@ -95,6 +96,15 @@ function routeConfig(path: string) { const routes = { "GET /weather": routeConfig("/weather"), "GET /joke": routeConfig("/joke"), + "GET /profile": { + accepts: [] as [], + description: "Auth-only: wallet signature required", + extensions: declareSIWxExtension({ + network: [EVM_NETWORK, SVM_NETWORK], // Required for auth-only routes (no payment to infer from) + statement: "Sign in to view your profile", + expirationSeconds: 300, + }), + }, }; // Configure resource server with SIWX extension and settle hook @@ -114,14 +124,20 @@ const httpServer = new x402HTTPResourceServer(resourceServer, routes).onProtecte ); const app = express(); + app.use(paymentMiddlewareFromHTTPServer(httpServer)); app.get("/weather", (_req, res) => res.json({ weather: "sunny", temperature: 72 })); app.get("/joke", (_req, res) => res.json({ joke: "Why do programmers prefer dark mode? Because light attracts bugs." }), ); +app.get("/profile", (req, res) => { + // SIWX hook already verified the signature β€” just parse to extract the address + const { address } = parseSIWxHeader(req.headers["sign-in-with-x"] as string); + res.json({ address, data: "Your profile data" }); +}); app.listen(PORT, () => { console.log(`Server running at http://localhost:${PORT}`); - console.log(`Routes: GET /weather, GET /joke`); + console.log(`Routes: GET /weather, GET /joke, GET /profile (auth-only)`); }); diff --git a/typescript/.changeset/auth-only-pipeline.md b/typescript/.changeset/auth-only-pipeline.md new file mode 100644 index 0000000000..b9fd5d482e --- /dev/null +++ b/typescript/.changeset/auth-only-pipeline.md @@ -0,0 +1,5 @@ +--- +'@x402/extensions': minor +--- + +Added auth-only route support in createSIWxRequestHook via accepts: [] detection diff --git a/typescript/packages/extensions/README.md b/typescript/packages/extensions/README.md index 91d4c56078..f937322d0a 100644 --- a/typescript/packages/extensions/README.md +++ b/typescript/packages/extensions/README.md @@ -471,7 +471,7 @@ The Sign-In-With-X extension implements [CAIP-122](https://chainagnostic.org/CAI 1. Server returns 402 with `sign-in-with-x` extension containing challenge parameters 2. Client signs the CAIP-122 message with their wallet 3. Client sends signed proof in `SIGN-IN-WITH-X` header -4. Server verifies signature and grants access if wallet has previous payment +4. Server verifies signature and grants access either because the route is auth-only or because the wallet has previously paid ### Server Usage @@ -495,7 +495,7 @@ const resourceServer = new x402ResourceServer(facilitatorClient) .registerExtension(siwxResourceServerExtension) // Refreshes nonce/timestamps per request .onAfterSettle(createSIWxSettleHook({ storage })); // Records payments -// 2. Declare SIWX support in routes (network/domain/uri derived automatically) +// 2. Declare SIWX support in routes const routes = { "GET /data": { accepts: [{scheme: "exact", price: "$0.01", network: "eip155:8453", payTo}], @@ -503,11 +503,19 @@ const routes = { statement: 'Sign in to access your purchased content', }), }, + "GET /profile": { + accepts: [], + extensions: declareSIWxExtension({ + network: ["eip155:8453", "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"], + statement: 'Sign in to view your profile', + expirationSeconds: 300, + }), + }, }; // 3. Verify incoming SIWX proofs const httpServer = new x402HTTPResourceServer(resourceServer, routes) - .onProtectedRequest(createSIWxRequestHook({ storage })); // Grants access if paid + .onProtectedRequest(createSIWxRequestHook({ storage })); // Grants access when SIWX auth is sufficient // Optional: Enable smart wallet support (EIP-1271/EIP-6492) import { createPublicClient, http } from 'viem'; @@ -524,7 +532,7 @@ const httpServerWithSmartWallets = new x402HTTPResourceServer(resourceServer, ro The hooks automatically: - **siwxResourceServerExtension**: Derives `network` from `accepts`, `domain`/`uri` from request URL, refreshes `nonce`/`issuedAt`/`expirationTime` per request - **createSIWxSettleHook**: Records payment when settlement succeeds -- **createSIWxRequestHook**: Validates and verifies SIWX proofs, grants access if wallet has paid +- **createSIWxRequestHook**: Validates and verifies SIWX proofs, grants access for auth-only routes or when the wallet has paid #### Manual Usage (Advanced) @@ -534,18 +542,15 @@ import { parseSIWxHeader, validateSIWxMessage, verifySIWxSignature, - SIGN_IN_WITH_X, } from '@x402/extensions/sign-in-with-x'; // 1. Declare in PaymentRequired response -const extensions = { - [SIGN_IN_WITH_X]: declareSIWxExtension({ - domain: 'api.example.com', - resourceUri: 'https://api.example.com/data', - network: 'eip155:8453', - statement: 'Sign in to access your purchased content', - }), -}; +const extensions = declareSIWxExtension({ + domain: 'api.example.com', + resourceUri: 'https://api.example.com/data', + network: 'eip155:8453', + statement: 'Sign in to access your purchased content', +}); // 2. Verify incoming proof async function handleRequest(request: Request) { @@ -571,10 +576,8 @@ async function handleRequest(request: Request) { } // verification.address is the verified wallet - // Check if this wallet has paid before - const hasPaid = await checkPaymentHistory(verification.address); - if (hasPaid) { - // Grant access without payment + if (await isAuthOnlyRoute(request) || await checkPaymentHistory(verification.address)) { + // Grant access } } ``` @@ -612,15 +615,15 @@ import { // 1. Get extension and network from 402 response const paymentRequired = await response.json(); const extension = paymentRequired.extensions['sign-in-with-x']; -const paymentNetwork = paymentRequired.accepts[0].network; // e.g., "eip155:8453" +const paymentNetwork = paymentRequired.accepts[0]?.network; // undefined for auth-only routes // 2. Find matching chain in supportedChains -const matchingChain = extension.supportedChains.find( - chain => chain.chainId === paymentNetwork -); +const matchingChain = paymentNetwork + ? extension.supportedChains.find(chain => chain.chainId === paymentNetwork) + : extension.supportedChains[0]; if (!matchingChain) { - // Payment network not supported for SIWX + // No chain supported by this signer / route combination throw new Error('Chain not supported'); } @@ -664,6 +667,8 @@ declareSIWxExtension({ - `resourceUri` β†’ from request URL - `domain` β†’ parsed from resourceUri +For auth-only routes declared with `accepts: []`, `network` cannot be inferred from payment requirements and should be provided explicitly. + **Multi-chain support:** When `network` is an array (or multiple networks in `accepts`), `supportedChains` will contain one entry per network. #### `parseSIWxHeader(header)` diff --git a/typescript/packages/extensions/src/sign-in-with-x/hooks.ts b/typescript/packages/extensions/src/sign-in-with-x/hooks.ts index 741b30f226..c416d2b31b 100644 --- a/typescript/packages/extensions/src/sign-in-with-x/hooks.ts +++ b/typescript/packages/extensions/src/sign-in-with-x/hooks.ts @@ -75,7 +75,11 @@ export function createSIWxSettleHook(options: CreateSIWxHookOptions) { } /** - * Creates an onProtectedRequest hook that validates SIWX auth before payment. + * Creates an onProtectedRequest hook that validates SIWX auth. + * + * For paid routes: grants access when the SIWX signature is valid and the address has paid. + * For auth-only routes (accepts: []): grants access on valid SIWX signature alone. + * Auth-only detection uses the routeConfig passed by x402HTTPResourceServer. * * @param options - Hook configuration * @returns Hook function for x402HTTPResourceServer.onProtectedRequest() @@ -99,10 +103,13 @@ export function createSIWxRequestHook(options: CreateSIWxHookOptions) { ); } - return async (context: { - adapter: { getHeader(name: string): string | undefined; getUrl(): string }; - path: string; - }): Promise => { + return async ( + context: { + adapter: { getHeader(name: string): string | undefined; getUrl(): string }; + path: string; + }, + routeConfig?: { accepts?: unknown }, + ): Promise => { // Try both cases for header (HTTP headers are case-insensitive) const header = context.adapter.getHeader(SIGN_IN_WITH_X) || @@ -134,8 +141,11 @@ export function createSIWxRequestHook(options: CreateSIWxHookOptions) { } } - const hasPaid = await storage.hasPaid(context.path, verification.address); - if (hasPaid) { + // Auth-only routes (accepts: []) grant access on valid SIWX alone + const isAuthOnly = Array.isArray(routeConfig?.accepts) && routeConfig.accepts.length === 0; + + const shouldGrant = isAuthOnly || (await storage.hasPaid(context.path, verification.address)); + if (shouldGrant) { // Record nonce as used before granting access if (storage.recordNonce) { await storage.recordNonce(payload.nonce); diff --git a/typescript/packages/extensions/src/sign-in-with-x/index.ts b/typescript/packages/extensions/src/sign-in-with-x/index.ts index 75dde2f561..1fe8b83241 100644 --- a/typescript/packages/extensions/src/sign-in-with-x/index.ts +++ b/typescript/packages/extensions/src/sign-in-with-x/index.ts @@ -5,65 +5,8 @@ * Allows clients to prove control of a wallet that may have previously paid * for a resource, enabling servers to grant access without requiring repurchase. * - * ## Server Usage - * - * ```typescript - * import { - * declareSIWxExtension, - * parseSIWxHeader, - * validateSIWxMessage, - * verifySIWxSignature, - * SIGN_IN_WITH_X, - * } from '@x402/extensions/sign-in-with-x'; - * - * // 1. Declare auth requirement in PaymentRequired response - * const extensions = declareSIWxExtension({ - * domain: 'api.example.com', - * resourceUri: 'https://api.example.com/data', - * network: 'eip155:8453', - * statement: 'Sign in to access your purchased content', - * }); - * - * // 2. Verify incoming proof - * const header = request.headers.get('SIGN-IN-WITH-X'); - * if (header) { - * const payload = parseSIWxHeader(header); - * - * const validation = await validateSIWxMessage( - * payload, - * 'https://api.example.com/data' - * ); - * - * if (validation.valid) { - * const verification = await verifySIWxSignature(payload); - * if (verification.valid) { - * // Authentication successful! - * // verification.address is the verified wallet - * } - * } - * } - * ``` - * - * ## Client Usage - * - * ```typescript - * import { - * createSIWxPayload, - * encodeSIWxHeader, - * } from '@x402/extensions/sign-in-with-x'; - * - * // 1. Get extension info from 402 response - * const serverInfo = paymentRequired.extensions['sign-in-with-x'].info; - * - * // 2. Create signed payload - * const payload = await createSIWxPayload(serverInfo, wallet); - * - * // 3. Encode for header - * const header = encodeSIWxHeader(payload); - * - * // 4. Send authenticated request - * fetch(url, { headers: { 'SIGN-IN-WITH-X': header } }); - * ``` + * Auth-only routes (accepts: []) are supported β€” the SIWX request hook + * grants access on a valid signature alone, no payment required. * * @module sign-in-with-x */ diff --git a/typescript/packages/extensions/test/sign-in-with-x.test.ts b/typescript/packages/extensions/test/sign-in-with-x.test.ts index 94284fe7a3..004b9c3a4c 100644 --- a/typescript/packages/extensions/test/sign-in-with-x.test.ts +++ b/typescript/packages/extensions/test/sign-in-with-x.test.ts @@ -31,27 +31,53 @@ import { type SolanaSigner, type EVMSigner, type EVMMessageVerifier, - type SIWxExtension, } from "../src/sign-in-with-x/index"; import { safeBase64Encode } from "@x402/core/utils"; import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"; import nacl from "tweetnacl"; import { randomBytes } from "crypto"; +import type { SIWxExtension } from "../src/sign-in-with-x/index"; /** - * Helper to generate fresh time-based fields for tests. - * In production, these are generated by enrichPaymentRequiredResponse. + * Test-only helper: builds a complete SIWX extension with nonce/issuedAt. * - * @param expirationSeconds - Optional expiration duration in seconds - * @returns Time-based fields for SIWX extension + * @param opts - Challenge configuration + * @param opts.domain - Server domain + * @param opts.resourceUri - Full resource URI + * @param opts.network - CAIP-2 network identifier(s) + * @param opts.statement - Human-readable signing statement + * @param opts.expirationSeconds - Challenge TTL in seconds + * @returns Extension object keyed by "sign-in-with-x" */ -function generateTimeBasedFields(expirationSeconds?: number) { - const nonce = randomBytes(16).toString("hex"); - const issuedAt = new Date().toISOString(); - const expirationTime = expirationSeconds - ? new Date(Date.now() + expirationSeconds * 1000).toISOString() - : undefined; - return { nonce, issuedAt, expirationTime }; +function createTestChallenge(opts: { + domain: string; + resourceUri: string; + network: string | string[]; + statement?: string; + expirationSeconds?: number; +}): Record { + const networks = Array.isArray(opts.network) ? opts.network : [opts.network]; + return { + "sign-in-with-x": { + info: { + domain: opts.domain, + uri: opts.resourceUri, + version: "1", + nonce: randomBytes(16).toString("hex"), + issuedAt: new Date().toISOString(), + ...(opts.expirationSeconds !== undefined && { + expirationTime: new Date(Date.now() + opts.expirationSeconds * 1000).toISOString(), + }), + ...(opts.statement && { statement: opts.statement }), + resources: [opts.resourceUri], + }, + supportedChains: networks.map(n => ({ + chainId: n, + type: n.startsWith("solana:") ? ("ed25519" as const) : ("eip191" as const), + })), + schema: { header: "sign-in-with-x", type: "object" }, + }, + }; } const validPayload = { @@ -134,7 +160,7 @@ describe("Sign-In-With-X Extension", () => { }); describe("declareSIWxExtension", () => { - it("should create extension with supportedChains array (without time-based fields)", () => { + it("should create static declaration without time-based fields", () => { const result = declareSIWxExtension({ domain: "api.example.com", resourceUri: "https://api.example.com/data", @@ -149,11 +175,10 @@ describe("Sign-In-With-X Extension", () => { expect(extension.info.uri).toBe("https://api.example.com/data"); expect(extension.schema).toBeDefined(); - // Time-based fields are NOT generated by declareSIWxExtension - // They are generated per-request by enrichPaymentRequiredResponse + // Time-based fields are NOT generated by declareSIWxExtension; + // they are generated per-request by enrichPaymentRequiredResponse expect(extension.info.nonce).toBeUndefined(); expect(extension.info.issuedAt).toBeUndefined(); - expect(extension.info.expirationTime).toBeUndefined(); // Check supportedChains array expect(extension.supportedChains).toHaveLength(1); @@ -179,8 +204,9 @@ describe("Sign-In-With-X Extension", () => { expect(extension.supportedChains[1].chainId).toBe(SOLANA_DEVNET); expect(extension.supportedChains[1].type).toBe("ed25519"); - // Time-based fields are NOT generated - only _options are stored + // Static declaration β€” no time-based fields expect(extension.info.nonce).toBeUndefined(); + expect(extension.info.issuedAt).toBeUndefined(); expect(extension._options.expirationSeconds).toBe(300); }); @@ -255,7 +281,7 @@ describe("Sign-In-With-X Extension", () => { it("should sign and verify a message with a real wallet", async () => { const account = privateKeyToAccount(generatePrivateKey()); - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: "eip155:8453", @@ -263,10 +289,8 @@ describe("Sign-In-With-X Extension", () => { }); const ext = extension["sign-in-with-x"]; - // Add time-based fields (in production, enrichPaymentRequiredResponse does this) const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -285,17 +309,15 @@ describe("Sign-In-With-X Extension", () => { it("should reject tampered signature", async () => { const account = privateKeyToAccount(generatePrivateKey()); - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: "eip155:8453", }); const ext = extension["sign-in-with-x"]; - // Add time-based fields (in production, enrichPaymentRequiredResponse does this) const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -305,6 +327,36 @@ describe("Sign-In-With-X Extension", () => { const verification = await verifySIWxSignature(payload); expect(verification.valid).toBe(false); }); + + it("should work for auth-only endpoints (no enrichment)", async () => { + const account = privateKeyToAccount(generatePrivateKey()); + const resourceUri = "https://api.example.com/resource"; + + const extensions = createTestChallenge({ + domain: "api.example.com", + resourceUri, + network: "eip155:8453", + statement: "Sign in to access", + expirationSeconds: 300, + }); + + const ext = extensions["sign-in-with-x"]; + const completeInfo = { + ...ext.info, + chainId: ext.supportedChains[0].chainId, + type: ext.supportedChains[0].type, + }; + const payload = await createSIWxPayload(completeInfo, account); + const header = encodeSIWxHeader(payload); + + const parsed = parseSIWxHeader(header); + const validation = await validateSIWxMessage(parsed, resourceUri); + expect(validation.valid).toBe(true); + + const result = await verifySIWxSignature(parsed); + expect(result.valid).toBe(true); + expect(result.address?.toLowerCase()).toBe(account.address.toLowerCase()); + }); }); describe("Smart wallet verification (evmVerifier option)", () => { @@ -312,7 +364,7 @@ describe("Sign-In-With-X Extension", () => { const mockVerifier: EVMMessageVerifier = vi.fn().mockResolvedValue(true); const account = privateKeyToAccount(generatePrivateKey()); - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: "eip155:8453", @@ -321,7 +373,6 @@ describe("Sign-In-With-X Extension", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -343,7 +394,7 @@ describe("Sign-In-With-X Extension", () => { it("should fallback to EOA verification when no verifier provided", async () => { const account = privateKeyToAccount(generatePrivateKey()); - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: "eip155:8453", @@ -352,7 +403,6 @@ describe("Sign-In-With-X Extension", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -368,7 +418,7 @@ describe("Sign-In-With-X Extension", () => { const mockVerifier: EVMMessageVerifier = vi.fn().mockResolvedValue(false); const account = privateKeyToAccount(generatePrivateKey()); - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: "eip155:8453", @@ -377,7 +427,6 @@ describe("Sign-In-With-X Extension", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -395,7 +444,7 @@ describe("Sign-In-With-X Extension", () => { const mockVerifier: EVMMessageVerifier = vi.fn().mockRejectedValue(new Error("RPC error")); const account = privateKeyToAccount(generatePrivateKey()); - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: "eip155:8453", @@ -404,7 +453,6 @@ describe("Sign-In-With-X Extension", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -428,7 +476,7 @@ describe("Sign-In-With-X Extension", () => { publicKey: address, }; - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: SOLANA_MAINNET, @@ -437,7 +485,6 @@ describe("Sign-In-With-X Extension", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -798,7 +845,7 @@ describe("Sign-In-With-X Extension", () => { publicKey: address, }; - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: SOLANA_MAINNET, @@ -808,7 +855,6 @@ describe("Sign-In-With-X Extension", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -834,7 +880,7 @@ describe("Sign-In-With-X Extension", () => { publicKey: { toBase58: () => address }, }; - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "api.example.com", resourceUri: "https://api.example.com/resource", network: SOLANA_DEVNET, @@ -843,7 +889,6 @@ describe("Sign-In-With-X Extension", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -1046,7 +1091,7 @@ describe("SIWX Hooks", () => { storage.recordPayment("/resource", account.address); // Create valid SIWX header - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "example.com", resourceUri: "http://example.com/resource", network: "eip155:8453", @@ -1054,7 +1099,6 @@ describe("SIWX Hooks", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -1080,7 +1124,7 @@ describe("SIWX Hooks", () => { // Don't pre-record payment - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "example.com", resourceUri: "http://example.com/resource", network: "eip155:8453", @@ -1088,7 +1132,6 @@ describe("SIWX Hooks", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -1201,7 +1244,7 @@ describe("SIWX Hooks", () => { storage.recordPayment("/resource", account.address); // Create valid SIWX header - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "example.com", resourceUri: "http://example.com/resource", network: "eip155:8453", @@ -1209,7 +1252,6 @@ describe("SIWX Hooks", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -1242,7 +1284,7 @@ describe("SIWX Hooks", () => { storage.recordPayment("/resource", account.address); // Create valid SIWX header - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "example.com", resourceUri: "http://example.com/resource", network: "eip155:8453", @@ -1250,7 +1292,6 @@ describe("SIWX Hooks", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -1282,7 +1323,7 @@ describe("SIWX Hooks", () => { storage.recordPayment("/resource", account.address); // Create valid SIWX header - const extension = declareSIWxExtension({ + const extension = createTestChallenge({ domain: "example.com", resourceUri: "http://example.com/resource", network: "eip155:8453", @@ -1290,7 +1331,6 @@ describe("SIWX Hooks", () => { const ext = extension["sign-in-with-x"]; const completeInfo = { ...ext.info, - ...generateTimeBasedFields(300), chainId: ext.supportedChains[0].chainId, type: ext.supportedChains[0].type, }; @@ -1322,6 +1362,127 @@ describe("SIWX Hooks", () => { expect(result2).toEqual({ grantAccess: true }); }); }); + + describe("auth-only routes (accepts: [])", () => { + it("should grant access with valid SIWX when accepts is empty array", async () => { + const storage = new InMemorySIWxStorage(); + const account = privateKeyToAccount(generatePrivateKey()); + + // Do NOT record any payment β€” auth-only should not require it + + const extension = createTestChallenge({ + domain: "example.com", + resourceUri: "http://example.com/profile", + network: "eip155:8453", + }); + const ext = extension["sign-in-with-x"]; + const completeInfo = { + ...ext.info, + chainId: ext.supportedChains[0].chainId, + type: ext.supportedChains[0].type, + }; + const payload = await createSIWxPayload(completeInfo, account); + const header = encodeSIWxHeader(payload); + + const hook = createSIWxRequestHook({ storage }); + const result = await hook( + { + adapter: { + getHeader: (name: string) => + name === "sign-in-with-x" || name === "SIGN-IN-WITH-X" ? header : undefined, + getUrl: () => "http://example.com/profile", + }, + path: "/profile", + }, + { accepts: [] }, + ); + + expect(result).toEqual({ grantAccess: true }); + }); + + it("should reject nonce replay on auth-only routes", async () => { + const base = new InMemorySIWxStorage(); + const usedNonces = new Set(); + const storage = { + ...base, + hasPaid: base.hasPaid.bind(base), + recordPayment: base.recordPayment.bind(base), + hasUsedNonce: (nonce: string) => usedNonces.has(nonce), + recordNonce: (nonce: string) => { + usedNonces.add(nonce); + }, + }; + + const account = privateKeyToAccount(generatePrivateKey()); + const events: SIWxHookEvent[] = []; + + const extension = createTestChallenge({ + domain: "example.com", + resourceUri: "http://example.com/profile", + network: "eip155:8453", + }); + const ext = extension["sign-in-with-x"]; + const completeInfo = { + ...ext.info, + chainId: ext.supportedChains[0].chainId, + type: ext.supportedChains[0].type, + }; + const payload = await createSIWxPayload(completeInfo, account); + const header = encodeSIWxHeader(payload); + + const hook = createSIWxRequestHook({ storage, onEvent: e => events.push(e) }); + const authOnlyRoute = { accepts: [] }; + const context = { + adapter: { + getHeader: (name: string) => + name === "sign-in-with-x" || name === "SIGN-IN-WITH-X" ? header : undefined, + getUrl: () => "http://example.com/profile", + }, + path: "/profile", + }; + + // First request should succeed + const result1 = await hook(context, authOnlyRoute); + expect(result1).toEqual({ grantAccess: true }); + + // Second request with same nonce should be rejected + const result2 = await hook(context, authOnlyRoute); + expect(result2).toBeUndefined(); + expect(events.some(e => e.type === "nonce_reused")).toBe(true); + }); + + it("should NOT grant access without routeConfig when address has not paid", async () => { + const storage = new InMemorySIWxStorage(); + const account = privateKeyToAccount(generatePrivateKey()); + + // No payment recorded, no routeConfig passed β€” should behave as before + const extension = createTestChallenge({ + domain: "example.com", + resourceUri: "http://example.com/resource", + network: "eip155:8453", + }); + const ext = extension["sign-in-with-x"]; + const completeInfo = { + ...ext.info, + chainId: ext.supportedChains[0].chainId, + type: ext.supportedChains[0].type, + }; + const payload = await createSIWxPayload(completeInfo, account); + const header = encodeSIWxHeader(payload); + + const hook = createSIWxRequestHook({ storage }); + const result = await hook({ + adapter: { + getHeader: (name: string) => + name === "sign-in-with-x" || name === "SIGN-IN-WITH-X" ? header : undefined, + getUrl: () => "http://example.com/resource", + }, + path: "/resource", + }); + + expect(result).toBeUndefined(); + }); + }); }); describe("createSIWxClientHook", () => { @@ -1340,29 +1501,16 @@ describe("SIWX Hooks", () => { const account = privateKeyToAccount(generatePrivateKey()); const hook = createSIWxClientHook(account); - const declaration = declareSIWxExtension({ + const challenge = createTestChallenge({ domain: "example.com", resourceUri: "http://example.com/resource", network: "eip155:1", }); - // Simulate what enrichPaymentRequiredResponse does: add time-based fields - const ext = declaration["sign-in-with-x"]; - const enrichedExtension = { - "sign-in-with-x": { - info: { - ...ext.info, - ...generateTimeBasedFields(300), - }, - supportedChains: ext.supportedChains, - schema: ext.schema, - }, - }; - const result = await hook({ paymentRequired: { accepts: [{ network: "eip155:1" }], - extensions: enrichedExtension, + extensions: challenge, }, }); @@ -1435,4 +1583,23 @@ describe("siwxResourceServerExtension", () => { expect(result.info.domain).toBe("api.example.com"); expect(result.info.uri).toBe("https://api.example.com/data"); }); + + it("should generate time-based fields from static declaration", async () => { + const declaration = declareSIWxExtension({ expirationSeconds: 300 }); + const ext = declaration["sign-in-with-x"]; + + // Static declaration has no nonce/issuedAt + expect(ext.info.nonce).toBeUndefined(); + expect(ext.info.issuedAt).toBeUndefined(); + + const result = (await siwxResourceServerExtension.enrichPaymentRequiredResponse!( + ext, + mockContext(["eip155:8453"]), + )) as SIWxExtension; + + // Enrichment generates fresh time-based fields + expect(result.info.nonce).toHaveLength(32); + expect(result.info.issuedAt).toBeDefined(); + expect(result.info.expirationTime).toBeDefined(); + }); }); From 26d651d842887d401495b6ce731d2786adc85ae9 Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 18:55:30 +0900 Subject: [PATCH 079/129] Document SIWX auth-only routes (#1653) * Update docs/extensions/sign-in-with-x.mdx Generated-By: mintlify-agent * Update docs/extensions/sign-in-with-x.mdx Generated-By: mintlify-agent * Update docs/extensions/sign-in-with-x.mdx Generated-By: mintlify-agent * Update docs/extensions/sign-in-with-x.mdx Generated-By: mintlify-agent * Update docs/extensions/sign-in-with-x.mdx Generated-By: mintlify-agent * Update docs/extensions/sign-in-with-x.mdx Generated-By: mintlify-agent --------- Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- docs/extensions/sign-in-with-x.mdx | 37 ++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/docs/extensions/sign-in-with-x.mdx b/docs/extensions/sign-in-with-x.mdx index 22257a775d..0344207164 100644 --- a/docs/extensions/sign-in-with-x.mdx +++ b/docs/extensions/sign-in-with-x.mdx @@ -7,10 +7,14 @@ The Sign-In-With-X (SIWX) extension implements [CAIP-122](https://chainagnostic. ## Overview -SIWX solves a key problem in x402: **repeat access to purchased content**. Without SIWX, clients must pay every time they request a resource. With SIWX: +SIWX solves two key problems in x402: -* **For Buyers**: Sign in with your wallet to access content you've already paid for -* **For Sellers**: Grant access to returning customers without requiring repayment +1. **Repeat access to purchased content**: Without SIWX, clients must pay every time they request a resource. With SIWX, sign in with your wallet to access content you've already paid for. +2. **Auth-only routes**: Protect resources with wallet authentication alone, without requiring payment. + +**Key Features:** +* **For Buyers**: Sign in with your wallet to access content you've already paid for, or authenticate to access wallet-gated resources +* **For Sellers**: Grant access to returning customers without requiring repayment, or create auth-only routes that require wallet signatures but no payment * **Chain-Agnostic**: Works with EVM (Ethereum, Base, etc.) and Solana wallets * **Standards-Based**: Built on CAIP-122, EIP-4361 (SIWE), and Sign-In-With-Solana @@ -19,7 +23,9 @@ SIWX solves a key problem in x402: **repeat access to purchased content**. Witho 1. **Server** returns 402 with `sign-in-with-x` extension containing challenge parameters 2. **Client** signs the CAIP-122 message with their wallet 3. **Client** sends signed proof in `SIGN-IN-WITH-X` HTTP header -4. **Server** verifies signature and grants access if wallet has previous payment +4. **Server** verifies signature and grants access either because: + - The route is auth-only (requires signature but no payment), or + - The wallet has previously paid for the resource This is a **Server ↔ Client** extension. The Facilitator is not involved in the authentication flow. @@ -73,11 +79,19 @@ The easiest way to implement SIWX is using the provided hooks, which handle all statement: 'Sign in to access your purchased content', }), }, + 'GET /profile': { + accepts: [], // Auth-only route: no payment required + extensions: declareSIWxExtension({ + network: NETWORK, // Required for auth-only routes (cannot be inferred from accepts) + statement: 'Sign in to view your profile', + expirationSeconds: 300, + }), + }, }; // 3. Verify incoming SIWX proofs const httpServer = new x402HTTPResourceServer(resourceServer, routes) - .onProtectedRequest(createSIWxRequestHook({ storage })); // Grants access if paid + .onProtectedRequest(createSIWxRequestHook({ storage })); // Grants access for auth-only or paid routes ``` @@ -85,7 +99,9 @@ The easiest way to implement SIWX is using the provided hooks, which handle all The hooks automatically: - **siwxResourceServerExtension**: Derives `network` from `accepts`, `domain`/`uri` from request URL, refreshes `nonce`/`issuedAt`/`expirationTime` per request - **createSIWxSettleHook**: Records payment when settlement succeeds -- **createSIWxRequestHook**: Validates and verifies SIWX proofs, grants access if wallet has paid +- **createSIWxRequestHook**: Validates and verifies SIWX proofs, grants access for auth-only routes (`accepts: []`) or when wallet has paid + +**Auth-only routes** (declared with `accepts: []`) grant access based on a valid SIWX signature alone, without requiring payment. This is useful for wallet-gated content that doesn't need micropayments. ### Smart Wallet Support (EIP-1271 / EIP-6492) @@ -166,10 +182,11 @@ For custom implementations, you can use the low-level functions directly: } // verification.address is the verified wallet - // Check if this wallet has paid before + // Grant access for auth-only routes or if wallet has paid + const isAuthOnly = await checkIfAuthOnlyRoute(request); const hasPaid = await checkPaymentHistory(verification.address); - if (hasPaid) { - // Grant access without payment + if (isAuthOnly || hasPaid) { + // Grant access } } ``` @@ -326,6 +343,8 @@ declareSIWxExtension({ }) ``` +**Note for auth-only routes:** When using `accepts: []`, the `network` parameter cannot be inferred from payment requirements and must be provided explicitly. + ### `parseSIWxHeader(header)` Parses a base64-encoded SIGN-IN-WITH-X header into a payload object. From 547f22a9cfab3a530cd0eb0f964f301e21634a7f Mon Sep 17 00:00:00 2001 From: Deesmo Date: Tue, 17 Mar 2026 15:45:35 -0400 Subject: [PATCH 080/129] Add Arch AI Tools to x402 ecosystem (#1541) --- .../partners-data/arch-ai-tools/metadata.json | 7 ++++ .../site/public/logos/arch-ai-tools.svg | 36 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/arch-ai-tools/metadata.json create mode 100644 typescript/site/public/logos/arch-ai-tools.svg diff --git a/typescript/site/app/ecosystem/partners-data/arch-ai-tools/metadata.json b/typescript/site/app/ecosystem/partners-data/arch-ai-tools/metadata.json new file mode 100644 index 0000000000..31e9a6bc1d --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/arch-ai-tools/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Arch AI Tools", + "category": "Services/Endpoints", + "logoUrl": "/logos/arch-ai-tools.svg", + "description": "53 AI-powered tools in a single MCP server β€” web search, image generation, crypto prices, fact-checking, research reports, domain analysis, and more. Pay per use in USDC on Base via x402. No accounts required. Works with Claude Desktop, Cursor, and any MCP client.", + "websiteUrl": "https://archtools.dev" +} diff --git a/typescript/site/public/logos/arch-ai-tools.svg b/typescript/site/public/logos/arch-ai-tools.svg new file mode 100644 index 0000000000..4f6ade165d --- /dev/null +++ b/typescript/site/public/logos/arch-ai-tools.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 26746f0b0b6771467a298401c2fd5e167ac965a9 Mon Sep 17 00:00:00 2001 From: Carson Roscoe Date: Tue, 17 Mar 2026 16:03:29 -0700 Subject: [PATCH 081/129] feat: improved working of adding new default assets (#1662) * feat: improved working of adding new default assets * nit: extraneous --- CONTRIBUTING.md | 12 +++++ go/mechanisms/evm/DEFAULT_ASSET.md | 52 +++++++++++++++---- go/mechanisms/evm/README.md | 8 +-- go/mechanisms/evm/constants.go | 5 +- typescript/packages/mechanisms/evm/README.md | 9 ++-- .../evm/src/exact/server/DEFAULT_ASSET.md | 17 ++++++ 6 files changed, 84 insertions(+), 19 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c17d67b53..683297dae1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -135,6 +135,18 @@ 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. +### Adding a Default Asset for an EVM Chain + +If your chain is EVM-compatible and you want to add a default stablecoin for +dollar-string pricing (`"$0.10"`), you don't need the full 3-PR workflow below. See: + +- [Go: DEFAULT_ASSET.md](go/mechanisms/evm/DEFAULT_ASSET.md) +- [TypeScript: DEFAULT_ASSET.md](typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md) + +These guides include a cross-SDK checklist of every file to update. + +### Adding a New Chain Family + ### PR 1: Specification Only Open a PR with specs for one payment scheme implementation. diff --git a/go/mechanisms/evm/DEFAULT_ASSET.md b/go/mechanisms/evm/DEFAULT_ASSET.md index d500045f30..5313a93c1b 100644 --- a/go/mechanisms/evm/DEFAULT_ASSET.md +++ b/go/mechanisms/evm/DEFAULT_ASSET.md @@ -13,7 +13,7 @@ To add support for a new EVM chain, add an entry to the `NetworkConfigs` map in ```go NetworkConfigs = map[string]NetworkConfig{ // ... existing chains ... - + // Your New Chain "eip155:YOUR_CHAIN_ID": { ChainID: big.NewInt(YOUR_CHAIN_ID), @@ -22,6 +22,8 @@ NetworkConfigs = map[string]NetworkConfig{ Name: "Token Name", // Must match EIP-712 domain name Version: "1", // Must match EIP-712 domain version Decimals: 6, // Token decimals (e.g. 6 for USDC) + // AssetTransferMethod: AssetTransferMethodPermit2, // Uncomment if token doesn't support EIP-3009 + // SupportsEip2612: true, // Set if permit2 token implements EIP-2612 permit() }, }, } @@ -36,12 +38,21 @@ NetworkConfigs = map[string]NetworkConfig{ | `Name` | EIP-712 domain name (must match the token's domain separator) | | `Version` | EIP-712 domain version (must match the token's domain separator) | | `Decimals` | Token decimal places (typically 6 for USDC) | +| `AssetTransferMethod` | *(Optional)* Transfer method override: set to `AssetTransferMethodPermit2` for tokens that don't support EIP-3009. Omit for EIP-3009 tokens (default behavior). | +| `SupportsEip2612` | *(Optional)* Set to `true` for Permit2 tokens that implement EIP-2612 `permit()`. When true, clients can use gasless EIP-2612 permits for Permit2 approval. When false/absent on a Permit2 token, clients fall back to ERC-20 approval gas sponsoring. Ignored for EIP-3009 tokens. | + +## Asset Transfer Methods + +x402 supports two methods for transferring assets: + +| Method | Use Case | Recommendation | +|--------|----------|----------------| +| **EIP-3009** | Tokens with native `transferWithAuthorization` (e.g., USDC) | **Recommended** (Simplest, truly gasless) | +| **Permit2** | Any ERC-20 token | **Universal Fallback** (Requires one-time approval) | -## Current Limitation +### Default Behavior -> ⚠️ **EIP-3009 Required**: Currently, only stablecoins implementing [EIP-3009](https://eips.ethereum.org/EIPS/eip-3009) (`transferWithAuthorization`) are supported. -> -> Generic ERC-20 support via EIP-2612/Permit2 is planned but not yet implemented. +If no `AssetTransferMethod` is specified, the system defaults to **EIP-3009**. This maintains backward compatibility with existing deployments. ## Asset Selection Policy @@ -52,7 +63,6 @@ The default asset is chosen **per chain** based on the following guidelines: 2. **No official stance**: If the chain team has not taken a public position on a preferred stablecoin, we encourage the team behind that chain to make the selection and submit a PR. 3. **Community PRs welcome**: Chain teams and community members may submit PRs to add their chain's default asset, provided: - - The stablecoin implements EIP-3009 - The selection aligns with the chain's ecosystem preferences - The EIP-712 domain parameters are correctly specified @@ -60,7 +70,29 @@ The default asset is chosen **per chain** based on the following guidelines: To add a new chain's default asset: -1. Verify the stablecoin implements EIP-3009 -2. Obtain the correct EIP-712 domain `name` and `version` from the token contract -3. Add the entry to `NetworkConfigs` in `constants.go` -4. Submit a PR with the chain name and rationale for the asset selection +1. Obtain the correct EIP-712 domain `name` and `version` from the token contract +2. Check whether the token supports EIP-3009 (`transferWithAuthorization`): + - If yes: omit `AssetTransferMethod` (EIP-3009 is the default) + - If no: set `AssetTransferMethod: AssetTransferMethodPermit2` +3. For Permit2 tokens, check whether the token supports EIP-2612 (`permit()`): + - If yes: set `SupportsEip2612: true` so clients can use gasless EIP-2612 permits for Permit2 approval + - If no: omit `SupportsEip2612` β€” clients will fall back to ERC-20 approval gas sponsoring +4. Add the entry to `NetworkConfigs` in `constants.go` +5. Submit a PR with the chain name and rationale for the asset selection + +## Cross-SDK Checklist + +When adding a new chain's default asset, update all three SDKs to maintain parity: + +| SDK | File to edit | What to add | +|-----|-------------|-------------| +| **Go** | `go/mechanisms/evm/constants.go` | Entry in `NetworkConfigs` map | +| **TypeScript** | `typescript/packages/mechanisms/evm/src/exact/server/scheme.ts` | Entry in `stablecoins` map inside `getDefaultAsset()` | +| **Python** | `python/x402/mechanisms/evm/constants.py` | Entry in `NETWORK_CONFIGS` dict | + +All three must use: +- The same CAIP-2 network key (e.g., `eip155:YOUR_CHAIN_ID`) +- The same token contract address +- The same EIP-712 domain `name` and `version` +- The same `decimals` value +- The same asset transfer method (EIP-3009 default, or Permit2 if specified) diff --git a/go/mechanisms/evm/README.md b/go/mechanisms/evm/README.md index b290ec8761..1b0f180e3f 100644 --- a/go/mechanisms/evm/README.md +++ b/go/mechanisms/evm/README.md @@ -8,7 +8,7 @@ This package provides scheme implementations for EVM-based blockchains (Ethereum ## Exact Payment Scheme -The **exact** scheme implementation enables fixed-amount payments using EIP-3009 `transferWithAuthorization` for USDC and compatible tokens. +The **exact** scheme implementation enables fixed-amount payments using EIP-3009 `transferWithAuthorization` or Permit2 for USDC and compatible tokens. ### Export Paths @@ -65,6 +65,8 @@ Networks with default assets configured: - **Base Mainnet**: `eip155:8453` (USDC) - **Base Sepolia**: `eip155:84532` (USDC) +- **MegaETH Mainnet**: `eip155:4326` (MegaUSD) +- **Monad Mainnet**: `eip155:143` (USDC) To add default asset support for additional chains, see [DEFAULT_ASSET.md](./DEFAULT_ASSET.md). @@ -72,8 +74,8 @@ To add default asset support for additional chains, see [DEFAULT_ASSET.md](./DEF The **exact** scheme implements fixed-amount payments: -- **Standard**: EIP-3009 `transferWithAuthorization` -- **Token**: USDC and EIP-3009 compatible tokens +- **Standard**: EIP-3009 `transferWithAuthorization` or Permit2 (per-asset configuration) +- **Token**: USDC and other stablecoins (EIP-3009 or any ERC-20 via Permit2) - **Gas**: Paid by facilitator - **Confirmation**: On-chain settlement with transaction hash diff --git a/go/mechanisms/evm/constants.go b/go/mechanisms/evm/constants.go index cf65a3c57b..28c60472c0 100644 --- a/go/mechanisms/evm/constants.go +++ b/go/mechanisms/evm/constants.go @@ -80,8 +80,9 @@ var ( // - If the chain has officially endorsed a stablecoin, that asset should be used // - If no official stance exists, the chain team should make the selection // - // NOTE: Currently only EIP-3009 supporting stablecoins can be used. - // Generic ERC-20 support via EIP-2612/Permit2 is planned but not yet implemented. + // Both EIP-3009 (transferWithAuthorization) and Permit2 asset transfer methods are supported. + // EIP-3009 is the default. Set AssetTransferMethod to AssetTransferMethodPermit2 for tokens + // that don't support EIP-3009. See DEFAULT_ASSET.md for details. NetworkConfigs = map[string]NetworkConfig{ // Base Mainnet "eip155:8453": { diff --git a/typescript/packages/mechanisms/evm/README.md b/typescript/packages/mechanisms/evm/README.md index 429c0e475e..9c6ea6b3a8 100644 --- a/typescript/packages/mechanisms/evm/README.md +++ b/typescript/packages/mechanisms/evm/README.md @@ -178,10 +178,11 @@ See `NETWORKS` constant in `@x402/evm/v1` ## Asset Support -Supports any ERC-3009 compatible token: -- USDC (primary) -- EURC -- Any token implementing `transferWithAuthorization()` +Supports two asset transfer methods: +- **EIP-3009**: Tokens with native `transferWithAuthorization()` (e.g., USDC, EURC) β€” simplest, truly gasless +- **Permit2**: Any ERC-20 token β€” universal fallback, requires one-time approval + +See [DEFAULT_ASSET.md](src/exact/server/DEFAULT_ASSET.md) for the current list of configured chains and how to add new ones. ## Development diff --git a/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md b/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md index e85fff8f39..7c03ba892d 100644 --- a/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md +++ b/typescript/packages/mechanisms/evm/src/exact/server/DEFAULT_ASSET.md @@ -144,3 +144,20 @@ To add a new chain's default asset: 4. Add the entry to `getDefaultAsset()` in `scheme.ts` 5. Submit a PR with the chain name and rationale for the asset selection +## Cross-SDK Checklist + +When adding a new chain's default asset, update all three SDKs to maintain parity: + +| SDK | File to edit | What to add | +|-----|-------------|-------------| +| **Go** | `go/mechanisms/evm/constants.go` | Entry in `NetworkConfigs` map | +| **TypeScript** | `typescript/packages/mechanisms/evm/src/exact/server/scheme.ts` | Entry in `stablecoins` map inside `getDefaultAsset()` | +| **Python** | `python/x402/mechanisms/evm/constants.py` | Entry in `NETWORK_CONFIGS` dict | + +All three must use: +- The same CAIP-2 network key (e.g., `eip155:YOUR_CHAIN_ID`) +- The same token contract address +- The same EIP-712 domain `name` and `version` +- The same `decimals` value +- The same asset transfer method (EIP-3009 default, or Permit2 if specified) + From 6a90fe93c57fe20104f175149747ed399d491192 Mon Sep 17 00:00:00 2001 From: Marcelo Salloum dos Santos Date: Tue, 17 Mar 2026 18:01:30 -0700 Subject: [PATCH 082/129] feat: add `Built on Stellar` facilitator listing (#1660) * feat: add Built on Stellar facilitator to x402 ecosystem listing * Update website URL --- .../built-on-stellar/metadata.json | 19 ++++++++++++++++++ .../site/public/logos/built-on-stellar.png | Bin 0 -> 6541 bytes 2 files changed, 19 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/built-on-stellar/metadata.json create mode 100644 typescript/site/public/logos/built-on-stellar.png diff --git a/typescript/site/app/ecosystem/partners-data/built-on-stellar/metadata.json b/typescript/site/app/ecosystem/partners-data/built-on-stellar/metadata.json new file mode 100644 index 0000000000..4c0aeb1dbb --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/built-on-stellar/metadata.json @@ -0,0 +1,19 @@ +{ + "name": "Built on Stellar", + "description": "Free, public x402 facilitator for Stellar with ~5-second finality and sponsored fees. Full verification and settlement flow powered by the OpenZeppelin Relayer.", + "logoUrl": "/logos/built-on-stellar.png", + "websiteUrl": "https://developers.stellar.org/docs/build/apps/x402/built-on-stellar", + "category": "Facilitators", + "facilitator": { + "baseUrl": "https://channels.openzeppelin.com/x402", + "networks": ["stellar:pubnet", "stellar:testnet"], + "schemes": ["exact"], + "assets": ["SEP-41"], + "supports": { + "verify": true, + "settle": true, + "supported": true, + "list": false + } + } +} diff --git a/typescript/site/public/logos/built-on-stellar.png b/typescript/site/public/logos/built-on-stellar.png new file mode 100644 index 0000000000000000000000000000000000000000..b8edf3b70f002b09cffe3cc40ea9543c332cb3fa GIT binary patch literal 6541 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 N@l%dZzCZhqe*yRJ?YjT~ literal 0 HcmV?d00001 From ff1bc506606a0c9beef1c074ed96206ac7962eca Mon Sep 17 00:00:00 2001 From: Misha Kolesnik Date: Wed, 18 Mar 2026 22:55:07 +0000 Subject: [PATCH 083/129] feat(spec): document Memo instruction and seller-defined memo for SVM scheme (#1682) The SVM exact scheme spec was out of date with the implementation (PR #1048 added Memo instruction support without updating the spec). This change: - Updates instruction layout from 3-5 to 3-6 instructions - Documents SPL Memo as an allowed optional program alongside Lighthouse - Adds optional extra.memo field for seller-defined memo content - Specifies client and facilitator behavior for memo verification The extra.memo field enables sellers to attach payment references (e.g., invoice IDs) to on-chain transactions, allowing payment reconciliation on a single payTo address without requiring unique deposit addresses (ATAs) per payment. --- specs/schemes/exact/scheme_exact_svm.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/specs/schemes/exact/scheme_exact_svm.md b/specs/schemes/exact/scheme_exact_svm.md index f2537d60d7..d22402b859 100644 --- a/specs/schemes/exact/scheme_exact_svm.md +++ b/specs/schemes/exact/scheme_exact_svm.md @@ -40,13 +40,15 @@ In addition to the standard x402 `PaymentRequirements` fields, the `exact` schem "payTo": "2wKupLR9q6wXYppw8Gr2NvWxKBUqm4PPJKkQfoxHDBg4", "maxTimeoutSeconds": 60, "extra": { - "feePayer": "EwWqGE4ZFKLofuestmU4LDdK7XM1N4ALgdZccwYugwGd" + "feePayer": "EwWqGE4ZFKLofuestmU4LDdK7XM1N4ALgdZccwYugwGd", + "memo": "pi_3abc123def456" } } ``` - `asset`: The public key of the token mint. - `extra.feePayer`: The public key of the account that will pay for the transaction fees. This is typically the facilitator's public key. +- `extra.memo` (optional): A seller-defined UTF-8 string to include in the transaction's Memo instruction. When present, the client MUST use this value as the Memo instruction data instead of a random nonce. Maximum 256 bytes. This enables sellers to attach payment references (e.g., invoice IDs) to on-chain transactions for reconciliation without requiring unique deposit addresses. ## PaymentPayload `payload` Field @@ -78,7 +80,8 @@ Full `PaymentPayload` object: "payTo": "2wKupLR9q6wXYppw8Gr2NvWxKBUqm4PPJKkQfoxHDBg4", "maxTimeoutSeconds": 60, "extra": { - "feePayer": "EwWqGE4ZFKLofuestmU4LDdK7XM1N4ALgdZccwYugwGd" + "feePayer": "EwWqGE4ZFKLofuestmU4LDdK7XM1N4ALgdZccwYugwGd", + "memo": "pi_3abc123def456" } }, "payload": { @@ -106,16 +109,18 @@ A facilitator verifying an `exact`-scheme SVM payment MUST enforce all of the fo 1. Instruction layout -- The decompiled transaction MUST contain 3 to 5 instructions in this order: +- The decompiled transaction MUST contain 3 to 6 instructions in this order: 1. Compute Budget: Set Compute Unit Limit 2. Compute Budget: Set Compute Unit Price 3. SPL Token or Token-2022 TransferChecked - 4. (Optional) Lighthouse program instruction (Phantom wallet protection) - 5. (Optional) Lighthouse program instruction (Solflare wallet protection) - -- If a 4th or 5th instruction is present, the program MUST be the Lighthouse program (`L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95`). -- Phantom wallet injects 1 Lighthouse instruction; Solflare injects 2. -- These Lighthouse instructions are wallet-injected user protection mechanisms and MUST be allowed to support these wallets. + 4. (Optional) Lighthouse or Memo program instruction + 5. (Optional) Lighthouse or Memo program instruction + 6. (Optional) Memo program instruction + +- Allowed optional programs: Lighthouse (`L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95`) and SPL Memo (`MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr`). +- Phantom wallet injects 1 Lighthouse instruction; Solflare injects 2. These are wallet-injected user protection mechanisms and MUST be allowed. +- The Memo instruction ensures transaction uniqueness across concurrent payments with identical parameters. Clients MUST include a Memo instruction containing either the value of `extra.memo` (when present) or a random nonce (at least 16 bytes, hex-encoded for UTF-8 compliance). +- If `extra.memo` is present in `PaymentRequirements`, the facilitator MUST verify that exactly one Memo instruction exists and that its data matches the value of `extra.memo` encoded as UTF-8. 2. Fee payer (facilitator) safety From b874b13e20d3fe2b76343aec98b208c8a5215afe Mon Sep 17 00:00:00 2001 From: Ethan Oroshiba Date: Wed, 18 Mar 2026 18:57:11 -0500 Subject: [PATCH 084/129] chore(site): add latest partners and remove endpoints category (#1681) * add latest partners * Remove duplicate and failed logo download artifacts Only keep the logos actually referenced in partner metadata. Made-with: Cursor * reinstate endpoint category --- .../partners-data/alchemy/metadata.json | 7 ++++ .../ecosystem/partners-data/aws/metadata.json | 7 ++++ .../partners-data/messari/metadata.json | 7 ++++ .../partners-data/nansen/metadata.json | 7 ++++ .../partners-data/stripe/metadata.json | 7 ++++ .../partners-data/world/metadata.json | 7 ++++ typescript/site/public/logos/alchemy.png | Bin 0 -> 43668 bytes typescript/site/public/logos/aws.svg | 38 ++++++++++++++++++ typescript/site/public/logos/messari.png | Bin 0 -> 6364 bytes typescript/site/public/logos/nansen-logo.png | Bin 0 -> 7673 bytes typescript/site/public/logos/stripe.svg | 3 ++ typescript/site/public/logos/world.png | Bin 0 -> 14484 bytes 12 files changed, 83 insertions(+) create mode 100644 typescript/site/app/ecosystem/partners-data/alchemy/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/aws/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/messari/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/nansen/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/stripe/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/world/metadata.json create mode 100644 typescript/site/public/logos/alchemy.png create mode 100644 typescript/site/public/logos/aws.svg create mode 100644 typescript/site/public/logos/messari.png create mode 100644 typescript/site/public/logos/nansen-logo.png create mode 100644 typescript/site/public/logos/stripe.svg create mode 100644 typescript/site/public/logos/world.png diff --git a/typescript/site/app/ecosystem/partners-data/alchemy/metadata.json b/typescript/site/app/ecosystem/partners-data/alchemy/metadata.json new file mode 100644 index 0000000000..b42855e87a --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/alchemy/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Alchemy", + "description": "Alchemy integrates x402 to enable monetized access to their blockchain developer platform, allowing AI agents and applications to pay for RPC calls and web3 APIs using stablecoins.", + "logoUrl": "/logos/alchemy.png", + "websiteUrl": "https://www.alchemy.com", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/app/ecosystem/partners-data/aws/metadata.json b/typescript/site/app/ecosystem/partners-data/aws/metadata.json new file mode 100644 index 0000000000..9ac0eef970 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/aws/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "AWS", + "description": "Amazon Web Services supports x402 for machine-to-machine payments in the cloud, enabling AI agents and services to transact seamlessly using the HTTP 402 payment protocol.", + "logoUrl": "/logos/aws.svg", + "websiteUrl": "https://aws.amazon.com", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/app/ecosystem/partners-data/messari/metadata.json b/typescript/site/app/ecosystem/partners-data/messari/metadata.json new file mode 100644 index 0000000000..c021c7b495 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/messari/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Messari", + "description": "Messari leverages x402 to gate access to their professional-grade crypto intelligence and research APIs, enabling pay-per-use access to on-chain data and market analytics.", + "logoUrl": "/logos/messari.png", + "websiteUrl": "https://messari.io", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/app/ecosystem/partners-data/nansen/metadata.json b/typescript/site/app/ecosystem/partners-data/nansen/metadata.json new file mode 100644 index 0000000000..9c33b8d97c --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/nansen/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Nansen", + "description": "Nansen uses x402 to monetize access to their blockchain analytics platform, enabling AI agents and developers to pay for on-chain intelligence and wallet analytics using stablecoins.", + "logoUrl": "/logos/nansen-logo.png", + "websiteUrl": "https://nansen.ai", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/app/ecosystem/partners-data/stripe/metadata.json b/typescript/site/app/ecosystem/partners-data/stripe/metadata.json new file mode 100644 index 0000000000..0fe0af7473 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/stripe/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Stripe", + "description": "Stripe has integrated x402 to enable stablecoin payments for internet commerce, allowing businesses to accept USDC payments natively via the HTTP 402 standard.", + "logoUrl": "/logos/stripe.svg", + "websiteUrl": "https://stripe.com", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/app/ecosystem/partners-data/world/metadata.json b/typescript/site/app/ecosystem/partners-data/world/metadata.json new file mode 100644 index 0000000000..e2a0402fa0 --- /dev/null +++ b/typescript/site/app/ecosystem/partners-data/world/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "World", + "description": "World (formerly Worldcoin) integrates x402 to enable verified human identity in payment flows, combining World ID with the HTTP 402 payment protocol for secure, human-verified transactions.", + "logoUrl": "/logos/world.png", + "websiteUrl": "https://world.org", + "category": "Infrastructure & Tooling" +} diff --git a/typescript/site/public/logos/alchemy.png b/typescript/site/public/logos/alchemy.png new file mode 100644 index 0000000000000000000000000000000000000000..7d5e52b169eb49fc2943db9cbd7e795e98253495 GIT binary patch literal 43668 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 + + + + + + + + + + + diff --git a/typescript/site/public/logos/messari.png b/typescript/site/public/logos/messari.png new file mode 100644 index 0000000000000000000000000000000000000000..ea1fddbbc94462a7a7d34773b205e8ab15cd6c90 GIT binary patch literal 6364 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 literal 0 HcmV?d00001 diff --git a/typescript/site/public/logos/nansen-logo.png b/typescript/site/public/logos/nansen-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c10a272fc5b77487190e3f0c7b8ff720d087f7a1 GIT binary patch literal 7673 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 literal 0 HcmV?d00001 diff --git a/typescript/site/public/logos/stripe.svg b/typescript/site/public/logos/stripe.svg new file mode 100644 index 0000000000..e1fd0e126d --- /dev/null +++ b/typescript/site/public/logos/stripe.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/typescript/site/public/logos/world.png b/typescript/site/public/logos/world.png new file mode 100644 index 0000000000000000000000000000000000000000..4154f617d5028ba6b45340883f317576c01a8e93 GIT binary patch literal 14484 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 Date: Wed, 18 Mar 2026 16:57:46 -0700 Subject: [PATCH 085/129] fix: permit2 e2e typescript servers (#1685) --- e2e/servers/hono/index.ts | 2 ++ e2e/servers/next/proxy.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/e2e/servers/hono/index.ts b/e2e/servers/hono/index.ts index bf8434d56f..97372423da 100644 --- a/e2e/servers/hono/index.ts +++ b/e2e/servers/hono/index.ts @@ -208,6 +208,8 @@ app.use( asset: EVM_PERMIT2_ASSET, extra: { assetTransferMethod: "permit2", + name: EVM_NETWORK == "eip155:84532" ? "USDC" : "USD Coin", + version: "2", }, }, }, diff --git a/e2e/servers/next/proxy.ts b/e2e/servers/next/proxy.ts index ab34be83c8..7df95db525 100644 --- a/e2e/servers/next/proxy.ts +++ b/e2e/servers/next/proxy.ts @@ -169,6 +169,8 @@ export const proxy = paymentProxy( asset: EVM_PERMIT2_ASSET, extra: { assetTransferMethod: "permit2", + name: EVM_NETWORK == "eip155:84532" ? "USDC" : "USD Coin", + version: "2", }, }, }, From c2de525a79c5fe55328b766eef332fc484b34a0f Mon Sep 17 00:00:00 2001 From: Carson Roscoe Date: Wed, 18 Mar 2026 16:58:18 -0700 Subject: [PATCH 086/129] fix: Solana spec links (#1683) --- docs/core-concepts/client-server.md | 2 +- docs/core-concepts/facilitator.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core-concepts/client-server.md b/docs/core-concepts/client-server.md index ecb76c4434..83c3478a13 100644 --- a/docs/core-concepts/client-server.md +++ b/docs/core-concepts/client-server.md @@ -59,7 +59,7 @@ To mitigate this, servers that settle Solana payments themselves **must** mainta 3. If the key is not present, insert it into the cache and proceed with settlement. 4. Evict entries older than 120 seconds (approximately twice the Solana blockhash lifetime). -If you are using a facilitator, the x402 SVM libraries already include built-in duplicate settlement protection via a `SettlementCache`. See the [Exact SVM Scheme Specification](/specs/schemes/exact/scheme_exact_svm#duplicate-settlement-mitigation-recommended) for full details. +If you are using a facilitator, the x402 SVM libraries already include built-in duplicate settlement protection via a `SettlementCache`. See the [Exact SVM Scheme Specification](https://github.com/coinbase/x402/blob/main/specs/schemes/exact/scheme_exact_svm.md) for full details. ### Communication Flow diff --git a/docs/core-concepts/facilitator.md b/docs/core-concepts/facilitator.md index 0d9a537569..4c96cba36f 100644 --- a/docs/core-concepts/facilitator.md +++ b/docs/core-concepts/facilitator.md @@ -59,7 +59,7 @@ To mitigate this, the x402 SVM mechanism packages include a built-in `Settlement This protection is enabled by default when using the standard SVM facilitator registration helpers in TypeScript and Python. In Go, a shared `SettlementCache` instance should be passed to both V1 and V2 SVM facilitator schemes during registration. -**If you are a merchant settling payments directly (without a facilitator), you must implement equivalent duplicate detection yourself.** See the [Exact SVM Scheme Specification](/specs/schemes/exact/scheme_exact_svm#duplicate-settlement-mitigation-recommended) for the full specification. +**If you are a merchant settling payments directly (without a facilitator), you must implement equivalent duplicate detection yourself.** See the [Exact SVM Scheme Specification](https://github.com/coinbase/x402/blob/main/specs/schemes/exact/scheme_exact_svm.md) for the full specification. ### Summary From 7b7e163c1560fc0f3c731cf2c45b915e6979b94a Mon Sep 17 00:00:00 2001 From: Carson Roscoe Date: Thu, 19 Mar 2026 11:17:34 -0700 Subject: [PATCH 087/129] feat: python permit2 and gas sponsorship extensions (#1686) * feat: implement permit2 in python * feat: added eip2612 gas sponsoring extension * feat: added erc20 approval gas sponsoring extension * feat: added permit2 to exact evm with gas sponsorship support * feat: updated unit/integration tests * feat: updated e2e clients * feat: updated e2e servers * feat: updated e2e facilitator * feat: added changelog fragment * feat: updated specs * fix: format/lint * fix: format * feat: pr feedback --- e2e/clients/httpx/build.sh | 6 +- e2e/clients/httpx/main.py | 13 +- e2e/clients/httpx/run.sh | 3 +- e2e/clients/httpx/test.config.json | 11 +- e2e/clients/requests/build.sh | 6 +- e2e/clients/requests/main.py | 8 +- e2e/clients/requests/run.sh | 3 +- e2e/clients/requests/test.config.json | 11 +- e2e/facilitators/python/build.sh | 6 +- e2e/facilitators/python/main.py | 70 +- e2e/facilitators/python/run.sh | 2 +- e2e/facilitators/python/test.config.json | 7 +- e2e/servers/fastapi/build.sh | 6 +- e2e/servers/fastapi/main.py | 83 +- e2e/servers/fastapi/run.sh | 3 +- e2e/servers/fastapi/test.config.json | 32 +- e2e/servers/flask/build.sh | 6 +- e2e/servers/flask/main.py | 86 ++ e2e/servers/flask/run.sh | 3 +- e2e/servers/flask/test.config.json | 26 +- python/x402/changelog.d/689.feature.md | 1 + python/x402/client_base.py | 20 +- .../eip2612_gas_sponsoring/__init__.py | 19 + .../eip2612_gas_sponsoring/client.py | 86 ++ .../eip2612_gas_sponsoring/facilitator.py | 86 ++ .../eip2612_gas_sponsoring/schema.py | 58 ++ .../eip2612_gas_sponsoring/server.py | 27 + .../eip2612_gas_sponsoring/types.py | 56 ++ .../erc20_approval_gas_sponsoring/__init__.py | 29 + .../erc20_approval_gas_sponsoring/client.py | 87 ++ .../facilitator.py | 154 ++++ .../erc20_approval_gas_sponsoring/schema.py | 46 ++ .../erc20_approval_gas_sponsoring/server.py | 28 + .../erc20_approval_gas_sponsoring/types.py | 105 +++ python/x402/mechanisms/evm/__init__.py | 3 +- python/x402/mechanisms/evm/constants.py | 179 +++++ python/x402/mechanisms/evm/exact/client.py | 157 +++- .../x402/mechanisms/evm/exact/facilitator.py | 12 +- .../mechanisms/evm/exact/permit2_utils.py | 740 ++++++++++++++++++ python/x402/mechanisms/evm/signer.py | 58 +- python/x402/mechanisms/evm/signers.py | 169 +++- python/x402/mechanisms/evm/types.py | 117 +++ python/x402/mechanisms/evm/utils.py | 12 + python/x402/tests/unit/extensions/__init__.py | 1 - .../extensions/test_eip2612_gas_sponsoring.py | 143 ++++ .../test_erc20_approval_gas_sponsoring.py | 111 +++ .../tests/unit/mechanisms/evm/test_permit2.py | 609 ++++++++++++++ specs/extensions/eip2612_gas_sponsoring.md | 9 +- specs/extensions/erc20_gas_sponsoring.md | 9 +- specs/schemes/exact/scheme_exact_evm.md | 36 +- 50 files changed, 3419 insertions(+), 139 deletions(-) create mode 100644 python/x402/changelog.d/689.feature.md create mode 100644 python/x402/extensions/eip2612_gas_sponsoring/__init__.py create mode 100644 python/x402/extensions/eip2612_gas_sponsoring/client.py create mode 100644 python/x402/extensions/eip2612_gas_sponsoring/facilitator.py create mode 100644 python/x402/extensions/eip2612_gas_sponsoring/schema.py create mode 100644 python/x402/extensions/eip2612_gas_sponsoring/server.py create mode 100644 python/x402/extensions/eip2612_gas_sponsoring/types.py create mode 100644 python/x402/extensions/erc20_approval_gas_sponsoring/__init__.py create mode 100644 python/x402/extensions/erc20_approval_gas_sponsoring/client.py create mode 100644 python/x402/extensions/erc20_approval_gas_sponsoring/facilitator.py create mode 100644 python/x402/extensions/erc20_approval_gas_sponsoring/schema.py create mode 100644 python/x402/extensions/erc20_approval_gas_sponsoring/server.py create mode 100644 python/x402/extensions/erc20_approval_gas_sponsoring/types.py create mode 100644 python/x402/mechanisms/evm/exact/permit2_utils.py create mode 100644 python/x402/tests/unit/extensions/test_eip2612_gas_sponsoring.py create mode 100644 python/x402/tests/unit/extensions/test_erc20_approval_gas_sponsoring.py create mode 100644 python/x402/tests/unit/mechanisms/evm/test_permit2.py diff --git a/e2e/clients/httpx/build.sh b/e2e/clients/httpx/build.sh index f5fbe5e8f8..c1bb071bbe 100755 --- a/e2e/clients/httpx/build.sh +++ b/e2e/clients/httpx/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Python doesn't require a build step -# This file is intentionally empty -exit 0 +set -e +# Rebuild the local x402 editable dependency so the venv reflects source changes +uv sync --reinstall-package x402 diff --git a/e2e/clients/httpx/main.py b/e2e/clients/httpx/main.py index fdf976316a..424f0530ae 100644 --- a/e2e/clients/httpx/main.py +++ b/e2e/clients/httpx/main.py @@ -1,16 +1,20 @@ """httpx e2e test client using x402 v2 SDK.""" +import logging import os import json import asyncio from dotenv import load_dotenv from eth_account import Account -# Import from new x402 package +logging.basicConfig(level=logging.INFO, format="%(name)s %(levelname)s: %(message)s", stream=__import__('sys').stderr) +logging.getLogger("x402.signers").setLevel(logging.DEBUG) +logging.getLogger("x402.permit2").setLevel(logging.DEBUG) + from x402 import x402Client from x402.http import decode_payment_response_header from x402.http.clients import x402_httpx_transport -from x402.mechanisms.evm import EthAccountSigner +from x402.mechanisms.evm import EthAccountSignerWithRPC from x402.mechanisms.evm.exact import register_exact_evm_client from x402.mechanisms.svm import KeypairSigner from x402.mechanisms.svm.exact import register_exact_svm_client @@ -22,6 +26,7 @@ # Get environment variables evm_private_key = os.getenv("EVM_PRIVATE_KEY") svm_private_key = os.getenv("SVM_PRIVATE_KEY") +evm_rpc_url = os.getenv("EVM_RPC_URL", "https://sepolia.base.org") base_url = os.getenv("RESOURCE_SERVER_URL") endpoint_path = os.getenv("ENDPOINT_PATH") @@ -45,8 +50,8 @@ async def main(): # Register EVM exact scheme if private key is available if evm_private_key: - account = Account.from_key(evm_private_key) - evm_signer = EthAccountSigner(account) + evm_account = Account.from_key(evm_private_key) + evm_signer = EthAccountSignerWithRPC(evm_account, rpc_url=evm_rpc_url) register_exact_evm_client(client, evm_signer) # Register SVM exact scheme if private key is available diff --git a/e2e/clients/httpx/run.sh b/e2e/clients/httpx/run.sh index 31c1f93486..c653d856a9 100755 --- a/e2e/clients/httpx/run.sh +++ b/e2e/clients/httpx/run.sh @@ -1,4 +1,3 @@ #!/bin/bash -# Ensure dependencies are synced before running -uv sync --quiet +uv sync --reinstall-package x402 --quiet uv run python main.py diff --git a/e2e/clients/httpx/test.config.json b/e2e/clients/httpx/test.config.json index fcdeb61f96..26fecdf809 100644 --- a/e2e/clients/httpx/test.config.json +++ b/e2e/clients/httpx/test.config.json @@ -11,8 +11,12 @@ 2 ], "evm": { - "transferMethods": ["eip3009"] + "transferMethods": ["eip3009", "permit2"] }, + "extensions": [ + "eip2612GasSponsoring", + "erc20ApprovalGasSponsoring" + ], "description": "Python httpx client with x402 v2 payment hooks", "environment": { "required": [ @@ -21,7 +25,8 @@ ], "optional": [ "EVM_PRIVATE_KEY", - "SVM_PRIVATE_KEY" + "SVM_PRIVATE_KEY", + "EVM_RPC_URL" ] } -} \ No newline at end of file +} diff --git a/e2e/clients/requests/build.sh b/e2e/clients/requests/build.sh index f5fbe5e8f8..c1bb071bbe 100755 --- a/e2e/clients/requests/build.sh +++ b/e2e/clients/requests/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Python doesn't require a build step -# This file is intentionally empty -exit 0 +set -e +# Rebuild the local x402 editable dependency so the venv reflects source changes +uv sync --reinstall-package x402 diff --git a/e2e/clients/requests/main.py b/e2e/clients/requests/main.py index e1bcef0b6b..c5eb3b291d 100644 --- a/e2e/clients/requests/main.py +++ b/e2e/clients/requests/main.py @@ -5,11 +5,10 @@ from dotenv import load_dotenv from eth_account import Account -# Import from new x402 package (sync variant for requests) from x402 import x402ClientSync from x402.http import decode_payment_response_header from x402.http.clients import x402_requests -from x402.mechanisms.evm import EthAccountSigner +from x402.mechanisms.evm import EthAccountSignerWithRPC from x402.mechanisms.evm.exact import register_exact_evm_client from x402.mechanisms.svm import KeypairSigner from x402.mechanisms.svm.exact import register_exact_svm_client @@ -20,6 +19,7 @@ # Get environment variables evm_private_key = os.getenv("EVM_PRIVATE_KEY") svm_private_key = os.getenv("SVM_PRIVATE_KEY") +evm_rpc_url = os.getenv("EVM_RPC_URL", "https://sepolia.base.org") base_url = os.getenv("RESOURCE_SERVER_URL") endpoint_path = os.getenv("ENDPOINT_PATH") @@ -43,8 +43,8 @@ def main(): # Register EVM exact scheme if private key is available if evm_private_key: - account = Account.from_key(evm_private_key) - evm_signer = EthAccountSigner(account) + evm_account = Account.from_key(evm_private_key) + evm_signer = EthAccountSignerWithRPC(evm_account, rpc_url=evm_rpc_url) register_exact_evm_client(client, evm_signer) # Register SVM exact scheme if private key is available diff --git a/e2e/clients/requests/run.sh b/e2e/clients/requests/run.sh index 31c1f93486..c653d856a9 100644 --- a/e2e/clients/requests/run.sh +++ b/e2e/clients/requests/run.sh @@ -1,4 +1,3 @@ #!/bin/bash -# Ensure dependencies are synced before running -uv sync --quiet +uv sync --reinstall-package x402 --quiet uv run python main.py diff --git a/e2e/clients/requests/test.config.json b/e2e/clients/requests/test.config.json index 009e3eb0d1..783ba8467f 100644 --- a/e2e/clients/requests/test.config.json +++ b/e2e/clients/requests/test.config.json @@ -11,8 +11,12 @@ 2 ], "evm": { - "transferMethods": ["eip3009"] + "transferMethods": ["eip3009", "permit2"] }, + "extensions": [ + "eip2612GasSponsoring", + "erc20ApprovalGasSponsoring" + ], "description": "Python requests client with x402 v2 HTTP adapter", "environment": { "required": [ @@ -21,7 +25,8 @@ ], "optional": [ "EVM_PRIVATE_KEY", - "SVM_PRIVATE_KEY" + "SVM_PRIVATE_KEY", + "EVM_RPC_URL" ] } -} \ No newline at end of file +} diff --git a/e2e/facilitators/python/build.sh b/e2e/facilitators/python/build.sh index 9889f505ad..c1bb071bbe 100755 --- a/e2e/facilitators/python/build.sh +++ b/e2e/facilitators/python/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Python build - no compilation needed -# This file exists for consistency with the e2e setup process -exit 0 +set -e +# Rebuild the local x402 editable dependency so the venv reflects source changes +uv sync --reinstall-package x402 diff --git a/e2e/facilitators/python/main.py b/e2e/facilitators/python/main.py index 9160860027..658d931c4b 100644 --- a/e2e/facilitators/python/main.py +++ b/e2e/facilitators/python/main.py @@ -7,15 +7,22 @@ - EVM networks (Base Sepolia) via web3.py - SVM networks (Solana Devnet) via solders - Bazaar discovery extension for resource cataloging +- EIP-2612 gas sponsoring extension (gasless Permit2 approval via permit) +- ERC-20 approval gas sponsoring extension (gasless Permit2 via signed tx relay) - V1 and V2 protocol versions Run with: uv run uvicorn main:app --port 4022 """ +import logging import os import sys from typing import Any +logging.basicConfig(level=logging.INFO, format="%(name)s %(levelname)s: %(message)s") +logging.getLogger("x402.permit2").setLevel(logging.DEBUG) +logging.getLogger("x402.signers").setLevel(logging.DEBUG) + from dotenv import load_dotenv from fastapi import FastAPI, HTTPException from pydantic import BaseModel @@ -23,8 +30,15 @@ from x402 import x402Facilitator from x402.extensions.bazaar import extract_discovery_info +from x402.extensions.eip2612_gas_sponsoring import EIP2612_GAS_SPONSORING +from x402.extensions.erc20_approval_gas_sponsoring import ( + Erc20ApprovalFacilitatorExtension, + WriteContractCall, +) from x402.mechanisms.evm import FacilitatorWeb3Signer +from x402.mechanisms.evm.constants import TX_STATUS_SUCCESS from x402.mechanisms.evm.exact import register_exact_evm_facilitator +from x402.mechanisms.evm.types import TransactionReceipt from x402.mechanisms.svm import FacilitatorKeypairSigner from x402.mechanisms.svm.exact import register_exact_svm_facilitator @@ -62,6 +76,47 @@ print(f"SVM Facilitator account: {svm_signer.get_addresses()[0]}") +class Erc20ApprovalSigner: + """Wraps FacilitatorWeb3Signer with send_transactions for ERC-20 approval sponsoring. + + Broadcasts pre-signed approval txs and settles via the proxy contract, + matching the Go/TS facilitator pattern. + """ + + def __init__(self, base_signer: FacilitatorWeb3Signer): + self._signer = base_signer + + def send_transactions(self, transactions: list) -> list[str]: + hashes: list[str] = [] + for tx in transactions: + if isinstance(tx, str): + tx_hash = self._signer._w3.eth.send_raw_transaction( + bytes.fromhex(tx[2:] if tx.startswith("0x") else tx) + ).hex() + elif isinstance(tx, dict) or isinstance(tx, WriteContractCall): + if isinstance(tx, dict): + call = WriteContractCall(**tx) + else: + call = tx + tx_hash = self._signer.write_contract( + call.address, call.abi, call.function, *call.args + ) + else: + raise ValueError(f"Unsupported transaction type: {type(tx)}") + + receipt = self._signer.wait_for_transaction_receipt(tx_hash) + if receipt.status != TX_STATUS_SUCCESS: + raise RuntimeError(f"transaction_failed: {tx_hash}") + hashes.append(tx_hash) + return hashes + + def wait_for_transaction_receipt(self, tx_hash: str) -> TransactionReceipt: + return self._signer.wait_for_transaction_receipt(tx_hash) + + +erc20_approval_signer = Erc20ApprovalSigner(evm_signer) + + def _handle_after_verify(ctx: Any) -> None: """Handle after verify hook - extract discovery info and catalog.""" print("βœ… Payment verified") @@ -129,6 +184,12 @@ def _handle_after_verify(ctx: Any) -> None: networks="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", # Devnet ) +# Register gas sponsoring extensions +facilitator.register_extension(EIP2612_GAS_SPONSORING) +facilitator.register_extension( + Erc20ApprovalFacilitatorExtension(signer=erc20_approval_signer) +) + # Pydantic models for request/response class VerifyRequest(BaseModel): @@ -179,13 +240,18 @@ async def verify(request: VerifyRequest): # - Extract and catalog discovery info (on_after_verify) response = await facilitator.verify(payload, requirements) + if not response.is_valid: + print(f" ❌ Verify rejected: {response.invalid_reason} (payer={response.payer})") + return { "isValid": response.is_valid, "payer": response.payer, "invalidReason": response.invalid_reason, } except Exception as e: + import traceback print(f"Verify error: {e}") + traceback.print_exc() raise HTTPException(status_code=500, detail=str(e)) @@ -292,7 +358,7 @@ async def health(): "network": "eip155:84532", "facilitator": "python", "version": "2.0.0", - "extensions": ["bazaar"], + "extensions": facilitator.get_extensions(), "discoveredResources": bazaar_catalog.get_count(), } @@ -322,7 +388,7 @@ async def shutdown(): β•‘ Server: http://localhost:{PORT} β•‘ β•‘ Network: eip155:84532 β•‘ β•‘ Address: {evm_signer.get_addresses()[0]} β•‘ -β•‘ Extensions: bazaar β•‘ +β•‘ Extensions: bazaar, eip2612, erc20approval β•‘ β•‘ β•‘ β•‘ Endpoints: β•‘ β•‘ β€’ POST /verify (verify payment) β•‘ diff --git a/e2e/facilitators/python/run.sh b/e2e/facilitators/python/run.sh index d3a07c0c9e..c653d856a9 100755 --- a/e2e/facilitators/python/run.sh +++ b/e2e/facilitators/python/run.sh @@ -1,3 +1,3 @@ #!/bin/bash +uv sync --reinstall-package x402 --quiet uv run python main.py - diff --git a/e2e/facilitators/python/test.config.json b/e2e/facilitators/python/test.config.json index 11ced9d07d..ab0ea28eb9 100644 --- a/e2e/facilitators/python/test.config.json +++ b/e2e/facilitators/python/test.config.json @@ -11,10 +11,12 @@ 2 ], "extensions": [ - "bazaar" + "bazaar", + "eip2612GasSponsoring", + "erc20ApprovalGasSponsoring" ], "evm": { - "transferMethods": ["eip3009"] + "transferMethods": ["eip3009", "permit2"] }, "environment": { "required": [ @@ -29,4 +31,3 @@ ] } } - diff --git a/e2e/servers/fastapi/build.sh b/e2e/servers/fastapi/build.sh index f5fbe5e8f8..c1bb071bbe 100755 --- a/e2e/servers/fastapi/build.sh +++ b/e2e/servers/fastapi/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Python doesn't require a build step -# This file is intentionally empty -exit 0 +set -e +# Rebuild the local x402 editable dependency so the venv reflects source changes +uv sync --reinstall-package x402 diff --git a/e2e/servers/fastapi/main.py b/e2e/servers/fastapi/main.py index 1d582a8823..edee26386a 100644 --- a/e2e/servers/fastapi/main.py +++ b/e2e/servers/fastapi/main.py @@ -22,6 +22,10 @@ declare_discovery_extension, OutputConfig, ) +from x402.extensions.eip2612_gas_sponsoring import declare_eip2612_gas_sponsoring_extension +from x402.extensions.erc20_approval_gas_sponsoring import ( + declare_erc20_approval_gas_sponsoring_extension, +) # Load environment variables load_dotenv() @@ -31,6 +35,9 @@ SVM_ADDRESS = os.getenv("SVM_PAYEE_ADDRESS") PORT = int(os.getenv("PORT", "4021")) FACILITATOR_URL = os.getenv("FACILITATOR_URL") +EVM_PERMIT2_ASSET = os.getenv( + "EVM_PERMIT2_ASSET", "0x036CbD53842c5426634e7929541eC2318f3dCF7e" +) if not EVM_ADDRESS: print("Error: Missing required environment variable EVM_PAYEE_ADDRESS") @@ -92,18 +99,18 @@ ), }, }, - "GET /protected-2": { + "GET /protected-svm": { "accepts": { "scheme": "exact", - "payTo": EVM_ADDRESS, - "price": "$0.001", # 0.001 USDC - "network": EVM_NETWORK, + "payTo": SVM_ADDRESS, + "price": "$0.001", + "network": SVM_NETWORK, }, "extensions": { **declare_discovery_extension( output=OutputConfig( example={ - "message": "Access granted to protected resource #2", + "message": "Access granted to SVM protected resource", "timestamp": "2024-01-01T00:00:00Z", }, schema={ @@ -117,29 +124,55 @@ ), }, }, - "GET /protected-svm": { + "GET /protected-permit2": { "accepts": { "scheme": "exact", - "payTo": SVM_ADDRESS, - "price": "$0.001", - "network": SVM_NETWORK, + "payTo": EVM_ADDRESS, + "network": EVM_NETWORK, + "price": { + "amount": "1000", + "asset": EVM_PERMIT2_ASSET, + "extra": { + "assetTransferMethod": "permit2", + "name": "USDC", + "version": "2", + }, + }, }, "extensions": { **declare_discovery_extension( output=OutputConfig( example={ - "message": "Access granted to SVM protected resource", + "message": "Permit2 endpoint accessed successfully", "timestamp": "2024-01-01T00:00:00Z", + "method": "permit2", }, schema={ "properties": { "message": {"type": "string"}, "timestamp": {"type": "string"}, + "method": {"type": "string"}, }, "required": ["message", "timestamp"], }, ) ), + **declare_eip2612_gas_sponsoring_extension(), + }, + }, + "GET /protected-permit2-erc20": { + "accepts": { + "scheme": "exact", + "payTo": EVM_ADDRESS, + "network": EVM_NETWORK, + "price": { + "amount": "1000", + "asset": EVM_PERMIT2_ASSET, + "extra": {"assetTransferMethod": "permit2"}, + }, + }, + "extensions": { + **declare_erc20_approval_gas_sponsoring_extension(), }, }, } @@ -167,27 +200,41 @@ async def protected_endpoint() -> Dict[str, Any]: } -@app.get("/protected-2") -async def protected_endpoint_2() -> Dict[str, Any]: - """Protected endpoint that requires ERC20 payment.""" +@app.get("/protected-svm") +async def protected_svm_endpoint() -> Dict[str, Any]: + """Protected endpoint that requires SVM (Solana) payment.""" if shutdown_requested: raise HTTPException(status_code=503, detail="Server shutting down") return { - "message": "Access granted to protected resource #2", + "message": "Access granted to SVM protected resource", "timestamp": "2024-01-01T00:00:00Z", } -@app.get("/protected-svm") -async def protected_svm_endpoint() -> Dict[str, Any]: - """Protected endpoint that requires SVM (Solana) payment.""" +@app.get("/protected-permit2") +async def protected_permit2_endpoint() -> Dict[str, Any]: + """Protected endpoint that requires Permit2 payment.""" if shutdown_requested: raise HTTPException(status_code=503, detail="Server shutting down") return { - "message": "Access granted to SVM protected resource", + "message": "Permit2 endpoint accessed successfully", + "timestamp": "2024-01-01T00:00:00Z", + "method": "permit2", + } + + +@app.get("/protected-permit2-erc20") +async def protected_permit2_erc20_endpoint() -> Dict[str, Any]: + """Protected endpoint that requires Permit2 payment with ERC-20 approval sponsoring.""" + if shutdown_requested: + raise HTTPException(status_code=503, detail="Server shutting down") + + return { + "message": "Permit2+ERC20Approval endpoint accessed successfully", "timestamp": "2024-01-01T00:00:00Z", + "method": "permit2+erc20approval", } diff --git a/e2e/servers/fastapi/run.sh b/e2e/servers/fastapi/run.sh index 31c1f93486..c653d856a9 100644 --- a/e2e/servers/fastapi/run.sh +++ b/e2e/servers/fastapi/run.sh @@ -1,4 +1,3 @@ #!/bin/bash -# Ensure dependencies are synced before running -uv sync --quiet +uv sync --reinstall-package x402 --quiet uv run python main.py diff --git a/e2e/servers/fastapi/test.config.json b/e2e/servers/fastapi/test.config.json index 6a532a64f7..f6ab6032aa 100644 --- a/e2e/servers/fastapi/test.config.json +++ b/e2e/servers/fastapi/test.config.json @@ -4,32 +4,43 @@ "language": "python", "x402Version": 2, "extensions": [ - "bazaar" + "bazaar", + "eip2612GasSponsoring", + "erc20ApprovalGasSponsoring" ], "description": "Python FastAPI server with x402 v2 payment middleware", "endpoints": [ { "path": "/protected", "method": "GET", - "description": "Protected endpoint requiring payment", + "description": "Protected endpoint requiring EIP-3009 payment", "requiresPayment": true, "protocolFamily": "evm", "transferMethod": "eip3009" }, { - "path": "/protected-2", + "path": "/protected-svm", + "method": "GET", + "description": "Protected endpoint requiring SVM (Solana) payment", + "requiresPayment": true, + "protocolFamily": "svm" + }, + { + "path": "/protected-permit2", "method": "GET", - "description": "Protected endpoint requiring ERC20 payment", + "description": "Protected endpoint requiring Permit2 payment", "requiresPayment": true, "protocolFamily": "evm", - "transferMethod": "eip3009" + "transferMethod": "permit2" }, { - "path": "/protected-svm", + "path": "/protected-permit2-erc20", "method": "GET", - "description": "Protected endpoint requiring SVM (Solana) payment", + "description": "Protected endpoint requiring Permit2 payment with ERC-20 approval gas sponsoring", "requiresPayment": true, - "protocolFamily": "svm" + "protocolFamily": "evm", + "transferMethod": "permit2", + "extensions": ["erc20ApprovalGasSponsoring"] }, { "path": "/health", @@ -51,7 +62,8 @@ ], "optional": [ "PORT", - "FACILITATOR_URL" + "FACILITATOR_URL", + "EVM_PERMIT2_ASSET" ] } -} \ No newline at end of file +} diff --git a/e2e/servers/flask/build.sh b/e2e/servers/flask/build.sh index f5fbe5e8f8..c1bb071bbe 100755 --- a/e2e/servers/flask/build.sh +++ b/e2e/servers/flask/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Python doesn't require a build step -# This file is intentionally empty -exit 0 +set -e +# Rebuild the local x402 editable dependency so the venv reflects source changes +uv sync --reinstall-package x402 diff --git a/e2e/servers/flask/main.py b/e2e/servers/flask/main.py index 09b1b99dc7..ea0557cca1 100644 --- a/e2e/servers/flask/main.py +++ b/e2e/servers/flask/main.py @@ -19,6 +19,10 @@ declare_discovery_extension, OutputConfig, ) +from x402.extensions.eip2612_gas_sponsoring import declare_eip2612_gas_sponsoring_extension +from x402.extensions.erc20_approval_gas_sponsoring import ( + declare_erc20_approval_gas_sponsoring_extension, +) # Configure logging to reduce verbosity logging.getLogger("werkzeug").setLevel(logging.ERROR) @@ -32,6 +36,9 @@ SVM_ADDRESS = os.getenv("SVM_PAYEE_ADDRESS") PORT = int(os.getenv("PORT", "4021")) FACILITATOR_URL = os.getenv("FACILITATOR_URL") +EVM_PERMIT2_ASSET = os.getenv( + "EVM_PERMIT2_ASSET", "0x036CbD53842c5426634e7929541eC2318f3dCF7e" +) if not EVM_ADDRESS: print("Error: Missing required environment variable EVM_PAYEE_ADDRESS") @@ -120,6 +127,57 @@ ), }, }, + "GET /protected-permit2": { + "accepts": { + "scheme": "exact", + "payTo": EVM_ADDRESS, + "network": EVM_NETWORK, + "price": { + "amount": "1000", + "asset": EVM_PERMIT2_ASSET, + "extra": { + "assetTransferMethod": "permit2", + "name": "USDC", + "version": "2", + }, + }, + }, + "extensions": { + **declare_discovery_extension( + output=OutputConfig( + example={ + "message": "Permit2 endpoint accessed successfully", + "timestamp": "2024-01-01T00:00:00Z", + "method": "permit2", + }, + schema={ + "properties": { + "message": {"type": "string"}, + "timestamp": {"type": "string"}, + "method": {"type": "string"}, + }, + "required": ["message", "timestamp"], + }, + ) + ), + **declare_eip2612_gas_sponsoring_extension(), + }, + }, + "GET /protected-permit2-erc20": { + "accepts": { + "scheme": "exact", + "payTo": EVM_ADDRESS, + "network": EVM_NETWORK, + "price": { + "amount": "1000", + "asset": EVM_PERMIT2_ASSET, + "extra": {"assetTransferMethod": "permit2"}, + }, + }, + "extensions": { + **declare_erc20_approval_gas_sponsoring_extension(), + }, + }, } # Apply payment middleware @@ -158,6 +216,34 @@ def protected_svm_endpoint(): ) +@app.route("/protected-permit2") +def protected_permit2_endpoint(): + """Protected endpoint that requires Permit2 payment.""" + if shutdown_requested: + return jsonify({"error": "Server shutting down"}), 503 + return jsonify( + { + "message": "Permit2 endpoint accessed successfully", + "timestamp": "2024-01-01T00:00:00Z", + "method": "permit2", + } + ) + + +@app.route("/protected-permit2-erc20") +def protected_permit2_erc20_endpoint(): + """Protected endpoint that requires Permit2 payment with ERC-20 approval sponsoring.""" + if shutdown_requested: + return jsonify({"error": "Server shutting down"}), 503 + return jsonify( + { + "message": "Permit2+ERC20Approval endpoint accessed successfully", + "timestamp": "2024-01-01T00:00:00Z", + "method": "permit2+erc20approval", + } + ) + + @app.route("/health") def health_check(): """Health check endpoint.""" diff --git a/e2e/servers/flask/run.sh b/e2e/servers/flask/run.sh index 31c1f93486..c653d856a9 100644 --- a/e2e/servers/flask/run.sh +++ b/e2e/servers/flask/run.sh @@ -1,4 +1,3 @@ #!/bin/bash -# Ensure dependencies are synced before running -uv sync --quiet +uv sync --reinstall-package x402 --quiet uv run python main.py diff --git a/e2e/servers/flask/test.config.json b/e2e/servers/flask/test.config.json index 4c73225cf1..629667ee76 100644 --- a/e2e/servers/flask/test.config.json +++ b/e2e/servers/flask/test.config.json @@ -4,14 +4,16 @@ "language": "python", "x402Version": 2, "extensions": [ - "bazaar" + "bazaar", + "eip2612GasSponsoring", + "erc20ApprovalGasSponsoring" ], "description": "Python Flask server with x402 v2 payment middleware", "endpoints": [ { "path": "/protected", "method": "GET", - "description": "Protected endpoint requiring payment", + "description": "Protected endpoint requiring EIP-3009 payment", "requiresPayment": true, "protocolFamily": "evm", "transferMethod": "eip3009" @@ -23,6 +25,23 @@ "requiresPayment": true, "protocolFamily": "svm" }, + { + "path": "/protected-permit2", + "method": "GET", + "description": "Protected endpoint requiring Permit2 payment", + "requiresPayment": true, + "protocolFamily": "evm", + "transferMethod": "permit2" + }, + { + "path": "/protected-permit2-erc20", + "method": "GET", + "description": "Protected endpoint requiring Permit2 payment with ERC-20 approval gas sponsoring", + "requiresPayment": true, + "protocolFamily": "evm", + "transferMethod": "permit2", + "extensions": ["erc20ApprovalGasSponsoring"] + }, { "path": "/health", "method": "GET", @@ -43,7 +62,8 @@ ], "optional": [ "PORT", - "FACILITATOR_URL" + "FACILITATOR_URL", + "EVM_PERMIT2_ASSET" ] } } diff --git a/python/x402/changelog.d/689.feature.md b/python/x402/changelog.d/689.feature.md new file mode 100644 index 0000000000..c86366560c --- /dev/null +++ b/python/x402/changelog.d/689.feature.md @@ -0,0 +1 @@ +Added Permit2 support to the Python SDK exact EVM mechanism with full TS/Go parity. The client routes to Permit2 (`PermitWitnessTransferFrom`) when `assetTransferMethod == "permit2"` in payment requirements extra, and the facilitator verifies and settles via the `x402ExactPermit2Proxy` contract. Includes `eip2612GasSponsoring` and `erc20ApprovalGasSponsoring` extension support for gasless Permit2 approval flows, universal signature verification via `signer.verify_typed_data` (EOA + EIP-1271 + ERC-6492), and `settleWithPermit` settlement path. Added E2E `/protected-permit2`, `/protected-permit2-eip2612`, and `/protected-permit2-erc20` endpoints to Flask server, and updated httpx client for cross-language Permit2 testing. diff --git a/python/x402/client_base.py b/python/x402/client_base.py index 4bc6ed7c8e..aa5dbbf7e0 100644 --- a/python/x402/client_base.py +++ b/python/x402/client_base.py @@ -5,6 +5,7 @@ from __future__ import annotations +import inspect from collections.abc import Awaitable, Callable, Generator from dataclasses import dataclass, field from typing import Any, Literal @@ -303,8 +304,21 @@ def _create_payment_payload_v2_core( client = schemes[selected.scheme] - # 5. Create inner payload - inner_payload = client.create_payment_payload(selected) + # 5. Create inner payload (pass extensions for enrichment if scheme supports it) + server_extensions = payment_required.extensions + sig = inspect.signature(client.create_payment_payload) + if "extensions" in sig.parameters: + inner_payload = client.create_payment_payload( + selected, extensions=server_extensions + ) + else: + inner_payload = client.create_payment_payload(selected) + + # 5b. Extract scheme-generated extensions (e.g. gas sponsoring) + scheme_extensions = inner_payload.pop("__extensions", None) + final_extensions = extensions or payment_required.extensions or {} + if scheme_extensions: + final_extensions = {**final_extensions, **scheme_extensions} # 6. Wrap into full PaymentPayload payload = PaymentPayload( @@ -312,7 +326,7 @@ def _create_payment_payload_v2_core( payload=inner_payload, accepted=selected, resource=resource or payment_required.resource, - extensions=extensions or payment_required.extensions, + extensions=final_extensions or None, ) # 7. Execute after hooks diff --git a/python/x402/extensions/eip2612_gas_sponsoring/__init__.py b/python/x402/extensions/eip2612_gas_sponsoring/__init__.py new file mode 100644 index 0000000000..3d9ee1e2f7 --- /dev/null +++ b/python/x402/extensions/eip2612_gas_sponsoring/__init__.py @@ -0,0 +1,19 @@ +"""EIP-2612 Gas Sponsoring Extension for x402 Permit2 flows.""" + +from .facilitator import ( + extract_eip2612_gas_sponsoring_info, + validate_eip2612_gas_sponsoring_info, + validate_eip2612_permit_for_payment, +) +from .server import declare_eip2612_gas_sponsoring_extension +from .types import EIP2612_GAS_SPONSORING, EIP2612_GAS_SPONSORING_KEY, Eip2612GasSponsoringInfo + +__all__ = [ + "EIP2612_GAS_SPONSORING", + "EIP2612_GAS_SPONSORING_KEY", + "Eip2612GasSponsoringInfo", + "declare_eip2612_gas_sponsoring_extension", + "extract_eip2612_gas_sponsoring_info", + "validate_eip2612_gas_sponsoring_info", + "validate_eip2612_permit_for_payment", +] diff --git a/python/x402/extensions/eip2612_gas_sponsoring/client.py b/python/x402/extensions/eip2612_gas_sponsoring/client.py new file mode 100644 index 0000000000..bc68716dee --- /dev/null +++ b/python/x402/extensions/eip2612_gas_sponsoring/client.py @@ -0,0 +1,86 @@ +"""Client-side EIP-2612 permit signing for Permit2 approval sponsoring.""" + +from __future__ import annotations + +from typing import Any + +from ...mechanisms.evm.constants import ( + EIP2612_NONCES_ABI, + EIP2612_PERMIT_TYPES, + PERMIT2_ADDRESS, +) +from ...mechanisms.evm.types import TypedDataField +from .types import Eip2612GasSponsoringInfo + + +def sign_eip2612_permit( + signer: Any, + token_address: str, + token_name: str, + token_version: str, + chain_id: int, + deadline: str, + amount: str, +) -> Eip2612GasSponsoringInfo: + """Sign an EIP-2612 permit authorizing Permit2 to spend tokens. + + The signer must implement read_contract (to query nonces) and + sign_typed_data. + + Args: + signer: Client signer with read_contract and sign_typed_data. + token_address: ERC-20 token contract address. + token_name: Token name for EIP-712 domain. + token_version: Token version for EIP-712 domain. + chain_id: Chain ID. + deadline: Deadline timestamp as decimal string. + amount: Amount to approve as decimal string. + + Returns: + Eip2612GasSponsoringInfo ready to attach to payload extensions. + """ + nonce = signer.read_contract( + token_address, + EIP2612_NONCES_ABI, + "nonces", + signer.address, + ) + + domain_dict: dict[str, Any] = { + "name": token_name, + "version": token_version, + "chainId": chain_id, + "verifyingContract": token_address, + } + + message = { + "owner": signer.address, + "spender": PERMIT2_ADDRESS, + "value": int(amount), + "nonce": int(nonce), + "deadline": int(deadline), + } + + typed_fields: dict[str, list[TypedDataField]] = { + type_name: [TypedDataField(name=f["name"], type=f["type"]) for f in fields] + for type_name, fields in EIP2612_PERMIT_TYPES.items() + } + + sig_bytes = signer.sign_typed_data( + domain_dict, + typed_fields, + "Permit", + message, + ) + signature = "0x" + sig_bytes.hex() + + return Eip2612GasSponsoringInfo( + from_address=signer.address, + asset=token_address, + spender=PERMIT2_ADDRESS, + amount=amount, + nonce=str(int(nonce)), + deadline=deadline, + signature=signature, + version="1", + ) diff --git a/python/x402/extensions/eip2612_gas_sponsoring/facilitator.py b/python/x402/extensions/eip2612_gas_sponsoring/facilitator.py new file mode 100644 index 0000000000..e99356142d --- /dev/null +++ b/python/x402/extensions/eip2612_gas_sponsoring/facilitator.py @@ -0,0 +1,86 @@ +"""Facilitator-side extraction and validation for EIP-2612 Gas Sponsoring.""" + +from __future__ import annotations + +import re +import time + +from ...mechanisms.evm.constants import PERMIT2_ADDRESS, PERMIT2_DEADLINE_BUFFER +from ...schemas import PaymentPayload +from .types import EIP2612_GAS_SPONSORING_KEY, Eip2612GasSponsoringInfo + +_HEX_ADDRESS = re.compile(r"^0x[a-fA-F0-9]{40}$") +_DECIMAL_STRING = re.compile(r"^[0-9]+$") +_HEX_STRING = re.compile(r"^0x[a-fA-F0-9]+$") +_VERSION_STRING = re.compile(r"^[0-9]+(\.[0-9]+)*$") + + +def extract_eip2612_gas_sponsoring_info( + payload: PaymentPayload, +) -> Eip2612GasSponsoringInfo | None: + """Extract EIP-2612 gas sponsoring info from a payment payload. + + Returns None if the extension is not present or malformed. + """ + extensions = payload.extensions + if not extensions: + return None + + ext_data = extensions.get(EIP2612_GAS_SPONSORING_KEY) + if not isinstance(ext_data, dict): + return None + + info = ext_data.get("info") + if not isinstance(info, dict): + return None + + required = ["from", "asset", "spender", "amount", "nonce", "deadline", "signature"] + if not all(isinstance(info.get(k), str) for k in required): + return None + + return Eip2612GasSponsoringInfo.from_dict(info) + + +def validate_eip2612_gas_sponsoring_info(info: Eip2612GasSponsoringInfo) -> bool: + """Validate info fields against the JSON Schema patterns.""" + return ( + bool(_HEX_ADDRESS.match(info.from_address)) + and bool(_HEX_ADDRESS.match(info.asset)) + and bool(_HEX_ADDRESS.match(info.spender)) + and bool(_DECIMAL_STRING.match(info.amount)) + and bool(_DECIMAL_STRING.match(info.nonce)) + and bool(_DECIMAL_STRING.match(info.deadline)) + and bool(_HEX_STRING.match(info.signature)) + and bool(_VERSION_STRING.match(info.version)) + ) + + +def validate_eip2612_permit_for_payment( + info: Eip2612GasSponsoringInfo, + payer: str, + token_address: str, +) -> str: + """Validate EIP-2612 extension data for a specific payment. + + Returns empty string if valid, or an error reason string. + """ + if not validate_eip2612_gas_sponsoring_info(info): + return "invalid_eip2612_extension_format" + + if info.from_address.lower() != payer.lower(): + return "eip2612_from_mismatch" + + if info.asset.lower() != token_address.lower(): + return "eip2612_asset_mismatch" + + if info.spender.lower() != PERMIT2_ADDRESS.lower(): + return "eip2612_spender_not_permit2" + + now = int(time.time()) + try: + if int(info.deadline) < now + PERMIT2_DEADLINE_BUFFER: + return "eip2612_deadline_expired" + except (ValueError, TypeError): + return "eip2612_deadline_expired" + + return "" diff --git a/python/x402/extensions/eip2612_gas_sponsoring/schema.py b/python/x402/extensions/eip2612_gas_sponsoring/schema.py new file mode 100644 index 0000000000..541c0d49a3 --- /dev/null +++ b/python/x402/extensions/eip2612_gas_sponsoring/schema.py @@ -0,0 +1,58 @@ +"""JSON Schema for the EIP-2612 Gas Sponsoring extension info payload.""" + +eip2612_gas_sponsoring_schema: dict = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "from": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the sender.", + }, + "asset": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the ERC-20 token contract.", + }, + "spender": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the spender (Canonical Permit2).", + }, + "amount": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "The amount to approve (uint256).", + }, + "nonce": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "The current EIP-2612 nonce of the sender.", + }, + "deadline": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "The timestamp at which the signature expires.", + }, + "signature": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$", + "description": "The 65-byte concatenated signature (r, s, v) as a hex string.", + }, + "version": { + "type": "string", + "pattern": r"^[0-9]+(\.[0-9]+)*$", + "description": "Schema version identifier.", + }, + }, + "required": [ + "from", + "asset", + "spender", + "amount", + "nonce", + "deadline", + "signature", + "version", + ], +} diff --git a/python/x402/extensions/eip2612_gas_sponsoring/server.py b/python/x402/extensions/eip2612_gas_sponsoring/server.py new file mode 100644 index 0000000000..3bf3e70736 --- /dev/null +++ b/python/x402/extensions/eip2612_gas_sponsoring/server.py @@ -0,0 +1,27 @@ +"""Resource server declaration for the EIP-2612 Gas Sponsoring extension.""" + +from __future__ import annotations + +from typing import Any + +from .schema import eip2612_gas_sponsoring_schema +from .types import EIP2612_GAS_SPONSORING_KEY + + +def declare_eip2612_gas_sponsoring_extension() -> dict[str, Any]: + """Declare the eip2612GasSponsoring extension for inclusion in PaymentRequired. + + Returns a dict keyed by the extension key, ready to merge into + PaymentRequired.extensions. + """ + return { + EIP2612_GAS_SPONSORING_KEY: { + "info": { + "description": ( + "The facilitator accepts EIP-2612 gasless Permit to Permit2 canonical contract." + ), + "version": "1", + }, + "schema": eip2612_gas_sponsoring_schema, + } + } diff --git a/python/x402/extensions/eip2612_gas_sponsoring/types.py b/python/x402/extensions/eip2612_gas_sponsoring/types.py new file mode 100644 index 0000000000..eeebc54321 --- /dev/null +++ b/python/x402/extensions/eip2612_gas_sponsoring/types.py @@ -0,0 +1,56 @@ +"""Types for the EIP-2612 Gas Sponsoring extension.""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Any + +from ...interfaces import FacilitatorExtension + +EIP2612_GAS_SPONSORING_KEY = "eip2612GasSponsoring" + +EIP2612_GAS_SPONSORING = FacilitatorExtension(key=EIP2612_GAS_SPONSORING_KEY) +"""Singleton extension instance for registering with x402Facilitator. + +Unlike erc20ApprovalGasSponsoring, this extension needs no special signer β€” +the facilitator's main EVM signer handles settleWithPermit directly. +""" + + +@dataclass +class Eip2612GasSponsoringInfo: + """EIP-2612 permit data sent by the client for gasless Permit2 approval.""" + + from_address: str + asset: str + spender: str + amount: str + nonce: str + deadline: str + signature: str + version: str = "1" + + def to_dict(self) -> dict[str, Any]: + return { + "from": self.from_address, + "asset": self.asset, + "spender": self.spender, + "amount": self.amount, + "nonce": self.nonce, + "deadline": self.deadline, + "signature": self.signature, + "version": self.version, + } + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Eip2612GasSponsoringInfo: + return cls( + from_address=data.get("from", ""), + asset=data.get("asset", ""), + spender=data.get("spender", ""), + amount=data.get("amount", ""), + nonce=data.get("nonce", ""), + deadline=data.get("deadline", ""), + signature=data.get("signature", ""), + version=data.get("version", "1"), + ) diff --git a/python/x402/extensions/erc20_approval_gas_sponsoring/__init__.py b/python/x402/extensions/erc20_approval_gas_sponsoring/__init__.py new file mode 100644 index 0000000000..8bdbc86b90 --- /dev/null +++ b/python/x402/extensions/erc20_approval_gas_sponsoring/__init__.py @@ -0,0 +1,29 @@ +"""ERC-20 Approval Gas Sponsoring Extension for x402 Permit2 flows.""" + +from .facilitator import ( + extract_erc20_approval_gas_sponsoring_info, + validate_erc20_approval_for_payment, + validate_erc20_approval_gas_sponsoring_info, +) +from .server import declare_erc20_approval_gas_sponsoring_extension +from .types import ( + ERC20_APPROVAL_GAS_SPONSORING_KEY, + Erc20ApprovalFacilitatorExtension, + Erc20ApprovalGasSponsoringInfo, + Erc20ApprovalGasSponsoringSigner, + TransactionRequest, + WriteContractCall, +) + +__all__ = [ + "ERC20_APPROVAL_GAS_SPONSORING_KEY", + "Erc20ApprovalFacilitatorExtension", + "Erc20ApprovalGasSponsoringInfo", + "Erc20ApprovalGasSponsoringSigner", + "TransactionRequest", + "WriteContractCall", + "declare_erc20_approval_gas_sponsoring_extension", + "extract_erc20_approval_gas_sponsoring_info", + "validate_erc20_approval_for_payment", + "validate_erc20_approval_gas_sponsoring_info", +] diff --git a/python/x402/extensions/erc20_approval_gas_sponsoring/client.py b/python/x402/extensions/erc20_approval_gas_sponsoring/client.py new file mode 100644 index 0000000000..9f66e16e6e --- /dev/null +++ b/python/x402/extensions/erc20_approval_gas_sponsoring/client.py @@ -0,0 +1,87 @@ +"""Client-side ERC-20 approval transaction signing for Permit2 approval sponsoring.""" + +from __future__ import annotations + +from typing import Any + +from ...mechanisms.evm.constants import ( + ERC20_APPROVE_ABI, + ERC20_APPROVE_GAS_LIMIT, + PERMIT2_ADDRESS, +) +from .types import Erc20ApprovalGasSponsoringInfo + +MAX_UINT256 = 2**256 - 1 + + +def sign_erc20_approval_transaction( + signer: Any, + token_address: str, + chain_id: int, +) -> Erc20ApprovalGasSponsoringInfo: + """Sign an ERC-20 approve(Permit2, MaxUint256) transaction. + + The signer must implement: + - address: str property + - sign_transaction(tx_dict) -> hex string + - get_transaction_count(address) -> int + - estimate_fees_per_gas() -> (max_fee, max_priority_fee) (optional) + + Args: + signer: Client signer with transaction signing capabilities. + token_address: ERC-20 token contract address. + chain_id: Chain ID. + + Returns: + Erc20ApprovalGasSponsoringInfo ready to attach to payload extensions. + """ + try: + from web3 import Web3 + + w3 = Web3() + contract = w3.eth.contract( + address=Web3.to_checksum_address(token_address), + abi=ERC20_APPROVE_ABI, + ) + calldata = contract.encode_abi( + abi_element_identifier="approve", + args=[Web3.to_checksum_address(PERMIT2_ADDRESS), MAX_UINT256], + ) + except ImportError: + calldata = ( + "0x095ea7b3" + PERMIT2_ADDRESS[2:].lower().zfill(64) + hex(MAX_UINT256)[2:].zfill(64) + ) + + nonce = signer.get_transaction_count(signer.address) + + max_fee = 1_000_000_000 + max_priority_fee = 100_000_000 + if hasattr(signer, "estimate_fees_per_gas"): + try: + fees = signer.estimate_fees_per_gas() + max_fee = fees[0] if isinstance(fees, tuple) else fees["maxFeePerGas"] + max_priority_fee = fees[1] if isinstance(fees, tuple) else fees["maxPriorityFeePerGas"] + except Exception: + pass + + tx = { + "to": token_address, + "data": calldata, + "nonce": nonce, + "gas": ERC20_APPROVE_GAS_LIMIT, + "maxFeePerGas": max_fee, + "maxPriorityFeePerGas": max_priority_fee, + "chainId": chain_id, + "type": 2, + } + + signed_tx_hex = signer.sign_transaction(tx) + + return Erc20ApprovalGasSponsoringInfo( + from_address=signer.address, + asset=token_address, + spender=PERMIT2_ADDRESS, + amount=str(MAX_UINT256), + signed_transaction=signed_tx_hex, + version="1", + ) diff --git a/python/x402/extensions/erc20_approval_gas_sponsoring/facilitator.py b/python/x402/extensions/erc20_approval_gas_sponsoring/facilitator.py new file mode 100644 index 0000000000..fd8cc55c50 --- /dev/null +++ b/python/x402/extensions/erc20_approval_gas_sponsoring/facilitator.py @@ -0,0 +1,154 @@ +"""Facilitator-side extraction and validation for ERC-20 Approval Gas Sponsoring.""" + +from __future__ import annotations + +import re + +from ...mechanisms.evm.constants import PERMIT2_ADDRESS +from ...schemas import PaymentPayload +from .types import ERC20_APPROVAL_GAS_SPONSORING_KEY, Erc20ApprovalGasSponsoringInfo + +_HEX_ADDRESS = re.compile(r"^0x[a-fA-F0-9]{40}$") +_DECIMAL_STRING = re.compile(r"^[0-9]+$") +_HEX_STRING = re.compile(r"^0x[a-fA-F0-9]+$") +_VERSION_STRING = re.compile(r"^[0-9]+(\.[0-9]+)*$") + +# ERC-20 approve(address,uint256) selector +_APPROVE_SELECTOR = "095ea7b3" + + +def extract_erc20_approval_gas_sponsoring_info( + payload: PaymentPayload, +) -> Erc20ApprovalGasSponsoringInfo | None: + """Extract ERC-20 approval gas sponsoring info from a payment payload. + + Returns None if the extension is not present or malformed. + """ + extensions = payload.extensions + if not extensions: + return None + + ext_data = extensions.get(ERC20_APPROVAL_GAS_SPONSORING_KEY) + if not isinstance(ext_data, dict): + return None + + info = ext_data.get("info") + if not isinstance(info, dict): + return None + + required = ["from", "asset", "spender", "amount", "signedTransaction"] + if not all(isinstance(info.get(k), str) for k in required): + return None + + return Erc20ApprovalGasSponsoringInfo.from_dict(info) + + +def validate_erc20_approval_gas_sponsoring_info( + info: Erc20ApprovalGasSponsoringInfo, +) -> bool: + """Validate info fields against the JSON Schema patterns.""" + return ( + bool(_HEX_ADDRESS.match(info.from_address)) + and bool(_HEX_ADDRESS.match(info.asset)) + and bool(_HEX_ADDRESS.match(info.spender)) + and bool(_DECIMAL_STRING.match(info.amount)) + and bool(_HEX_STRING.match(info.signed_transaction)) + and bool(_VERSION_STRING.match(info.version)) + ) + + +def validate_erc20_approval_for_payment( + info: Erc20ApprovalGasSponsoringInfo, + payer: str, + token_address: str, +) -> tuple[str, str]: + """Validate ERC-20 approval extension data for a specific payment. + + Returns ("", "") if valid, or (reason, message) on failure. + Performs schema validation, address matching, and signed tx decoding. + """ + if not validate_erc20_approval_gas_sponsoring_info(info): + return "invalid_erc20_approval_extension_format", "format validation failed" + + if info.from_address.lower() != payer.lower(): + return "erc20_approval_from_mismatch", "from does not match payer" + + if info.asset.lower() != token_address.lower(): + return "erc20_approval_asset_mismatch", "asset does not match token" + + if info.spender.lower() != PERMIT2_ADDRESS.lower(): + return "erc20_approval_spender_not_permit2", "spender is not Permit2" + + # Decode and validate the signed transaction + try: + reason, msg = _validate_signed_approval_tx(info.signed_transaction, payer, token_address) + if reason: + return reason, msg + except Exception as e: + return "erc20_approval_tx_parse_failed", str(e)[:200] + + return "", "" + + +def _validate_signed_approval_tx( + signed_tx_hex: str, + payer: str, + token_address: str, +) -> tuple[str, str]: + """Decode and validate a signed ERC-20 approve transaction. + + Checks: target address, function selector, spender in calldata, + and recovered signer. + """ + try: + from eth_account import Account + except ImportError: + return "erc20_approval_tx_validation_unavailable", "eth_account not installed" + + tx_bytes = bytes.fromhex(signed_tx_hex[2:] if signed_tx_hex.startswith("0x") else signed_tx_hex) + + try: + recovered = Account.recover_transaction(signed_tx_hex) + except Exception: + return "erc20_approval_tx_invalid_signature", "failed to recover signer" + + if recovered.lower() != payer.lower(): + return "erc20_approval_tx_signer_mismatch", "recovered signer does not match payer" + + try: + from eth_account._utils.typed_transactions import TypedTransaction + + tx_obj = TypedTransaction.from_bytes(tx_bytes) + tx_dict = tx_obj.transaction.dictionary + + to_addr = tx_dict.get("to", b"") + if isinstance(to_addr, bytes): + to_addr = "0x" + to_addr.hex() + to_addr = str(to_addr) + + if to_addr.lower() != token_address.lower(): + return "erc20_approval_tx_wrong_target", "tx target is not the token" + + data = tx_dict.get("data", b"") + if isinstance(data, bytes): + data_hex = data.hex() + else: + data_hex = str(data) + + if not data_hex.startswith(_APPROVE_SELECTOR): + return "erc20_approval_tx_wrong_selector", "not an approve() call" + + # Decode spender from calldata (bytes 4..36 = 32-byte padded address) + if len(data_hex) < 72: + return "erc20_approval_tx_invalid_calldata", "calldata too short" + + spender_hex = "0x" + data_hex[32:72] + if spender_hex.lower() != PERMIT2_ADDRESS.lower(): + return "erc20_approval_tx_wrong_spender", "approve spender is not Permit2" + + except ImportError: + return "erc20_approval_tx_validation_unavailable", "typed transaction parsing not available" + except Exception as e: + return "erc20_approval_tx_parse_failed", str(e)[:200] + + return "", "" diff --git a/python/x402/extensions/erc20_approval_gas_sponsoring/schema.py b/python/x402/extensions/erc20_approval_gas_sponsoring/schema.py new file mode 100644 index 0000000000..15a7771d88 --- /dev/null +++ b/python/x402/extensions/erc20_approval_gas_sponsoring/schema.py @@ -0,0 +1,46 @@ +"""JSON Schema for the ERC-20 Approval Gas Sponsoring extension info payload.""" + +erc20_approval_gas_sponsoring_schema: dict = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "from": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the sender.", + }, + "asset": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The ERC-20 token contract address to approve.", + }, + "spender": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]{40}$", + "description": "The address of the spender (Canonical Permit2).", + }, + "amount": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Approval amount (uint256).", + }, + "signedTransaction": { + "type": "string", + "pattern": "^0x[a-fA-F0-9]+$", + "description": "RLP-encoded signed transaction calling ERC20.approve().", + }, + "version": { + "type": "string", + "pattern": r"^[0-9]+(\.[0-9]+)*$", + "description": "Schema version identifier.", + }, + }, + "required": [ + "from", + "asset", + "spender", + "amount", + "signedTransaction", + "version", + ], +} diff --git a/python/x402/extensions/erc20_approval_gas_sponsoring/server.py b/python/x402/extensions/erc20_approval_gas_sponsoring/server.py new file mode 100644 index 0000000000..fbac2f71cb --- /dev/null +++ b/python/x402/extensions/erc20_approval_gas_sponsoring/server.py @@ -0,0 +1,28 @@ +"""Resource server declaration for the ERC-20 Approval Gas Sponsoring extension.""" + +from __future__ import annotations + +from typing import Any + +from .schema import erc20_approval_gas_sponsoring_schema +from .types import ERC20_APPROVAL_GAS_SPONSORING_KEY + + +def declare_erc20_approval_gas_sponsoring_extension() -> dict[str, Any]: + """Declare the erc20ApprovalGasSponsoring extension for PaymentRequired. + + Returns a dict keyed by the extension key, ready to merge into + PaymentRequired.extensions. + """ + return { + ERC20_APPROVAL_GAS_SPONSORING_KEY: { + "info": { + "description": ( + "The facilitator accepts a raw signed approval transaction " + "and will sponsor the gas fees." + ), + "version": "1", + }, + "schema": erc20_approval_gas_sponsoring_schema, + } + } diff --git a/python/x402/extensions/erc20_approval_gas_sponsoring/types.py b/python/x402/extensions/erc20_approval_gas_sponsoring/types.py new file mode 100644 index 0000000000..3d6ab85f4f --- /dev/null +++ b/python/x402/extensions/erc20_approval_gas_sponsoring/types.py @@ -0,0 +1,105 @@ +"""Types for the ERC-20 Approval Gas Sponsoring extension.""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import Any, Protocol + +ERC20_APPROVAL_GAS_SPONSORING_KEY = "erc20ApprovalGasSponsoring" + + +@dataclass +class Erc20ApprovalGasSponsoringInfo: + """ERC-20 approval data sent by the client for gasless Permit2 approval.""" + + from_address: str + asset: str + spender: str + amount: str + signed_transaction: str + version: str = "1" + + def to_dict(self) -> dict[str, Any]: + return { + "from": self.from_address, + "asset": self.asset, + "spender": self.spender, + "amount": self.amount, + "signedTransaction": self.signed_transaction, + "version": self.version, + } + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> Erc20ApprovalGasSponsoringInfo: + return cls( + from_address=data.get("from", ""), + asset=data.get("asset", ""), + spender=data.get("spender", ""), + amount=data.get("amount", ""), + signed_transaction=data.get("signedTransaction", ""), + version=data.get("version", "1"), + ) + + +@dataclass +class WriteContractCall: + """An unsigned contract call for the extension signer to execute.""" + + address: str + abi: list[dict[str, Any]] + function: str + args: list[Any] = field(default_factory=list) + + +TransactionRequest = str | WriteContractCall + + +class Erc20ApprovalGasSponsoringSigner(Protocol): + """Extension signer capable of broadcasting approval + settle atomically. + + Extends FacilitatorEvmSigner with send_transactions for batched execution. + """ + + def send_transactions(self, transactions: list[TransactionRequest]) -> list[str]: + """Send a batch of transactions (pre-signed raw hex or unsigned calls). + + Args: + transactions: List of either raw hex tx strings or WriteContractCall. + + Returns: + List of transaction hashes, one per input. + """ + ... + + def wait_for_transaction_receipt(self, tx_hash: str) -> Any: + """Wait for a transaction to be mined.""" + ... + + +class Erc20ApprovalFacilitatorExtension: + """Facilitator extension for ERC-20 approval gas sponsoring. + + Wraps a signer (or per-network signer resolver) that can broadcast + the approval + settle bundle. + + Implements the FacilitatorExtension interface (key attribute) without + inheriting from the frozen dataclass. + """ + + key: str = ERC20_APPROVAL_GAS_SPONSORING_KEY + + def __init__( + self, + signer: Erc20ApprovalGasSponsoringSigner | None = None, + signer_for_network: Any = None, + ): + self._signer = signer + self._signer_for_network = signer_for_network + + def resolve_signer(self, network: str) -> Erc20ApprovalGasSponsoringSigner | None: + """Resolve the signer for a given network.""" + if self._signer_for_network is not None: + result = self._signer_for_network(network) + if result is not None: + return result + return self._signer diff --git a/python/x402/mechanisms/evm/__init__.py b/python/x402/mechanisms/evm/__init__.py index a364df1775..ddd4196c3a 100644 --- a/python/x402/mechanisms/evm/__init__.py +++ b/python/x402/mechanisms/evm/__init__.py @@ -56,7 +56,7 @@ from .signer import ClientEvmSigner, FacilitatorEvmSigner # Signer implementations -from .signers import EthAccountSigner, FacilitatorWeb3Signer +from .signers import EthAccountSigner, EthAccountSignerWithRPC, FacilitatorWeb3Signer # Types from .types import ( @@ -153,6 +153,7 @@ "FacilitatorEvmSigner", # Signer implementations "EthAccountSigner", + "EthAccountSignerWithRPC", "FacilitatorWeb3Signer", # Utilities "get_evm_chain_id", diff --git a/python/x402/mechanisms/evm/constants.py b/python/x402/mechanisms/evm/constants.py index 8ef6492576..e597b4aa38 100644 --- a/python/x402/mechanisms/evm/constants.py +++ b/python/x402/mechanisms/evm/constants.py @@ -31,6 +31,175 @@ # EIP-1271 magic value (returned by isValidSignature on success) EIP1271_MAGIC_VALUE = bytes.fromhex("1626ba7e") +# Permit2 contract address (same on all EVM chains via CREATE2) +PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3" + +# x402ExactPermit2Proxy contract address +X402_EXACT_PERMIT2_PROXY_ADDRESS = "0x402085c248EeA27D92E8b30b2C58ed07f9E20001" + +# Permit2 EIP-712 witness types for PermitWitnessTransferFrom +# Note: Types must be in alphabetical order after primary type (TokenPermissions < Witness) +PERMIT2_WITNESS_TYPES: dict[str, list[dict[str, str]]] = { + "PermitWitnessTransferFrom": [ + {"name": "permitted", "type": "TokenPermissions"}, + {"name": "spender", "type": "address"}, + {"name": "nonce", "type": "uint256"}, + {"name": "deadline", "type": "uint256"}, + {"name": "witness", "type": "Witness"}, + ], + "TokenPermissions": [ + {"name": "token", "type": "address"}, + {"name": "amount", "type": "uint256"}, + ], + "Witness": [ + {"name": "to", "type": "address"}, + {"name": "validAfter", "type": "uint256"}, + ], +} + +# x402ExactPermit2Proxy settle ABI +X402_EXACT_PERMIT2_PROXY_ABI = [ + { + "type": "function", + "name": "settle", + "inputs": [ + { + "name": "permit", + "type": "tuple", + "components": [ + { + "name": "permitted", + "type": "tuple", + "components": [ + {"name": "token", "type": "address"}, + {"name": "amount", "type": "uint256"}, + ], + }, + {"name": "nonce", "type": "uint256"}, + {"name": "deadline", "type": "uint256"}, + ], + }, + {"name": "owner", "type": "address"}, + { + "name": "witness", + "type": "tuple", + "components": [ + {"name": "to", "type": "address"}, + {"name": "validAfter", "type": "uint256"}, + ], + }, + {"name": "signature", "type": "bytes"}, + ], + "outputs": [], + "stateMutability": "nonpayable", + } +] + +# x402ExactPermit2Proxy settleWithPermit ABI (EIP-2612 extension path) +X402_EXACT_PERMIT2_PROXY_SETTLE_WITH_PERMIT_ABI = [ + { + "type": "function", + "name": "settleWithPermit", + "inputs": [ + { + "name": "permit2612", + "type": "tuple", + "components": [ + {"name": "value", "type": "uint256"}, + {"name": "deadline", "type": "uint256"}, + {"name": "r", "type": "bytes32"}, + {"name": "s", "type": "bytes32"}, + {"name": "v", "type": "uint8"}, + ], + }, + { + "name": "permit", + "type": "tuple", + "components": [ + { + "name": "permitted", + "type": "tuple", + "components": [ + {"name": "token", "type": "address"}, + {"name": "amount", "type": "uint256"}, + ], + }, + {"name": "nonce", "type": "uint256"}, + {"name": "deadline", "type": "uint256"}, + ], + }, + {"name": "owner", "type": "address"}, + { + "name": "witness", + "type": "tuple", + "components": [ + {"name": "to", "type": "address"}, + {"name": "validAfter", "type": "uint256"}, + ], + }, + {"name": "signature", "type": "bytes"}, + ], + "outputs": [], + "stateMutability": "nonpayable", + } +] + +# EIP-2612 nonces ABI +EIP2612_NONCES_ABI = [ + { + "type": "function", + "name": "nonces", + "inputs": [{"name": "owner", "type": "address"}], + "outputs": [{"type": "uint256"}], + "stateMutability": "view", + } +] + +# EIP-2612 EIP-712 Permit types +EIP2612_PERMIT_TYPES: dict[str, list[dict[str, str]]] = { + "Permit": [ + {"name": "owner", "type": "address"}, + {"name": "spender", "type": "address"}, + {"name": "value", "type": "uint256"}, + {"name": "nonce", "type": "uint256"}, + {"name": "deadline", "type": "uint256"}, + ] +} + +# Gas limit for a standard ERC-20 approve() transaction +ERC20_APPROVE_GAS_LIMIT = 70_000 + +# Permit2 deadline buffer (seconds) for verification +PERMIT2_DEADLINE_BUFFER = 6 + +# ERC-20 allowance ABI +ERC20_ALLOWANCE_ABI = [ + { + "type": "function", + "name": "allowance", + "inputs": [ + {"name": "owner", "type": "address"}, + {"name": "spender", "type": "address"}, + ], + "outputs": [{"type": "uint256"}], + "stateMutability": "view", + } +] + +# ERC-20 approve ABI +ERC20_APPROVE_ABI = [ + { + "type": "function", + "name": "approve", + "inputs": [ + {"name": "spender", "type": "address"}, + {"name": "amount", "type": "uint256"}, + ], + "outputs": [{"type": "bool"}], + "stateMutability": "nonpayable", + } +] + # Error codes ERR_INVALID_SIGNATURE = "invalid_exact_evm_payload_signature" ERR_UNDEPLOYED_SMART_WALLET = "invalid_exact_evm_payload_undeployed_smart_wallet" @@ -53,6 +222,16 @@ ERR_EIP3009_NOT_SUPPORTED = "invalid_exact_evm_eip3009_not_supported" ERR_TRANSACTION_SIMULATION_FAILED = "invalid_exact_evm_transaction_simulation_failed" +# Permit2-specific error codes +ERR_PERMIT2_INVALID_SPENDER = "invalid_permit2_spender" +ERR_PERMIT2_RECIPIENT_MISMATCH = "invalid_permit2_recipient_mismatch" +ERR_PERMIT2_DEADLINE_EXPIRED = "permit2_deadline_expired" +ERR_PERMIT2_NOT_YET_VALID = "permit2_not_yet_valid" +ERR_PERMIT2_AMOUNT_MISMATCH = "invalid_exact_evm_payload_amount_mismatch" +ERR_PERMIT2_TOKEN_MISMATCH = "permit2_token_mismatch" +ERR_PERMIT2_INVALID_SIGNATURE = "invalid_permit2_signature" +ERR_PERMIT2_ALLOWANCE_REQUIRED = "permit2_allowance_required" + class _AssetInfoRequired(TypedDict): """Required fields for a token asset.""" diff --git a/python/x402/mechanisms/evm/exact/client.py b/python/x402/mechanisms/evm/exact/client.py index 66157a8212..5eabc10a39 100644 --- a/python/x402/mechanisms/evm/exact/client.py +++ b/python/x402/mechanisms/evm/exact/client.py @@ -6,16 +6,22 @@ from typing import Any from ....schemas import PaymentRequirements -from ..constants import SCHEME_EXACT +from ..constants import ERC20_ALLOWANCE_ABI, PERMIT2_ADDRESS, SCHEME_EXACT from ..eip712 import build_typed_data_for_signing -from ..signer import ClientEvmSigner +from ..signer import ( + ClientEvmSigner, + ClientEvmSignerWithReadContract, + ClientEvmSignerWithSignTransaction, +) from ..types import ExactEIP3009Authorization, ExactEIP3009Payload, TypedDataField from ..utils import ( create_nonce, create_validity_window, get_asset_info, get_evm_chain_id, + normalize_address, ) +from .permit2_utils import create_permit2_payload def _wrap_if_local_account(signer: Any) -> ClientEvmSigner: @@ -38,6 +44,10 @@ class ExactEvmScheme: Implements SchemeNetworkClient protocol. Returns the inner payload dict, which x402Client wraps into a full PaymentPayload. + For Permit2 flows, if the server advertises gas sponsoring extensions + and the signer has the required capabilities, the scheme automatically + signs extension data when Permit2 allowance is insufficient. + Attributes: scheme: The scheme identifier ("exact"). """ @@ -57,16 +67,32 @@ def __init__(self, signer: ClientEvmSigner): def create_payment_payload( self, requirements: PaymentRequirements, + extensions: dict[str, Any] | None = None, ) -> dict[str, Any]: - """Create signed EIP-3009 inner payload. + """Create signed payment inner payload. + + Routes to Permit2 or EIP-3009 based on requirements.extra.assetTransferMethod. + For Permit2, enriches with gas sponsoring extensions when advertised. Args: requirements: Payment requirements from server. + extensions: Server-declared extensions from PaymentRequired. Returns: - Inner payload dict (authorization + signature). + Inner payload dict. x402Client wraps this with x402_version, accepted, resource, extensions. """ + extra = requirements.extra or {} + if extra.get("assetTransferMethod") == "permit2": + result = create_permit2_payload(self._signer, requirements) + + if extensions: + ext_data = self._try_sign_extensions(requirements, result, extensions) + if ext_data: + result["__extensions"] = ext_data + + return result + nonce = create_nonce() valid_after, valid_before = create_validity_window( timedelta(seconds=requirements.max_timeout_seconds or 3600) @@ -85,9 +111,130 @@ def create_payment_payload( payload = ExactEIP3009Payload(authorization=authorization, signature=signature) - # Return inner payload dict - x402Client wraps this return payload.to_dict() + def _try_sign_extensions( + self, + requirements: PaymentRequirements, + result: dict[str, Any], + extensions: dict[str, Any], + ) -> dict[str, Any] | None: + """Try to sign gas sponsoring extensions for Permit2 flows.""" + + # Try EIP-2612 first + eip2612_ext = self._try_sign_eip2612(requirements, result, extensions) + if eip2612_ext: + return eip2612_ext + + # Try ERC-20 approval fallback + erc20_ext = self._try_sign_erc20_approval(requirements, extensions) + if erc20_ext: + return erc20_ext + + return None + + def _try_sign_eip2612( + self, + requirements: PaymentRequirements, + result: dict[str, Any], + extensions: dict[str, Any], + ) -> dict[str, Any] | None: + """Try to sign an EIP-2612 permit for gasless Permit2 approval.""" + from ....extensions.eip2612_gas_sponsoring import EIP2612_GAS_SPONSORING_KEY + from ....extensions.eip2612_gas_sponsoring.client import sign_eip2612_permit + + if EIP2612_GAS_SPONSORING_KEY not in extensions: + return None + + if not isinstance(self._signer, ClientEvmSignerWithReadContract): + return None + + extra = requirements.extra or {} + token_name = extra.get("name") + token_version = extra.get("version") + if not token_name or not token_version: + return None + + chain_id = get_evm_chain_id(str(requirements.network)) + token_address = normalize_address(requirements.asset) + + try: + allowance = self._signer.read_contract( + token_address, + ERC20_ALLOWANCE_ABI, + "allowance", + self._signer.address, + PERMIT2_ADDRESS, + ) + if int(allowance) >= int(requirements.amount): + return None + except Exception: + pass # Allowance check failed, proceed with signing + + permit2_auth = result.get("permit2Authorization", {}) + deadline = permit2_auth.get("deadline", "") + if not deadline: + import time + + deadline = str(int(time.time()) + (requirements.max_timeout_seconds or 3600)) + + info = sign_eip2612_permit( + self._signer, + token_address, + token_name, + token_version, + chain_id, + deadline, + requirements.amount, + ) + + return {EIP2612_GAS_SPONSORING_KEY: {"info": info.to_dict()}} + + def _try_sign_erc20_approval( + self, + requirements: PaymentRequirements, + extensions: dict[str, Any], + ) -> dict[str, Any] | None: + """Try to sign an ERC-20 approval tx for gasless Permit2 approval.""" + from ....extensions.erc20_approval_gas_sponsoring import ( + ERC20_APPROVAL_GAS_SPONSORING_KEY, + ) + from ....extensions.erc20_approval_gas_sponsoring.client import ( + sign_erc20_approval_transaction, + ) + + if ERC20_APPROVAL_GAS_SPONSORING_KEY not in extensions: + return None + + if not isinstance(self._signer, ClientEvmSignerWithSignTransaction): + return None + + chain_id = get_evm_chain_id(str(requirements.network)) + token_address = normalize_address(requirements.asset) + + # Skip if allowance is already sufficient + if isinstance(self._signer, ClientEvmSignerWithReadContract): + try: + allowance = self._signer.read_contract( + token_address, + ERC20_ALLOWANCE_ABI, + "allowance", + self._signer.address, + PERMIT2_ADDRESS, + ) + if int(allowance) >= int(requirements.amount): + return None + except Exception: + pass + + info = sign_erc20_approval_transaction( + self._signer, + token_address, + chain_id, + ) + + return {ERC20_APPROVAL_GAS_SPONSORING_KEY: {"info": info.to_dict()}} + def _sign_authorization( self, authorization: ExactEIP3009Authorization, diff --git a/python/x402/mechanisms/evm/exact/facilitator.py b/python/x402/mechanisms/evm/exact/facilitator.py index a80bacb6f7..e7b61010d5 100644 --- a/python/x402/mechanisms/evm/exact/facilitator.py +++ b/python/x402/mechanisms/evm/exact/facilitator.py @@ -36,8 +36,9 @@ parse_eip3009_authorization, simulate_eip3009_transfer, ) +from ..exact.permit2_utils import settle_permit2, verify_permit2 from ..signer import FacilitatorEvmSigner -from ..types import ERC6492SignatureData, ExactEIP3009Payload +from ..types import ERC6492SignatureData, ExactEIP3009Payload, is_permit2_payload from ..utils import bytes_to_hex, get_evm_chain_id, hex_to_bytes, normalize_address @@ -107,6 +108,8 @@ def verify( requirements: PaymentRequirements, context=None, ) -> VerifyResponse: + if is_permit2_payload(payload.payload): + return verify_permit2(self._signer, payload, requirements, context) return self._verify(payload, requirements, simulate=True) def _verify( @@ -271,8 +274,10 @@ def settle( requirements: PaymentRequirements, context=None, ) -> SettleResponse: - """Settle EIP-3009 payment on-chain. + """Settle payment on-chain. + Routes to Permit2 or EIP-3009 settlement based on payload type. + For EIP-3009: - Re-verifies payment - Deploys smart wallet if configured and needed (ERC-6492) - Calls transferWithAuthorization (v,r,s or bytes overload) @@ -285,6 +290,9 @@ def settle( Returns: SettleResponse with success, transaction, and payer. """ + if is_permit2_payload(payload.payload): + return settle_permit2(self._signer, payload, requirements, context) + # First verify verify_result = self._verify( payload, diff --git a/python/x402/mechanisms/evm/exact/permit2_utils.py b/python/x402/mechanisms/evm/exact/permit2_utils.py new file mode 100644 index 0000000000..d5d10fddf3 --- /dev/null +++ b/python/x402/mechanisms/evm/exact/permit2_utils.py @@ -0,0 +1,740 @@ +"""Permit2 helpers for the exact EVM payment scheme.""" + +from __future__ import annotations + +import logging +import time +from typing import Any + +logger = logging.getLogger("x402.permit2") + +try: + from eth_utils import to_checksum_address +except ImportError as e: + raise ImportError( + "EVM mechanism requires ethereum packages. Install with: pip install x402[evm]" + ) from e + +from ....interfaces import FacilitatorContext # noqa: E402 +from ....schemas import ( # noqa: E402 + PaymentPayload, + PaymentRequirements, + SettleResponse, + VerifyResponse, +) +from ..constants import ( # noqa: E402 + BALANCE_OF_ABI, + ERC20_ALLOWANCE_ABI, + ERR_INSUFFICIENT_BALANCE, + ERR_NETWORK_MISMATCH, + ERR_PERMIT2_ALLOWANCE_REQUIRED, + ERR_PERMIT2_AMOUNT_MISMATCH, + ERR_PERMIT2_DEADLINE_EXPIRED, + ERR_PERMIT2_INVALID_SIGNATURE, + ERR_PERMIT2_INVALID_SPENDER, + ERR_PERMIT2_NOT_YET_VALID, + ERR_PERMIT2_RECIPIENT_MISMATCH, + ERR_PERMIT2_TOKEN_MISMATCH, + ERR_TRANSACTION_FAILED, + ERR_UNSUPPORTED_SCHEME, + PERMIT2_ADDRESS, + PERMIT2_WITNESS_TYPES, + SCHEME_EXACT, + TX_STATUS_SUCCESS, + X402_EXACT_PERMIT2_PROXY_ABI, + X402_EXACT_PERMIT2_PROXY_ADDRESS, + X402_EXACT_PERMIT2_PROXY_SETTLE_WITH_PERMIT_ABI, +) +from ..signer import ClientEvmSigner, FacilitatorEvmSigner # noqa: E402 +from ..types import ( # noqa: E402 + ExactPermit2Authorization, + ExactPermit2Payload, + ExactPermit2TokenPermissions, + ExactPermit2Witness, + TypedDataField, +) +from ..utils import ( # noqa: E402 + create_permit2_nonce, + get_evm_chain_id, + hex_to_bytes, + normalize_address, +) + + +def create_permit2_payload( + signer: ClientEvmSigner, + requirements: PaymentRequirements, +) -> dict[str, Any]: + """Create a signed Permit2 PermitWitnessTransferFrom payload. + + The spender is always x402ExactPermit2Proxy, which enforces that funds + can only be sent to the witness.to address (requirements.pay_to). + + Args: + signer: EVM signer for signing the Permit2 authorization. + requirements: Payment requirements from server. + + Returns: + Inner payload dict (permit2Authorization + signature). + """ + now = int(time.time()) + nonce = create_permit2_nonce() + + # Lower time bound - allow clock skew + valid_after = str(now - 600) + # Upper time bound - permit2 deadline + deadline = str(now + (requirements.max_timeout_seconds or 3600)) + + permit2_authorization = ExactPermit2Authorization( + from_address=signer.address, + permitted=ExactPermit2TokenPermissions( + token=normalize_address(requirements.asset), + amount=requirements.amount, + ), + spender=X402_EXACT_PERMIT2_PROXY_ADDRESS, + nonce=nonce, + deadline=deadline, + witness=ExactPermit2Witness( + to=normalize_address(requirements.pay_to), + valid_after=valid_after, + ), + ) + + signature = _sign_permit2_authorization(signer, permit2_authorization, requirements) + + payload = ExactPermit2Payload( + permit2_authorization=permit2_authorization, + signature=signature, + ) + return payload.to_dict() + + +def _sign_permit2_authorization( + signer: ClientEvmSigner, + permit2_authorization: ExactPermit2Authorization, + requirements: PaymentRequirements, +) -> str: + """Sign a Permit2 PermitWitnessTransferFrom using EIP-712. + + The Permit2 domain has NO version field β€” only name, chainId, verifyingContract. + We pass the domain as a raw dict to support signers whose protocol expects + TypedDataDomain (which requires version), using the dict fallback path in + EthAccountSigner.sign_typed_data(). + + Args: + signer: EVM signer. + permit2_authorization: The authorization to sign. + requirements: Payment requirements (used for chain ID). + + Returns: + Hex-encoded signature with 0x prefix. + """ + chain_id = get_evm_chain_id(str(requirements.network)) + domain_dict, typed_fields, primary_type, message = _build_permit2_typed_data( + permit2_authorization, chain_id + ) + + sig_bytes = signer.sign_typed_data( + domain_dict, # type: ignore[arg-type] + typed_fields, + primary_type, + message, + ) + return "0x" + sig_bytes.hex() + + +def verify_permit2( + signer: FacilitatorEvmSigner, + payload: PaymentPayload, + requirements: PaymentRequirements, + context: FacilitatorContext | None = None, +) -> VerifyResponse: + """Verify a Permit2 payment payload. + + Verification cascade (cheap to expensive): + 1. Scheme check + 2. Network check + 3. Spender check (must be x402ExactPermit2Proxy) + 4. Recipient check (witness.to must match requirements.pay_to) + 5. Deadline check (must not be expired) + 6. validAfter check (must not be in the future) + 7. Amount check + 8. Token check + 9. Signature verification + 10. Allowance check (with extension fallbacks) + 11. Balance check + + Args: + signer: Facilitator EVM signer for on-chain reads. + payload: Payment payload from client. + requirements: Payment requirements. + context: Optional facilitator context for extension lookup. + + Returns: + VerifyResponse with is_valid and payer. + """ + permit2_payload = ExactPermit2Payload.from_dict(payload.payload) + payer = permit2_payload.permit2_authorization.from_address + + # 1. Scheme check + if payload.accepted.scheme != SCHEME_EXACT: + return VerifyResponse(is_valid=False, invalid_reason=ERR_UNSUPPORTED_SCHEME, payer=payer) + + # 2. Network check + if payload.accepted.network != requirements.network: + return VerifyResponse(is_valid=False, invalid_reason=ERR_NETWORK_MISMATCH, payer=payer) + + chain_id = get_evm_chain_id(str(requirements.network)) + token_address = normalize_address(requirements.asset) + + # 3. Spender check + try: + spender_norm = normalize_address(permit2_payload.permit2_authorization.spender) + proxy_norm = normalize_address(X402_EXACT_PERMIT2_PROXY_ADDRESS) + except Exception: + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_INVALID_SPENDER, payer=payer + ) + + if spender_norm != proxy_norm: + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_INVALID_SPENDER, payer=payer + ) + + # 4. Recipient check + try: + witness_to = normalize_address(permit2_payload.permit2_authorization.witness.to) + pay_to = normalize_address(requirements.pay_to) + except Exception: + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_RECIPIENT_MISMATCH, payer=payer + ) + + if witness_to != pay_to: + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_RECIPIENT_MISMATCH, payer=payer + ) + + now = int(time.time()) + + # 5-7. Parse numeric fields from untrusted input before comparison + try: + deadline_val = int(permit2_payload.permit2_authorization.deadline) + valid_after_val = int(permit2_payload.permit2_authorization.witness.valid_after) + amount_val = int(permit2_payload.permit2_authorization.permitted.amount) + except (ValueError, TypeError): + return VerifyResponse( + is_valid=False, invalid_reason="invalid_permit2_payload_format", payer=payer + ) + + # 5. Deadline check (6 second buffer) + if deadline_val < now + 6: + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_DEADLINE_EXPIRED, payer=payer + ) + + # 6. validAfter check + if valid_after_val > now: + return VerifyResponse(is_valid=False, invalid_reason=ERR_PERMIT2_NOT_YET_VALID, payer=payer) + + # 7. Amount check + if amount_val != int(requirements.amount): + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_AMOUNT_MISMATCH, payer=payer + ) + + # 8. Token check + try: + permitted_token = normalize_address(permit2_payload.permit2_authorization.permitted.token) + except Exception: + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_TOKEN_MISMATCH, payer=payer + ) + + if permitted_token != token_address: + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_TOKEN_MISMATCH, payer=payer + ) + + # 9. Signature verification + if not permit2_payload.signature: + logger.warning("Permit2 verify: missing signature") + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_INVALID_SIGNATURE, payer=payer + ) + + try: + sig_bytes = hex_to_bytes(permit2_payload.signature) + logger.info( + "Permit2 verify: checking signature for payer=%s chain_id=%s sig_len=%d", + payer, + chain_id, + len(sig_bytes), + ) + is_valid_sig = _verify_permit2_signature( + signer, + payer, + permit2_payload.permit2_authorization, + chain_id, + sig_bytes, + ) + if not is_valid_sig: + logger.warning("Permit2 verify: signature verification returned False") + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_INVALID_SIGNATURE, payer=payer + ) + logger.info("Permit2 verify: signature OK") + except Exception as e: + logger.warning("Permit2 verify: signature exception: %s", e, exc_info=True) + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_INVALID_SIGNATURE, payer=payer + ) + + # 10. Allowance check β€” with extension fallbacks + allowance_result = _verify_permit2_allowance( + signer, payload, requirements, payer, token_address, context + ) + if allowance_result is not None: + logger.warning( + "Permit2 verify: allowance check failed: %s", allowance_result.invalid_reason + ) + return allowance_result + logger.info("Permit2 verify: allowance OK") + + # 11. Balance check (fail closed β€” RPC failure rejects rather than allowing underfunded payments) + try: + balance = signer.read_contract(token_address, BALANCE_OF_ABI, "balanceOf", payer) + if int(balance) < int(requirements.amount): + return VerifyResponse( + is_valid=False, invalid_reason=ERR_INSUFFICIENT_BALANCE, payer=payer + ) + except Exception: + logger.warning("Permit2 verify: balance check failed for payer=%s", payer, exc_info=True) + return VerifyResponse(is_valid=False, invalid_reason="balance_check_failed", payer=payer) + + return VerifyResponse(is_valid=True, payer=payer) + + +def _verify_permit2_allowance( + signer: FacilitatorEvmSigner, + payload: PaymentPayload, + requirements: PaymentRequirements, + payer: str, + token_address: str, + context: FacilitatorContext | None, +) -> VerifyResponse | None: + """Check Permit2 allowance with extension fallbacks. + + Returns a VerifyResponse if verification should stop (failure), + or None to continue with remaining checks. + + Fallback order (matching TS/Go): + 1. On-chain allowance sufficient -> None (continue) + 2. EIP-2612 gas sponsoring extension valid -> None (continue) + 3. ERC-20 approval gas sponsoring extension valid -> None (continue) + 4. Fail with permit2_allowance_required + """ + from ....extensions.eip2612_gas_sponsoring import ( + extract_eip2612_gas_sponsoring_info, + validate_eip2612_permit_for_payment, + ) + from ....extensions.erc20_approval_gas_sponsoring import ( + ERC20_APPROVAL_GAS_SPONSORING_KEY, + Erc20ApprovalFacilitatorExtension, + extract_erc20_approval_gas_sponsoring_info, + validate_erc20_approval_for_payment, + ) + + needs_extension = True + try: + allowance = signer.read_contract( + token_address, + ERC20_ALLOWANCE_ABI, + "allowance", + payer, + PERMIT2_ADDRESS, + ) + if int(allowance) >= int(requirements.amount): + needs_extension = False + except Exception: + logger.warning("Permit2 verify: allowance check failed for payer=%s", payer, exc_info=True) + + if not needs_extension: + return None + + # Try EIP-2612 gas sponsoring extension first + eip2612_info = extract_eip2612_gas_sponsoring_info(payload) + if eip2612_info is not None: + reason = validate_eip2612_permit_for_payment(eip2612_info, payer, token_address) + if reason: + return VerifyResponse(is_valid=False, invalid_reason=reason, payer=payer) + return None # Valid EIP-2612 extension, allowance will be set atomically + + # Try ERC-20 approval gas sponsoring extension + erc20_info = extract_erc20_approval_gas_sponsoring_info(payload) + if erc20_info is not None and context is not None: + ext = context.get_extension(ERC20_APPROVAL_GAS_SPONSORING_KEY) + if isinstance(ext, Erc20ApprovalFacilitatorExtension): + extension_signer = ext.resolve_signer(str(payload.accepted.network)) + if extension_signer is not None: + reason, _msg = validate_erc20_approval_for_payment(erc20_info, payer, token_address) + if reason: + return VerifyResponse(is_valid=False, invalid_reason=reason, payer=payer) + return None # Valid ERC-20 approval extension + + return VerifyResponse( + is_valid=False, invalid_reason=ERR_PERMIT2_ALLOWANCE_REQUIRED, payer=payer + ) + + +def settle_permit2( + signer: FacilitatorEvmSigner, + payload: PaymentPayload, + requirements: PaymentRequirements, + context: FacilitatorContext | None = None, +) -> SettleResponse: + """Settle a Permit2 payment on-chain. + + Routes to the appropriate settlement path: + 1. EIP-2612 extension -> settleWithPermit (atomic single tx) + 2. ERC-20 approval extension -> send_transactions (approval + settle) + 3. Standard -> settle directly (allowance already on-chain) + + Args: + signer: Facilitator EVM signer for on-chain writes. + payload: Verified payment payload. + requirements: Payment requirements. + context: Optional facilitator context for extension lookup. + + Returns: + SettleResponse with success, transaction, and payer. + """ + from ....extensions.eip2612_gas_sponsoring import extract_eip2612_gas_sponsoring_info + from ....extensions.erc20_approval_gas_sponsoring import ( + ERC20_APPROVAL_GAS_SPONSORING_KEY, + Erc20ApprovalFacilitatorExtension, + extract_erc20_approval_gas_sponsoring_info, + ) + + permit2_payload = ExactPermit2Payload.from_dict(payload.payload) + payer = permit2_payload.permit2_authorization.from_address + network = str(requirements.network) + + # Re-verify before settling + verify_result = verify_permit2(signer, payload, requirements, context) + if not verify_result.is_valid: + return SettleResponse( + success=False, + error_reason=verify_result.invalid_reason, + network=network, + payer=payer, + transaction="", + ) + + # Branch: EIP-2612 gas sponsoring (atomic settleWithPermit) + eip2612_info = extract_eip2612_gas_sponsoring_info(payload) + if eip2612_info is not None: + return _settle_permit2_with_eip2612(signer, payload, permit2_payload, eip2612_info) + + # Branch: ERC-20 approval gas sponsoring (broadcast approval + settle) + erc20_info = extract_erc20_approval_gas_sponsoring_info(payload) + if erc20_info is not None and context is not None: + ext = context.get_extension(ERC20_APPROVAL_GAS_SPONSORING_KEY) + if isinstance(ext, Erc20ApprovalFacilitatorExtension): + extension_signer = ext.resolve_signer(str(payload.accepted.network)) + if extension_signer is not None: + return _settle_permit2_with_erc20_approval( + extension_signer, payload, permit2_payload, erc20_info + ) + + # Branch: standard settle (allowance already on-chain) + return _settle_permit2_direct(signer, payload, permit2_payload) + + +def _build_permit2_settle_args( + permit2_payload: ExactPermit2Payload, +) -> tuple: + """Build common settle call arguments from a Permit2 payload. + + Returns (permit_tuple, owner_addr, witness_tuple, sig_bytes). + """ + sig_bytes = hex_to_bytes(permit2_payload.signature or "") + permit_tuple = ( + ( + to_checksum_address(permit2_payload.permit2_authorization.permitted.token), + int(permit2_payload.permit2_authorization.permitted.amount), + ), + int(permit2_payload.permit2_authorization.nonce), + int(permit2_payload.permit2_authorization.deadline), + ) + owner_addr = to_checksum_address(permit2_payload.permit2_authorization.from_address) + witness_tuple = ( + to_checksum_address(permit2_payload.permit2_authorization.witness.to), + int(permit2_payload.permit2_authorization.witness.valid_after), + ) + return permit_tuple, owner_addr, witness_tuple, sig_bytes + + +def _settle_permit2_direct( + signer: FacilitatorEvmSigner, + payload: PaymentPayload, + permit2_payload: ExactPermit2Payload, +) -> SettleResponse: + """Standard Permit2 settle β€” allowance is already on-chain.""" + payer = permit2_payload.permit2_authorization.from_address + network = str(payload.accepted.network) + + try: + permit_tuple, owner_addr, witness_tuple, sig_bytes = _build_permit2_settle_args( + permit2_payload + ) + + tx_hash = signer.write_contract( + X402_EXACT_PERMIT2_PROXY_ADDRESS, + X402_EXACT_PERMIT2_PROXY_ABI, + "settle", + permit_tuple, + owner_addr, + witness_tuple, + sig_bytes, + ) + + receipt = signer.wait_for_transaction_receipt(tx_hash) + if receipt.status != TX_STATUS_SUCCESS: + return SettleResponse( + success=False, + error_reason=ERR_TRANSACTION_FAILED, + transaction=tx_hash, + network=network, + payer=payer, + ) + + return SettleResponse( + success=True, + transaction=tx_hash, + network=network, + payer=payer, + ) + + except Exception as e: + return _map_settle_error(e, network, payer) + + +def _settle_permit2_with_eip2612( + signer: FacilitatorEvmSigner, + payload: PaymentPayload, + permit2_payload: ExactPermit2Payload, + eip2612_info: Any, +) -> SettleResponse: + """Settle via settleWithPermit β€” includes the EIP-2612 permit atomically.""" + payer = permit2_payload.permit2_authorization.from_address + network = str(payload.accepted.network) + + try: + permit_tuple, owner_addr, witness_tuple, sig_bytes = _build_permit2_settle_args( + permit2_payload + ) + + sig_hex = eip2612_info.signature + sig_raw = hex_to_bytes(sig_hex) + if len(sig_raw) != 65: + return _map_settle_error( + ValueError("EIP-2612 signature must be 65 bytes"), network, payer + ) + r = sig_raw[:32] + s = sig_raw[32:64] + v = sig_raw[64] + + permit2612_tuple = ( + int(eip2612_info.amount), + int(eip2612_info.deadline), + r, + s, + v, + ) + + tx_hash = signer.write_contract( + X402_EXACT_PERMIT2_PROXY_ADDRESS, + X402_EXACT_PERMIT2_PROXY_SETTLE_WITH_PERMIT_ABI, + "settleWithPermit", + permit2612_tuple, + permit_tuple, + owner_addr, + witness_tuple, + sig_bytes, + ) + + receipt = signer.wait_for_transaction_receipt(tx_hash) + if receipt.status != TX_STATUS_SUCCESS: + return SettleResponse( + success=False, + error_reason=ERR_TRANSACTION_FAILED, + transaction=tx_hash, + network=network, + payer=payer, + ) + + return SettleResponse( + success=True, + transaction=tx_hash, + network=network, + payer=payer, + ) + + except Exception as e: + return _map_settle_error(e, network, payer) + + +def _settle_permit2_with_erc20_approval( + extension_signer: Any, + payload: PaymentPayload, + permit2_payload: ExactPermit2Payload, + erc20_info: Any, +) -> SettleResponse: + """Settle via extension signer's send_transactions (approval + settle).""" + payer = permit2_payload.permit2_authorization.from_address + network = str(payload.accepted.network) + + try: + permit_tuple, owner_addr, witness_tuple, sig_bytes = _build_permit2_settle_args( + permit2_payload + ) + + from ....extensions.erc20_approval_gas_sponsoring.types import WriteContractCall + + tx_hashes = extension_signer.send_transactions( + [ + erc20_info.signed_transaction, + WriteContractCall( + address=X402_EXACT_PERMIT2_PROXY_ADDRESS, + abi=X402_EXACT_PERMIT2_PROXY_ABI, + function="settle", + args=[permit_tuple, owner_addr, witness_tuple, sig_bytes], + ), + ] + ) + + settle_tx_hash = tx_hashes[-1] if tx_hashes else "" + receipt = extension_signer.wait_for_transaction_receipt(settle_tx_hash) + if receipt.status != TX_STATUS_SUCCESS: + return SettleResponse( + success=False, + error_reason=ERR_TRANSACTION_FAILED, + transaction=settle_tx_hash, + network=network, + payer=payer, + ) + + return SettleResponse( + success=True, + transaction=settle_tx_hash, + network=network, + payer=payer, + ) + + except Exception as e: + return _map_settle_error(e, network, payer) + + +def _map_settle_error(error: Exception, network: str, payer: str) -> SettleResponse: + """Map contract revert errors to structured SettleResponse.""" + error_msg = str(error) + error_reason = ERR_TRANSACTION_FAILED + if "Permit2612AmountMismatch" in error_msg: + error_reason = "permit2_2612_amount_mismatch" + elif "InvalidAmount" in error_msg: + error_reason = "invalid_permit2_amount" + elif "InvalidDestination" in error_msg: + error_reason = "invalid_permit2_destination" + elif "InvalidOwner" in error_msg: + error_reason = "invalid_permit2_owner" + elif "PaymentTooEarly" in error_msg: + error_reason = "permit2_payment_too_early" + elif "InvalidSignature" in error_msg or "SignatureExpired" in error_msg: + error_reason = ERR_PERMIT2_INVALID_SIGNATURE + elif "InvalidNonce" in error_msg: + error_reason = "permit2_invalid_nonce" + elif "erc20_approval_tx_failed" in error_msg: + error_reason = "erc20_approval_tx_failed" + + return SettleResponse( + success=False, + error_reason=error_reason, + error_message=error_msg[:500], + network=network, + payer=payer, + transaction="", + ) + + +def _build_permit2_typed_data( + permit2_authorization: ExactPermit2Authorization, + chain_id: int, +) -> tuple[dict[str, Any], dict[str, list[TypedDataField]], str, dict[str, Any]]: + """Build EIP-712 typed data components for Permit2 signature verification. + + Returns (domain_dict, types, primary_type, message) suitable for both + client signing and facilitator verification. + """ + domain_dict: dict[str, Any] = { + "name": "Permit2", + "chainId": chain_id, + "verifyingContract": PERMIT2_ADDRESS, + } + + message = { + "permitted": { + "token": permit2_authorization.permitted.token, + "amount": int(permit2_authorization.permitted.amount), + }, + "spender": permit2_authorization.spender, + "nonce": int(permit2_authorization.nonce), + "deadline": int(permit2_authorization.deadline), + "witness": { + "to": permit2_authorization.witness.to, + "validAfter": int(permit2_authorization.witness.valid_after), + }, + } + + typed_fields: dict[str, list[TypedDataField]] = { + type_name: [TypedDataField(name=f["name"], type=f["type"]) for f in fields] + for type_name, fields in PERMIT2_WITNESS_TYPES.items() + } + + return domain_dict, typed_fields, "PermitWitnessTransferFrom", message + + +def _verify_permit2_signature( + signer: FacilitatorEvmSigner, + payer: str, + permit2_authorization: ExactPermit2Authorization, + chain_id: int, + signature: bytes, +) -> bool: + """Verify a Permit2 EIP-712 signature. + + Delegates to signer.verify_typed_data which supports EOA, EIP-1271, + and ERC-6492 verification (matching TS/Go universal signature verification). + + Args: + signer: Facilitator signer with verify_typed_data capability. + payer: Expected signer address. + permit2_authorization: The authorization that was signed. + chain_id: Chain ID. + signature: Signature bytes. + + Returns: + True if signature is valid. + """ + domain_dict, typed_fields, primary_type, message = _build_permit2_typed_data( + permit2_authorization, chain_id + ) + + return signer.verify_typed_data( + payer, + domain_dict, # type: ignore[arg-type] + typed_fields, + primary_type, + message, + signature, + ) diff --git a/python/x402/mechanisms/evm/signer.py b/python/x402/mechanisms/evm/signer.py index 147155a2dc..948b2fef74 100644 --- a/python/x402/mechanisms/evm/signer.py +++ b/python/x402/mechanisms/evm/signer.py @@ -1,6 +1,6 @@ """EVM signer protocol definitions.""" -from typing import Any, Protocol +from typing import Any, Protocol, runtime_checkable from .types import TransactionReceipt, TypedDataDomain, TypedDataField @@ -176,3 +176,59 @@ def get_code(self, address: str) -> bytes: Bytecode (empty if EOA). """ ... + + +@runtime_checkable +class ClientEvmSignerWithReadContract(Protocol): + """Extension of ClientEvmSigner that adds on-chain read capability. + + Required for EIP-2612 gas sponsoring (needs to read nonces from token). + """ + + @property + def address(self) -> str: ... + + def sign_typed_data( + self, + domain: TypedDataDomain, + types: dict[str, list[TypedDataField]], + primary_type: str, + message: dict[str, Any], + ) -> bytes: ... + + def read_contract( + self, + address: str, + abi: list[dict[str, Any]], + function_name: str, + *args: Any, + ) -> Any: + """Read data from a smart contract.""" + ... + + +@runtime_checkable +class ClientEvmSignerWithSignTransaction(Protocol): + """Extension of ClientEvmSigner that adds raw transaction signing. + + Required for ERC-20 approval gas sponsoring (signs approve tx off-chain). + """ + + @property + def address(self) -> str: ... + + def sign_typed_data( + self, + domain: TypedDataDomain, + types: dict[str, list[TypedDataField]], + primary_type: str, + message: dict[str, Any], + ) -> bytes: ... + + def sign_transaction(self, tx: dict[str, Any]) -> str: + """Sign an EIP-1559 transaction and return the RLP-encoded hex string.""" + ... + + def get_transaction_count(self, address: str) -> int: + """Get the pending nonce for an address.""" + ... diff --git a/python/x402/mechanisms/evm/signers.py b/python/x402/mechanisms/evm/signers.py index 847b68032a..9774ecf8f5 100644 --- a/python/x402/mechanisms/evm/signers.py +++ b/python/x402/mechanisms/evm/signers.py @@ -6,8 +6,11 @@ from __future__ import annotations +import logging from typing import Any +logger = logging.getLogger("x402.signers") + try: from eth_account import Account from eth_account.messages import encode_typed_data @@ -19,8 +22,8 @@ "EVM signers require eth_account and web3. Install with: pip install x402[evm]" ) from e -from .constants import EIP1271_MAGIC_VALUE, IS_VALID_SIGNATURE_ABI, TX_STATUS_SUCCESS -from .types import TransactionReceipt, TypedDataDomain, TypedDataField +from .constants import EIP1271_MAGIC_VALUE, IS_VALID_SIGNATURE_ABI, TX_STATUS_SUCCESS # noqa: E402 +from .types import TransactionReceipt, TypedDataDomain, TypedDataField # noqa: E402 # ERC20 ABI for balance checks _ERC20_BALANCE_ABI = [ @@ -117,6 +120,14 @@ def sign_typed_data( else: domain_dict = domain + logger.info( + "EthAccountSigner.sign_typed_data: primaryType=%s domain_keys=%s type_names=%s", + primary_type, + list(domain_dict.keys()), + list(types_dict.keys()), + ) + logger.debug("EthAccountSigner.sign_typed_data: domain=%s message=%s", domain_dict, message) + # Sign typed data using eth_account signed = self._account.sign_typed_data( domain_data=domain_dict, @@ -126,6 +137,102 @@ def sign_typed_data( return bytes(signed.signature) +class EthAccountSignerWithRPC(EthAccountSigner): + """Client-side EVM signer with RPC capabilities for gas sponsoring extensions. + + Extends EthAccountSigner with read_contract, sign_transaction, and + get_transaction_count β€” the capabilities needed for EIP-2612 and + ERC-20 approval gas sponsoring. + + Equivalent to TS's toClientEvmSigner(account, publicClient). + + Example: + ```python + from eth_account import Account + from x402.mechanisms.evm.signers import EthAccountSignerWithRPC + + account = Account.from_key("0x...") + signer = EthAccountSignerWithRPC(account, rpc_url="https://sepolia.base.org") + + # Supports Permit2 with gas sponsoring extensions + from x402 import x402Client + from x402.mechanisms.evm.exact import register_exact_evm_client + + client = x402Client() + register_exact_evm_client(client, signer) + ``` + """ + + def __init__(self, account: LocalAccount, rpc_url: str) -> None: + """Initialize signer with eth_account LocalAccount and RPC connection. + + Args: + account: eth_account LocalAccount instance. + rpc_url: Ethereum RPC endpoint URL for on-chain reads. + """ + super().__init__(account) + self._w3 = Web3(Web3.HTTPProvider(rpc_url)) + + def read_contract( + self, + address: str, + abi: list[dict[str, Any]], + function_name: str, + *args: Any, + ) -> Any: + """Read data from a smart contract. + + Args: + address: Contract address. + abi: Contract ABI. + function_name: Function to call. + *args: Function arguments. + + Returns: + Function return value. + """ + contract = self._w3.eth.contract( + address=Web3.to_checksum_address(address), + abi=abi, + ) + return getattr(contract.functions, function_name)(*args).call() + + def sign_transaction(self, tx: dict[str, Any]) -> str: + """Sign an EIP-1559 transaction and return the RLP-encoded hex string. + + Args: + tx: Transaction dict with fields like to, data, nonce, gas, etc. + + Returns: + Hex-encoded signed transaction with 0x prefix. + """ + signed = self._w3.eth.account.sign_transaction(tx, self._account.key) + return "0x" + signed.raw_transaction.hex() + + def get_transaction_count(self, address: str) -> int: + """Get the pending nonce for an address. + + Args: + address: Account address. + + Returns: + Pending transaction count. + """ + return self._w3.eth.get_transaction_count(Web3.to_checksum_address(address)) + + def estimate_fees_per_gas(self) -> tuple[int, int]: + """Estimate EIP-1559 fee parameters from the network. + + Returns: + Tuple of (maxFeePerGas, maxPriorityFeePerGas) in wei. + """ + latest = self._w3.eth.get_block("latest") + base_fee = latest.get("baseFeePerGas", 1_000_000_000) + max_priority_fee = self._w3.eth.max_priority_fee + max_fee = base_fee * 2 + max_priority_fee + return (max_fee, max_priority_fee) + + class FacilitatorWeb3Signer: """Facilitator-side EVM signer using web3.py. @@ -248,14 +355,30 @@ def verify_typed_data( Returns: True if signature is valid. """ - # Build full types including EIP712Domain + # Build domain dict β€” handle both TypedDataDomain and raw dict (Permit2 has no version) + if isinstance(domain, dict): + domain_dict = domain + else: + domain_dict = { + "name": domain.name, + "chainId": domain.chain_id, + "verifyingContract": domain.verifying_contract, + } + if domain.version: + domain_dict["version"] = domain.version + + # Derive EIP712Domain type from actual domain keys + domain_field_map = { + "name": {"name": "name", "type": "string"}, + "version": {"name": "version", "type": "string"}, + "chainId": {"name": "chainId", "type": "uint256"}, + "verifyingContract": {"name": "verifyingContract", "type": "address"}, + "salt": {"name": "salt", "type": "bytes32"}, + } + eip712_domain_type = [domain_field_map[k] for k in domain_dict if k in domain_field_map] + full_types: dict[str, list[dict[str, str]]] = { - "EIP712Domain": [ - {"name": "name", "type": "string"}, - {"name": "version", "type": "string"}, - {"name": "chainId", "type": "uint256"}, - {"name": "verifyingContract", "type": "address"}, - ] + "EIP712Domain": eip712_domain_type, } for type_name, fields in types.items(): full_types[type_name] = [ @@ -272,19 +395,27 @@ def verify_typed_data( typed_data = { "types": full_types, "primaryType": primary_type, - "domain": { - "name": domain.name, - "version": domain.version, - "chainId": domain.chain_id, - "verifyingContract": domain.verifying_contract, - }, + "domain": domain_dict, "message": msg_copy, } + logger.info( + "verify_typed_data: primaryType=%s domain_keys=%s type_names=%s", + primary_type, + list(domain_dict.keys()), + list(full_types.keys()), + ) + logger.debug("verify_typed_data: full typed_data=%s", typed_data) + # Try EOA signature verification first - recovered = Account.recover_message( - encode_typed_data(full_message=typed_data), - signature=signature, + signable = encode_typed_data(full_message=typed_data) + recovered = Account.recover_message(signable, signature=signature) + + logger.info( + "verify_typed_data: expected=%s recovered=%s match=%s", + address.lower(), + recovered.lower(), + recovered.lower() == address.lower(), ) if recovered.lower() == address.lower(): @@ -313,7 +444,7 @@ def verify_typed_data( return False except Exception as e: - print(f"Signature verification error: {e}") + logger.error("Signature verification error: %s", e, exc_info=True) return False def write_contract( diff --git a/python/x402/mechanisms/evm/types.py b/python/x402/mechanisms/evm/types.py index e6d18f557a..39c66a281c 100644 --- a/python/x402/mechanisms/evm/types.py +++ b/python/x402/mechanisms/evm/types.py @@ -72,6 +72,123 @@ def from_dict(cls, data: dict[str, Any]) -> "ExactEIP3009Payload": ExactEvmPayloadV2 = ExactEIP3009Payload +@dataclass +class ExactPermit2Witness: + """Witness data for Permit2 PermitWitnessTransferFrom.""" + + to: str # Recipient address + valid_after: str # Unix timestamp as string (lower time bound) + + +@dataclass +class ExactPermit2TokenPermissions: + """Token permissions for Permit2.""" + + token: str # ERC-20 token address + amount: str # Amount in smallest unit as string + + +@dataclass +class ExactPermit2Authorization: + """Permit2 PermitWitnessTransferFrom data.""" + + from_address: str # 'from' field (payer address) + permitted: ExactPermit2TokenPermissions + spender: str # x402ExactPermit2Proxy address + nonce: str # Random uint256 as decimal string + deadline: str # Unix timestamp as string (upper time bound) + witness: ExactPermit2Witness + + +@dataclass +class ExactPermit2Payload: + """Exact payment payload for Permit2 flow.""" + + permit2_authorization: ExactPermit2Authorization + signature: str | None = None + + def to_dict(self) -> dict[str, Any]: + """Convert to dictionary for JSON serialization. + + Returns: + Dict with permit2Authorization and signature fields. + """ + result: dict[str, Any] = { + "permit2Authorization": { + "from": self.permit2_authorization.from_address, + "permitted": { + "token": self.permit2_authorization.permitted.token, + "amount": self.permit2_authorization.permitted.amount, + }, + "spender": self.permit2_authorization.spender, + "nonce": self.permit2_authorization.nonce, + "deadline": self.permit2_authorization.deadline, + "witness": { + "to": self.permit2_authorization.witness.to, + "validAfter": self.permit2_authorization.witness.valid_after, + }, + } + } + if self.signature: + result["signature"] = self.signature + return result + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> "ExactPermit2Payload": + """Create from dictionary. + + Args: + data: Dict with permit2Authorization and optional signature. + + Returns: + ExactPermit2Payload instance. + """ + auth = data.get("permit2Authorization", {}) + permitted = auth.get("permitted", {}) + witness = auth.get("witness", {}) + return cls( + permit2_authorization=ExactPermit2Authorization( + from_address=auth.get("from", ""), + permitted=ExactPermit2TokenPermissions( + token=permitted.get("token", ""), + amount=permitted.get("amount", ""), + ), + spender=auth.get("spender", ""), + nonce=auth.get("nonce", ""), + deadline=auth.get("deadline", ""), + witness=ExactPermit2Witness( + to=witness.get("to", ""), + valid_after=witness.get("validAfter", ""), + ), + ), + signature=data.get("signature"), + ) + + +def is_permit2_payload(payload: dict[str, Any]) -> bool: + """Check if a raw payload dict is a Permit2 payload. + + Args: + payload: Raw payload dictionary. + + Returns: + True if the payload contains permit2Authorization key. + """ + return "permit2Authorization" in payload + + +def is_eip3009_payload(payload: dict[str, Any]) -> bool: + """Check if a raw payload dict is an EIP-3009 payload. + + Args: + payload: Raw payload dictionary. + + Returns: + True if the payload contains authorization key. + """ + return "authorization" in payload + + @dataclass class TypedDataDomain: """EIP-712 domain separator.""" diff --git a/python/x402/mechanisms/evm/utils.py b/python/x402/mechanisms/evm/utils.py index 223ca528d4..1d29cc2580 100644 --- a/python/x402/mechanisms/evm/utils.py +++ b/python/x402/mechanisms/evm/utils.py @@ -121,6 +121,18 @@ def create_nonce() -> str: return "0x" + os.urandom(32).hex() +def create_permit2_nonce() -> str: + """Generate random uint256 nonce as decimal string for Permit2. + + Permit2 uses uint256 nonces (not bytes32), so the nonce is returned + as a decimal string rather than a hex string. + + Returns: + Decimal string representation of a random uint256. + """ + return str(int.from_bytes(os.urandom(32), "big")) + + def normalize_address(address: str) -> str: """Normalize Ethereum address to checksummed format. diff --git a/python/x402/tests/unit/extensions/__init__.py b/python/x402/tests/unit/extensions/__init__.py index 2a219f87ea..e69de29bb2 100644 --- a/python/x402/tests/unit/extensions/__init__.py +++ b/python/x402/tests/unit/extensions/__init__.py @@ -1 +0,0 @@ -"""Unit tests for x402 extensions.""" diff --git a/python/x402/tests/unit/extensions/test_eip2612_gas_sponsoring.py b/python/x402/tests/unit/extensions/test_eip2612_gas_sponsoring.py new file mode 100644 index 0000000000..b4a6909a94 --- /dev/null +++ b/python/x402/tests/unit/extensions/test_eip2612_gas_sponsoring.py @@ -0,0 +1,143 @@ +"""Tests for the EIP-2612 Gas Sponsoring extension.""" + +from __future__ import annotations + +import time +from typing import Any + +from x402.extensions.eip2612_gas_sponsoring import ( + EIP2612_GAS_SPONSORING_KEY, + Eip2612GasSponsoringInfo, + declare_eip2612_gas_sponsoring_extension, + extract_eip2612_gas_sponsoring_info, + validate_eip2612_gas_sponsoring_info, + validate_eip2612_permit_for_payment, +) +from x402.mechanisms.evm.constants import PERMIT2_ADDRESS +from x402.schemas import PaymentPayload, PaymentRequirements, ResourceInfo + +TOKEN_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e" +PAYER = "0x1234567890123456789012345678901234567890" + + +def _make_info(**overrides: Any) -> Eip2612GasSponsoringInfo: + defaults = { + "from_address": PAYER, + "asset": TOKEN_ADDRESS, + "spender": PERMIT2_ADDRESS, + "amount": str(2**256 - 1), + "nonce": "0", + "deadline": str(int(time.time()) + 3600), + "signature": "0x" + "aa" * 65, + "version": "1", + } + defaults.update(overrides) + return Eip2612GasSponsoringInfo(**defaults) + + +def _make_payload(info: Eip2612GasSponsoringInfo | None = None) -> PaymentPayload: + ext = {} + if info is not None: + ext = {EIP2612_GAS_SPONSORING_KEY: {"info": info.to_dict()}} + return PaymentPayload( + x402_version=2, + resource=ResourceInfo(url="http://example.com", description="test", mime_type="text"), + accepted=PaymentRequirements( + scheme="exact", + network="eip155:84532", + asset=TOKEN_ADDRESS, + amount="1000", + pay_to="0x0987654321098765432109876543210987654321", + max_timeout_seconds=3600, + extra={"assetTransferMethod": "permit2"}, + ), + payload={"permit2Authorization": {"from": PAYER}}, + extensions=ext, + ) + + +class TestDeclaration: + def test_declare_returns_correct_key(self): + result = declare_eip2612_gas_sponsoring_extension() + assert EIP2612_GAS_SPONSORING_KEY in result + ext = result[EIP2612_GAS_SPONSORING_KEY] + assert "info" in ext + assert "schema" in ext + assert ext["info"]["version"] == "1" + + +class TestSerialization: + def test_roundtrip(self): + info = _make_info() + d = info.to_dict() + restored = Eip2612GasSponsoringInfo.from_dict(d) + assert restored.from_address == info.from_address + assert restored.asset == info.asset + assert restored.spender == info.spender + assert restored.amount == info.amount + assert restored.nonce == info.nonce + assert restored.deadline == info.deadline + assert restored.signature == info.signature + assert restored.version == info.version + + def test_to_dict_uses_camel_case(self): + info = _make_info() + d = info.to_dict() + assert "from" in d + assert "from_address" not in d + + +class TestExtraction: + def test_extract_from_payload(self): + info = _make_info() + payload = _make_payload(info) + result = extract_eip2612_gas_sponsoring_info(payload) + assert result is not None + assert result.from_address == PAYER + + def test_extract_returns_none_when_missing(self): + payload = _make_payload(None) + result = extract_eip2612_gas_sponsoring_info(payload) + assert result is None + + +class TestValidation: + def test_valid_info(self): + info = _make_info() + assert validate_eip2612_gas_sponsoring_info(info) is True + + def test_invalid_address(self): + info = _make_info(from_address="not-an-address") + assert validate_eip2612_gas_sponsoring_info(info) is False + + def test_invalid_amount(self): + info = _make_info(amount="abc") + assert validate_eip2612_gas_sponsoring_info(info) is False + + +class TestPaymentValidation: + def test_valid_permit(self): + info = _make_info() + assert validate_eip2612_permit_for_payment(info, PAYER, TOKEN_ADDRESS) == "" + + def test_from_mismatch(self): + info = _make_info() + assert "from_mismatch" in validate_eip2612_permit_for_payment( + info, "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", TOKEN_ADDRESS + ) + + def test_asset_mismatch(self): + info = _make_info() + assert "asset_mismatch" in validate_eip2612_permit_for_payment( + info, PAYER, "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + ) + + def test_spender_not_permit2(self): + info = _make_info(spender="0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") + assert "spender_not_permit2" in validate_eip2612_permit_for_payment( + info, PAYER, TOKEN_ADDRESS + ) + + def test_expired_deadline(self): + info = _make_info(deadline=str(int(time.time()) - 100)) + assert "deadline_expired" in validate_eip2612_permit_for_payment(info, PAYER, TOKEN_ADDRESS) diff --git a/python/x402/tests/unit/extensions/test_erc20_approval_gas_sponsoring.py b/python/x402/tests/unit/extensions/test_erc20_approval_gas_sponsoring.py new file mode 100644 index 0000000000..82ce5eaf1a --- /dev/null +++ b/python/x402/tests/unit/extensions/test_erc20_approval_gas_sponsoring.py @@ -0,0 +1,111 @@ +"""Tests for the ERC-20 Approval Gas Sponsoring extension.""" + +from __future__ import annotations + +from typing import Any + +from x402.extensions.erc20_approval_gas_sponsoring import ( + ERC20_APPROVAL_GAS_SPONSORING_KEY, + Erc20ApprovalGasSponsoringInfo, + declare_erc20_approval_gas_sponsoring_extension, + extract_erc20_approval_gas_sponsoring_info, + validate_erc20_approval_gas_sponsoring_info, +) +from x402.mechanisms.evm.constants import PERMIT2_ADDRESS +from x402.schemas import PaymentPayload, PaymentRequirements, ResourceInfo + +TOKEN_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e" +PAYER = "0x1234567890123456789012345678901234567890" + + +def _make_info(**overrides: Any) -> Erc20ApprovalGasSponsoringInfo: + defaults = { + "from_address": PAYER, + "asset": TOKEN_ADDRESS, + "spender": PERMIT2_ADDRESS, + "amount": str(2**256 - 1), + "signed_transaction": "0x" + "ff" * 100, + "version": "1", + } + defaults.update(overrides) + return Erc20ApprovalGasSponsoringInfo(**defaults) + + +def _make_payload(info: Erc20ApprovalGasSponsoringInfo | None = None) -> PaymentPayload: + ext = {} + if info is not None: + ext = {ERC20_APPROVAL_GAS_SPONSORING_KEY: {"info": info.to_dict()}} + return PaymentPayload( + x402_version=2, + resource=ResourceInfo(url="http://example.com", description="test", mime_type="text"), + accepted=PaymentRequirements( + scheme="exact", + network="eip155:84532", + asset=TOKEN_ADDRESS, + amount="1000", + pay_to="0x0987654321098765432109876543210987654321", + max_timeout_seconds=3600, + extra={"assetTransferMethod": "permit2"}, + ), + payload={"permit2Authorization": {"from": PAYER}}, + extensions=ext, + ) + + +class TestDeclaration: + def test_declare_returns_correct_key(self): + result = declare_erc20_approval_gas_sponsoring_extension() + assert ERC20_APPROVAL_GAS_SPONSORING_KEY in result + ext = result[ERC20_APPROVAL_GAS_SPONSORING_KEY] + assert "info" in ext + assert "schema" in ext + assert ext["info"]["version"] == "1" + + +class TestSerialization: + def test_roundtrip(self): + info = _make_info() + d = info.to_dict() + restored = Erc20ApprovalGasSponsoringInfo.from_dict(d) + assert restored.from_address == info.from_address + assert restored.asset == info.asset + assert restored.spender == info.spender + assert restored.amount == info.amount + assert restored.signed_transaction == info.signed_transaction + assert restored.version == info.version + + def test_to_dict_uses_camel_case(self): + info = _make_info() + d = info.to_dict() + assert "from" in d + assert "signedTransaction" in d + assert "from_address" not in d + assert "signed_transaction" not in d + + +class TestExtraction: + def test_extract_from_payload(self): + info = _make_info() + payload = _make_payload(info) + result = extract_erc20_approval_gas_sponsoring_info(payload) + assert result is not None + assert result.from_address == PAYER + + def test_extract_returns_none_when_missing(self): + payload = _make_payload(None) + result = extract_erc20_approval_gas_sponsoring_info(payload) + assert result is None + + +class TestValidation: + def test_valid_info(self): + info = _make_info() + assert validate_erc20_approval_gas_sponsoring_info(info) is True + + def test_invalid_address(self): + info = _make_info(from_address="not-an-address") + assert validate_erc20_approval_gas_sponsoring_info(info) is False + + def test_invalid_signed_transaction(self): + info = _make_info(signed_transaction="not-hex") + assert validate_erc20_approval_gas_sponsoring_info(info) is False diff --git a/python/x402/tests/unit/mechanisms/evm/test_permit2.py b/python/x402/tests/unit/mechanisms/evm/test_permit2.py new file mode 100644 index 0000000000..1f573886e9 --- /dev/null +++ b/python/x402/tests/unit/mechanisms/evm/test_permit2.py @@ -0,0 +1,609 @@ +"""Tests for the Permit2 payment flow in the exact EVM scheme.""" + +from __future__ import annotations + +import time +from typing import Any +from unittest.mock import MagicMock, patch + +from x402.mechanisms.evm.constants import ( + ERR_INSUFFICIENT_BALANCE, + ERR_NETWORK_MISMATCH, + ERR_PERMIT2_ALLOWANCE_REQUIRED, + ERR_PERMIT2_AMOUNT_MISMATCH, + ERR_PERMIT2_DEADLINE_EXPIRED, + ERR_PERMIT2_INVALID_SIGNATURE, + ERR_PERMIT2_INVALID_SPENDER, + ERR_PERMIT2_NOT_YET_VALID, + ERR_PERMIT2_RECIPIENT_MISMATCH, + ERR_PERMIT2_TOKEN_MISMATCH, + ERR_UNSUPPORTED_SCHEME, + X402_EXACT_PERMIT2_PROXY_ADDRESS, +) +from x402.mechanisms.evm.exact import ExactEvmClientScheme, ExactEvmFacilitatorScheme +from x402.mechanisms.evm.types import ( + ExactPermit2Authorization, + ExactPermit2Payload, + ExactPermit2TokenPermissions, + ExactPermit2Witness, + TransactionReceipt, + is_permit2_payload, +) +from x402.schemas import PaymentPayload, PaymentRequirements, ResourceInfo + +NETWORK = "eip155:84532" # Base Sepolia +TOKEN_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e" +PAYER = "0x1234567890123456789012345678901234567890" +RECIPIENT = "0x0987654321098765432109876543210987654321" +FACILITATOR = "0x1111111111111111111111111111111111111111" +AMOUNT = "1000" + + +def make_permit2_authorization( + *, + from_address: str = PAYER, + token: str = TOKEN_ADDRESS, + amount: str = AMOUNT, + spender: str = X402_EXACT_PERMIT2_PROXY_ADDRESS, + nonce: str = "12345678901234567890", + deadline_offset: int = 3600, + valid_after_offset: int = -600, + witness_to: str = RECIPIENT, +) -> ExactPermit2Authorization: + now = int(time.time()) + return ExactPermit2Authorization( + from_address=from_address, + permitted=ExactPermit2TokenPermissions(token=token, amount=amount), + spender=spender, + nonce=nonce, + deadline=str(now + deadline_offset), + witness=ExactPermit2Witness( + to=witness_to, + valid_after=str(now + valid_after_offset), + ), + ) + + +def make_permit2_payload_dict( + auth: ExactPermit2Authorization | None = None, + signature: str = "0x" + "aa" * 65, +) -> dict[str, Any]: + if auth is None: + auth = make_permit2_authorization() + payload = ExactPermit2Payload(permit2_authorization=auth, signature=signature) + return payload.to_dict() + + +def make_payment_payload( + *, + payload_dict: dict[str, Any] | None = None, + accepted_scheme: str = "exact", + accepted_network: str = NETWORK, + pay_to: str = RECIPIENT, + amount: str = AMOUNT, +) -> PaymentPayload: + if payload_dict is None: + payload_dict = make_permit2_payload_dict() + return PaymentPayload( + x402_version=2, + resource=ResourceInfo( + url="http://example.com/protected-permit2", + description="Test resource", + mime_type="application/json", + ), + accepted=PaymentRequirements( + scheme=accepted_scheme, + network=accepted_network, + asset=TOKEN_ADDRESS, + amount=amount, + pay_to=pay_to, + max_timeout_seconds=3600, + extra={"assetTransferMethod": "permit2"}, + ), + payload=payload_dict, + ) + + +def make_requirements( + *, + scheme: str = "exact", + network: str = NETWORK, + amount: str = AMOUNT, + pay_to: str = RECIPIENT, +) -> PaymentRequirements: + return PaymentRequirements( + scheme=scheme, + network=network, + asset=TOKEN_ADDRESS, + amount=amount, + pay_to=pay_to, + max_timeout_seconds=3600, + extra={"assetTransferMethod": "permit2"}, + ) + + +class MockFacilitatorSigner: + """Mock signer for permit2 facilitator tests.""" + + def __init__( + self, + *, + sig_valid: bool = True, + allowance: int = int(AMOUNT) * 2, + balance: int = int(AMOUNT) * 10, + tx_success: bool = True, + ): + self._sig_valid = sig_valid + self._allowance = allowance + self._balance = balance + self._tx_success = tx_success + self.write_calls: list[tuple] = [] + + def get_addresses(self) -> list[str]: + return [FACILITATOR] + + def read_contract(self, address: str, abi: list[dict], function_name: str, *args) -> Any: + if function_name == "allowance": + return self._allowance + if function_name == "balanceOf": + return self._balance + raise AssertionError(f"unexpected read_contract: {function_name}") + + def verify_typed_data(self, *args: Any, **kwargs: Any) -> bool: + return self._sig_valid + + def write_contract(self, address: str, abi: list[dict], function_name: str, *args) -> str: + self.write_calls.append((address, function_name, args)) + return "0x" + "ab" * 32 + + def send_transaction(self, to: str, data: bytes) -> str: + return "0x" + "cd" * 32 + + def wait_for_transaction_receipt(self, tx_hash: str) -> TransactionReceipt: + status = 1 if self._tx_success else 0 + return TransactionReceipt(status=status, block_number=1, tx_hash=tx_hash) + + def get_balance(self, address: str, token_address: str) -> int: + return self._balance + + def get_chain_id(self) -> int: + return 84532 + + def get_code(self, address: str) -> bytes: + return b"" + + +# ============================================================================ +# Type detection tests +# ============================================================================ + + +class TestIsPermit2Payload: + def test_detects_permit2_payload(self): + payload = make_permit2_payload_dict() + assert is_permit2_payload(payload) is True + + def test_rejects_eip3009_payload(self): + payload = {"authorization": {"from": PAYER}, "signature": "0x"} + assert is_permit2_payload(payload) is False + + def test_rejects_empty_dict(self): + assert is_permit2_payload({}) is False + + +# ============================================================================ +# ExactPermit2Payload serialization +# ============================================================================ + + +class TestExactPermit2PayloadSerialization: + def test_to_dict_and_from_dict_roundtrip(self): + auth = make_permit2_authorization() + original = ExactPermit2Payload(permit2_authorization=auth, signature="0x" + "ff" * 65) + + d = original.to_dict() + restored = ExactPermit2Payload.from_dict(d) + + assert restored.permit2_authorization.from_address == auth.from_address + assert restored.permit2_authorization.spender == auth.spender + assert restored.permit2_authorization.nonce == auth.nonce + assert restored.permit2_authorization.deadline == auth.deadline + assert restored.permit2_authorization.permitted.token == auth.permitted.token + assert restored.permit2_authorization.permitted.amount == auth.permitted.amount + assert restored.permit2_authorization.witness.to == auth.witness.to + assert restored.permit2_authorization.witness.valid_after == auth.witness.valid_after + assert restored.signature == original.signature + + def test_to_dict_keys_are_camel_case(self): + auth = make_permit2_authorization() + payload = ExactPermit2Payload(permit2_authorization=auth, signature="0xsig") + d = payload.to_dict() + + assert "permit2Authorization" in d + p2 = d["permit2Authorization"] + assert "from" in p2 + assert "permitted" in p2 + assert "spender" in p2 + assert "nonce" in p2 + assert "deadline" in p2 + assert "witness" in p2 + assert "to" in p2["witness"] + assert "validAfter" in p2["witness"] + + +# ============================================================================ +# Facilitator verify_permit2 tests +# ============================================================================ + + +class TestVerifyPermit2: + def _make_facilitator(self, **kwargs) -> ExactEvmFacilitatorScheme: + signer = MockFacilitatorSigner(**kwargs) + return ExactEvmFacilitatorScheme(signer) + + def _verify(self, facilitator: ExactEvmFacilitatorScheme, **payload_kwargs): + payload = make_payment_payload(**payload_kwargs) + requirements = make_requirements() + return facilitator.verify(payload, requirements) + + def test_verify_accepts_valid_payment(self): + facilitator = self._make_facilitator(sig_valid=True) + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = self._verify(facilitator) + assert result.is_valid is True + assert result.payer == PAYER + + def test_verify_rejects_wrong_scheme(self): + facilitator = self._make_facilitator() + payload = make_payment_payload(accepted_scheme="upto") + requirements = make_requirements() + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_UNSUPPORTED_SCHEME + + def test_verify_rejects_network_mismatch(self): + facilitator = self._make_facilitator() + payload = make_payment_payload(accepted_network="eip155:8453") + requirements = make_requirements(network="eip155:84532") + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_NETWORK_MISMATCH + + def test_verify_rejects_invalid_spender(self): + facilitator = self._make_facilitator() + auth = make_permit2_authorization(spender="0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") + payload = make_payment_payload(payload_dict=make_permit2_payload_dict(auth)) + requirements = make_requirements() + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_INVALID_SPENDER + + def test_verify_rejects_recipient_mismatch(self): + facilitator = self._make_facilitator() + wrong_recipient = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + auth = make_permit2_authorization(witness_to=wrong_recipient) + payload = make_payment_payload(payload_dict=make_permit2_payload_dict(auth)) + requirements = make_requirements(pay_to=RECIPIENT) + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_RECIPIENT_MISMATCH + + def test_verify_rejects_expired_deadline(self): + facilitator = self._make_facilitator() + auth = make_permit2_authorization(deadline_offset=-100) # expired + payload = make_payment_payload(payload_dict=make_permit2_payload_dict(auth)) + requirements = make_requirements() + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_DEADLINE_EXPIRED + + def test_verify_rejects_valid_after_in_future(self): + facilitator = self._make_facilitator() + auth = make_permit2_authorization(valid_after_offset=3600) # 1 hour from now + payload = make_payment_payload(payload_dict=make_permit2_payload_dict(auth)) + requirements = make_requirements() + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_NOT_YET_VALID + + def test_verify_rejects_amount_mismatch(self): + facilitator = self._make_facilitator() + auth = make_permit2_authorization(amount="999") # wrong amount + payload = make_payment_payload(payload_dict=make_permit2_payload_dict(auth)) + requirements = make_requirements(amount=AMOUNT) + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_AMOUNT_MISMATCH + + def test_verify_rejects_token_mismatch(self): + facilitator = self._make_facilitator() + wrong_token = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + auth = make_permit2_authorization(token=wrong_token) + payload = make_payment_payload(payload_dict=make_permit2_payload_dict(auth)) + requirements = make_requirements() + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_TOKEN_MISMATCH + + def test_verify_rejects_invalid_signature(self): + facilitator = self._make_facilitator() + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=False, + ): + result = self._verify(facilitator) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_INVALID_SIGNATURE + + def test_verify_rejects_missing_signature(self): + facilitator = self._make_facilitator() + auth = make_permit2_authorization() + payload_dict = ExactPermit2Payload(permit2_authorization=auth, signature=None).to_dict() + payload = make_payment_payload(payload_dict=payload_dict) + requirements = make_requirements() + result = facilitator.verify(payload, requirements) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_INVALID_SIGNATURE + + def test_verify_rejects_insufficient_allowance(self): + facilitator = self._make_facilitator(allowance=0) + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = self._verify(facilitator) + assert result.is_valid is False + assert result.invalid_reason == ERR_PERMIT2_ALLOWANCE_REQUIRED + + def test_verify_rejects_insufficient_balance(self): + facilitator = self._make_facilitator(allowance=int(AMOUNT) * 10, balance=0) + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = self._verify(facilitator) + assert result.is_valid is False + assert result.invalid_reason == ERR_INSUFFICIENT_BALANCE + + +# ============================================================================ +# Facilitator settle_permit2 tests +# ============================================================================ + + +class TestSettlePermit2: + def _make_facilitator(self, **kwargs) -> ExactEvmFacilitatorScheme: + signer = MockFacilitatorSigner(**kwargs) + return ExactEvmFacilitatorScheme(signer) + + def test_settle_calls_proxy_contract(self): + signer = MockFacilitatorSigner(sig_valid=True) + facilitator = ExactEvmFacilitatorScheme(signer) + payload = make_payment_payload() + requirements = make_requirements() + + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = facilitator.settle(payload, requirements) + + assert result.success is True + assert len(signer.write_calls) == 1 + address, function_name, _ = signer.write_calls[0] + assert address == X402_EXACT_PERMIT2_PROXY_ADDRESS + assert function_name == "settle" + + def test_settle_returns_transaction_hash(self): + signer = MockFacilitatorSigner() + facilitator = ExactEvmFacilitatorScheme(signer) + payload = make_payment_payload() + requirements = make_requirements() + + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = facilitator.settle(payload, requirements) + + assert result.success is True + assert result.transaction is not None + assert len(result.transaction) > 0 + + def test_settle_fails_if_verify_fails(self): + facilitator = self._make_facilitator(allowance=0) + payload = make_payment_payload() + requirements = make_requirements() + result = facilitator.settle(payload, requirements) + assert result.success is False + + def test_settle_fails_on_transaction_failure(self): + signer = MockFacilitatorSigner(tx_success=False) + facilitator = ExactEvmFacilitatorScheme(signer) + payload = make_payment_payload() + requirements = make_requirements() + + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = facilitator.settle(payload, requirements) + + assert result.success is False + + +# ============================================================================ +# Client routing tests +# ============================================================================ + + +class TestClientPermit2Routing: + def test_routes_to_permit2_when_asset_transfer_method_is_permit2(self): + mock_signer = MagicMock() + mock_signer.address = PAYER + mock_signer.sign_typed_data.return_value = b"\x00" * 65 + + client_scheme = ExactEvmClientScheme(mock_signer) + requirements = make_requirements() + + result = client_scheme.create_payment_payload(requirements) + + assert "permit2Authorization" in result + assert "authorization" not in result + assert result["permit2Authorization"]["from"] == PAYER + assert result["permit2Authorization"]["spender"] == X402_EXACT_PERMIT2_PROXY_ADDRESS + + def test_routes_to_eip3009_when_no_asset_transfer_method(self): + mock_signer = MagicMock() + mock_signer.address = PAYER + mock_signer.sign_typed_data.return_value = b"\x00" * 65 + + client_scheme = ExactEvmClientScheme(mock_signer) + requirements = PaymentRequirements( + scheme="exact", + network=NETWORK, + asset=TOKEN_ADDRESS, + amount=AMOUNT, + pay_to=RECIPIENT, + max_timeout_seconds=3600, + extra={"name": "USD Coin", "version": "2"}, + ) + + result = client_scheme.create_payment_payload(requirements) + + assert "authorization" in result + assert "permit2Authorization" not in result + + def test_permit2_payload_has_correct_structure(self): + mock_signer = MagicMock() + mock_signer.address = PAYER + mock_signer.sign_typed_data.return_value = b"\xff" * 65 + + client_scheme = ExactEvmClientScheme(mock_signer) + requirements = make_requirements() + + result = client_scheme.create_payment_payload(requirements) + + p2 = result["permit2Authorization"] + assert p2["from"] == PAYER + assert p2["spender"] == X402_EXACT_PERMIT2_PROXY_ADDRESS + assert p2["witness"]["to"] == RECIPIENT + assert "nonce" in p2 + assert "deadline" in p2 + assert "permitted" in p2 + assert p2["permitted"]["token"] == "0x036CbD53842c5426634e7929541eC2318f3dCF7e" + assert p2["permitted"]["amount"] == AMOUNT + + +# ============================================================================ +# Extension-aware verify tests +# ============================================================================ + + +class TestVerifyPermit2WithExtensions: + """Tests for verify_permit2 with gas sponsoring extension fallbacks.""" + + def _make_facilitator(self, **kwargs) -> ExactEvmFacilitatorScheme: + signer = MockFacilitatorSigner(**kwargs) + return ExactEvmFacilitatorScheme(signer) + + def test_verify_accepts_with_eip2612_extension_when_allowance_insufficient(self): + """When allowance is 0 but valid EIP-2612 extension is present, verify passes.""" + from x402.extensions.eip2612_gas_sponsoring import EIP2612_GAS_SPONSORING_KEY + from x402.mechanisms.evm.constants import PERMIT2_ADDRESS + + facilitator = self._make_facilitator(allowance=0, sig_valid=True) + + now = int(time.time()) + eip2612_info = { + "from": PAYER, + "asset": TOKEN_ADDRESS, + "spender": PERMIT2_ADDRESS, + "amount": str(2**256 - 1), + "nonce": "0", + "deadline": str(now + 3600), + "signature": "0x" + "aa" * 65, + "version": "1", + } + + payload_dict = make_permit2_payload_dict() + payload = PaymentPayload( + x402_version=2, + resource=ResourceInfo( + url="http://example.com/test", + description="Test", + mime_type="application/json", + ), + accepted=PaymentRequirements( + scheme="exact", + network=NETWORK, + asset=TOKEN_ADDRESS, + amount=AMOUNT, + pay_to=RECIPIENT, + max_timeout_seconds=3600, + extra={"assetTransferMethod": "permit2"}, + ), + payload=payload_dict, + extensions={EIP2612_GAS_SPONSORING_KEY: {"info": eip2612_info}}, + ) + requirements = make_requirements() + + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = facilitator.verify(payload, requirements) + + assert result.is_valid is True + + def test_verify_rejects_with_invalid_eip2612_extension(self): + """When allowance is 0 and EIP-2612 extension has wrong spender, verify fails.""" + from x402.extensions.eip2612_gas_sponsoring import EIP2612_GAS_SPONSORING_KEY + + facilitator = self._make_facilitator(allowance=0, sig_valid=True) + + now = int(time.time()) + eip2612_info = { + "from": PAYER, + "asset": TOKEN_ADDRESS, + "spender": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", + "amount": str(2**256 - 1), + "nonce": "0", + "deadline": str(now + 3600), + "signature": "0x" + "aa" * 65, + "version": "1", + } + + payload_dict = make_permit2_payload_dict() + payload = PaymentPayload( + x402_version=2, + resource=ResourceInfo( + url="http://example.com/test", + description="Test", + mime_type="application/json", + ), + accepted=PaymentRequirements( + scheme="exact", + network=NETWORK, + asset=TOKEN_ADDRESS, + amount=AMOUNT, + pay_to=RECIPIENT, + max_timeout_seconds=3600, + extra={"assetTransferMethod": "permit2"}, + ), + payload=payload_dict, + extensions={EIP2612_GAS_SPONSORING_KEY: {"info": eip2612_info}}, + ) + requirements = make_requirements() + + with patch( + "x402.mechanisms.evm.exact.permit2_utils._verify_permit2_signature", + return_value=True, + ): + result = facilitator.verify(payload, requirements) + + assert result.is_valid is False + assert "spender_not_permit2" in result.invalid_reason diff --git a/specs/extensions/eip2612_gas_sponsoring.md b/specs/extensions/eip2612_gas_sponsoring.md index 49e138458e..00579025df 100644 --- a/specs/extensions/eip2612_gas_sponsoring.md +++ b/specs/extensions/eip2612_gas_sponsoring.md @@ -128,13 +128,12 @@ To utilize this extension, the client must generate a valid EIP-2612 signature a "amount": "10000" }, "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", - "spender": "0xx402Permit2ProxyAddress", - "nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480", + "spender": "0x402085c248EeA27D92E8b30b2C58ed07f9E20001", + "nonce": "33247007178036348590600198031289925668252061821958005840077069883511451257277", "deadline": "1740672154", "witness": { "to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", - "validAfter": "1740672089", - "extra": {} + "validAfter": "1740672089" } } }, @@ -143,7 +142,7 @@ To utilize this extension, the client must generate a valid EIP-2612 signature a "info": { "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", - "spender": "0xCanonicalPermit2", + "spender": "0x000000000022D473030F116dDEE9F6B43aC78BA3", "amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "nonce": "0", "deadline": "1740672154", diff --git a/specs/extensions/erc20_gas_sponsoring.md b/specs/extensions/erc20_gas_sponsoring.md index 5ac5e515fa..7e079035c2 100644 --- a/specs/extensions/erc20_gas_sponsoring.md +++ b/specs/extensions/erc20_gas_sponsoring.md @@ -154,13 +154,12 @@ Incorrect fees or nonce values invalidate the signed transaction. "amount": "10000" }, "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", - "spender": "0xx402Permit2ProxyAddress", - "nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480", + "spender": "0x402085c248EeA27D92E8b30b2C58ed07f9E20001", + "nonce": "33247007178036348590600198031289925668252061821958005840077069883511451257277", "deadline": "1740672154", "witness": { "to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", - "validAfter": "1740672089", - "extra": {} + "validAfter": "1740672089" } } }, @@ -169,7 +168,7 @@ Incorrect fees or nonce values invalidate the signed transaction. "info": { "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", - "spender": "0xCanonicalPermit2", + "spender": "0x000000000022D473030F116dDEE9F6B43aC78BA3", "amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935", "signedTransaction": "0x505cbf0d9a4a227e0c52c6c2d6a7588d6acca34008c8e8986a12832597641d6293af148b571c73608a2ce6496642e377d6da8dbbf5836e9bd15092f9ecab05ded3", "version": "1" diff --git a/specs/schemes/exact/scheme_exact_evm.md b/specs/schemes/exact/scheme_exact_evm.md index 6cb2dc7ef8..605033bcf2 100644 --- a/specs/schemes/exact/scheme_exact_evm.md +++ b/specs/schemes/exact/scheme_exact_evm.md @@ -146,12 +146,11 @@ The `payload` field must contain: }, "from": "0x857b06519E91e3A54538791bDbb0E22373e36b66", "spender": "0x402085c248EeA27D92E8b30b2C58ed07f9E20001", // Canonical x402ExactPermit2Proxy address - "nonce": "0xf3746613c2d920b5fdabc0856f2aeb2d4f88ee6037b8cc5d04a71a4462f13480", + "nonce": "33247007178036348590600198031289925668252061821958005840077069883511451257277", "deadline": "1740672154", "witness": { "to": "0x209693Bc6afc0C5328bA36FaF03C514EF312287C", - "validAfter": "1740672089", - "extra": {} + "validAfter": "1740672089" } } }, @@ -164,8 +163,6 @@ The verifier must execute these checks in order: 1. **Verify** `payload.signature` is valid and recovers to the `permit2Authorization.from`. - - Note that `extra` must be converted to its ABI encoded version. - 2. **Verify** that the `client` has enabled the Permit2 approval. - if ERC20.allowance(from, Permit2_Address) < amount: @@ -181,7 +178,9 @@ The verifier must execute these checks in order: 6. **Verify** the Token and Network match the requirement. -7. **Simulation:** +7. **Simulation (Recommended):** + + Simulation is recommended but implementations may defer to re-verify-before-settle. - _Standard:_ Simulate `x402ExactPermit2Proxy.settle`. - _With "Sponsored ERC20 Approval" (Extension):_ Simulate batch `transfer` -> `approve` -> `settle`. @@ -354,20 +353,18 @@ contract x402ExactPermit2Proxy { event x402PermitTransfer(address from, address to, uint256 amount, address asset); - // EIP-712 Type Definition + // EIP-712 Type Definition (post-audit: extra removed from Witness) string public constant WITNESS_TYPE_STRING = - "Witness witness)Witness(bytes extra,address to,uint256 validAfter)TokenPermissions(address token,uint256 amount)"; + "Witness witness)TokenPermissions(address token,uint256 amount)Witness(address to,uint256 validAfter)"; bytes32 public constant WITNESS_TYPEHASH = - keccak256("Witness(bytes extra,address to,uint256 validAfter)"); + keccak256("Witness(address to,uint256 validAfter)"); struct Witness { address to; uint256 validAfter; - bytes extra; } - // New Struct to group EIP-2612 parameters and reduce stack depth struct EIP2612Permit { uint256 value; uint256 deadline; @@ -385,21 +382,18 @@ contract x402ExactPermit2Proxy { */ function settle( ISignatureTransfer.PermitTransferFrom calldata permit, - uint256 amount, address owner, Witness calldata witness, bytes calldata signature ) external { - _settleInternal(permit, amount, owner, witness, signature); + _settleInternal(permit, owner, witness, signature); } /** * @notice Extension: Settles a transfer using an EIP-2612 Permit for the allowance - * @dev Deconstructs the 2612 signature bytes to call the token contract */ - function settleWith2612( - EIP2612Permit calldata permit2612, // Deduplicated/Grouped params - uint256 amount, + function settleWithPermit( + EIP2612Permit calldata permit2612, ISignatureTransfer.PermitTransferFrom calldata permit, address owner, Witness calldata witness, @@ -415,29 +409,25 @@ contract x402ExactPermit2Proxy { ); // 2. Execute Permit2 Settlement - _settleInternal(permit, amount, owner, witness, signature); + _settleInternal(permit, owner, witness, signature); } function _settleInternal( ISignatureTransfer.PermitTransferFrom calldata permit, - uint256 amount, address owner, Witness calldata witness, bytes calldata signature ) internal { require(block.timestamp >= witness.validAfter, "Too early"); - require(amount <= permit.permitted.amount, "Amount higher than permitted"); ISignatureTransfer.SignatureTransferDetails memory transferDetails = ISignatureTransfer.SignatureTransferDetails({ to: witness.to, - requestedAmount: amount + requestedAmount: permit.permitted.amount }); - // Reconstruct hash to enforce witness integrity bytes32 witnessHash = keccak256(abi.encode( WITNESS_TYPEHASH, - keccak256(witness.extra), witness.to, witness.validAfter )); From db2bfac75f43f9ff0bdda1cbfc4f75ea7e880a4d Mon Sep 17 00:00:00 2001 From: Carson Roscoe Date: Thu, 19 Mar 2026 11:42:36 -0700 Subject: [PATCH 088/129] chore: version python package (#1704) --- python/x402/CHANGELOG.md | 11 +++++++++++ python/x402/__init__.py | 2 +- python/x402/changelog.d/545.bugfix.md | 1 - python/x402/changelog.d/689.feature.md | 1 - python/x402/pyproject.toml | 2 +- python/x402/uv.lock | 4 ++-- 6 files changed, 15 insertions(+), 6 deletions(-) delete mode 100644 python/x402/changelog.d/545.bugfix.md delete mode 100644 python/x402/changelog.d/689.feature.md diff --git a/python/x402/CHANGELOG.md b/python/x402/CHANGELOG.md index cf6aa58628..20d25d31f8 100644 --- a/python/x402/CHANGELOG.md +++ b/python/x402/CHANGELOG.md @@ -2,6 +2,17 @@ +## [2.5.0] - 2026-03-19 + +### Fixed + +- Fixed Python HTTP middleware to return `502` instead of `500` when the facilitator responds with invalid JSON or schema-invalid data. ([#545](https://github.com/coinbase/x402/pull/545)) + +### Added + +- Added Permit2 support to the Python SDK exact EVM mechanism with full TS/Go parity. The client routes to Permit2 (`PermitWitnessTransferFrom`) when `assetTransferMethod == "permit2"` in payment requirements extra, and the facilitator verifies and settles via the `x402ExactPermit2Proxy` contract. Includes `eip2612GasSponsoring` and `erc20ApprovalGasSponsoring` extension support for gasless Permit2 approval flows, universal signature verification via `signer.verify_typed_data` (EOA + EIP-1271 + ERC-6492), and `settleWithPermit` settlement path. Added E2E `/protected-permit2`, `/protected-permit2-eip2612`, and `/protected-permit2-erc20` endpoints to Flask server, and updated httpx client for cross-language Permit2 testing. ([#689](https://github.com/coinbase/x402/pull/689)) + + ## [2.4.0] - 2026-03-16 ### Fixed diff --git a/python/x402/__init__.py b/python/x402/__init__.py index 7932c40bed..619b316efe 100644 --- a/python/x402/__init__.py +++ b/python/x402/__init__.py @@ -137,7 +137,7 @@ x402ResourceServerSync, ) -__version__ = "0.1.0" +__version__ = "2.5.0" __all__ = [ # Version diff --git a/python/x402/changelog.d/545.bugfix.md b/python/x402/changelog.d/545.bugfix.md deleted file mode 100644 index b3e011de17..0000000000 --- a/python/x402/changelog.d/545.bugfix.md +++ /dev/null @@ -1 +0,0 @@ -Fixed Python HTTP middleware to return `502` instead of `500` when the facilitator responds with invalid JSON or schema-invalid data. diff --git a/python/x402/changelog.d/689.feature.md b/python/x402/changelog.d/689.feature.md deleted file mode 100644 index c86366560c..0000000000 --- a/python/x402/changelog.d/689.feature.md +++ /dev/null @@ -1 +0,0 @@ -Added Permit2 support to the Python SDK exact EVM mechanism with full TS/Go parity. The client routes to Permit2 (`PermitWitnessTransferFrom`) when `assetTransferMethod == "permit2"` in payment requirements extra, and the facilitator verifies and settles via the `x402ExactPermit2Proxy` contract. Includes `eip2612GasSponsoring` and `erc20ApprovalGasSponsoring` extension support for gasless Permit2 approval flows, universal signature verification via `signer.verify_typed_data` (EOA + EIP-1271 + ERC-6492), and `settleWithPermit` settlement path. Added E2E `/protected-permit2`, `/protected-permit2-eip2612`, and `/protected-permit2-erc20` endpoints to Flask server, and updated httpx client for cross-language Permit2 testing. diff --git a/python/x402/pyproject.toml b/python/x402/pyproject.toml index 218acc1d30..66e2d97fd9 100644 --- a/python/x402/pyproject.toml +++ b/python/x402/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "x402" -version = "2.4.0" +version = "2.5.0" description = "x402 Payment Protocol SDK for Python" readme = "README.md" license = { text = "MIT" } diff --git a/python/x402/uv.lock b/python/x402/uv.lock index 845f4badd9..5904dd13a3 100644 --- a/python/x402/uv.lock +++ b/python/x402/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10" [[package]] @@ -3407,7 +3407,7 @@ wheels = [ [[package]] name = "x402" -version = "2.4.0" +version = "2.5.0" source = { editable = "." } dependencies = [ { name = "nest-asyncio" }, From 53ba5b02036020622dc94c8632558ac24a037387 Mon Sep 17 00:00:00 2001 From: Carson Roscoe Date: Thu, 19 Mar 2026 13:09:31 -0700 Subject: [PATCH 089/129] feat: gitbooks permit2 python (#1689) * feat: add permit2 and gas sponsorship extensions to gitbooks * feat: added permit2 python sdk changes to gitbooks * fix: pr feedback --- .../network-and-token-support.mdx | 47 +++--- docs/docs.json | 4 +- docs/extensions/eip2612-gas-sponsoring.mdx | 142 +++++++++++++++++ .../erc20-approval-gas-sponsoring.mdx | 150 ++++++++++++++++++ docs/extensions/overview.mdx | 4 +- docs/faq.md | 6 +- docs/sdk-features.md | 3 + 7 files changed, 331 insertions(+), 25 deletions(-) create mode 100644 docs/extensions/eip2612-gas-sponsoring.mdx create mode 100644 docs/extensions/erc20-approval-gas-sponsoring.mdx diff --git a/docs/core-concepts/network-and-token-support.mdx b/docs/core-concepts/network-and-token-support.mdx index aaa7e9afc5..ffab259f2a 100644 --- a/docs/core-concepts/network-and-token-support.mdx +++ b/docs/core-concepts/network-and-token-support.mdx @@ -55,33 +55,44 @@ Multiple production-ready facilitators are available supporting various networks x402 supports tokens on EVM, Solana, Stellar, and Aptos networks: -* **EVM**: Any ERC-20 token that implements the EIP-3009 standard +* **EVM**: Any ERC-20 token (via EIP-3009 or Permit2) * **Solana**: Any SPL or token-2022 token * **Stellar**: Any Soroban token implementing SEP-41 * **Aptos**: Any fungible asset using Aptos's native fungible asset framework -**Important**: Facilitators support networks, not specific tokens β€” any EIP-3009 compatible token works on EVM networks, any SPL/token-2022 token works on Solana, any SEP-41 token works on Stellar, and any fungible asset works on Aptos, for the facilitators that support those networks. +**Important**: Facilitators support networks, not specific tokens β€” any ERC-20 token works on EVM networks (via EIP-3009 or Permit2), any SPL/token-2022 token works on Solana, any SEP-41 token works on Stellar, and any fungible asset works on Aptos, for the facilitators that support those networks. -#### EVM: EIP-3009 Requirement +#### EVM: Asset Transfer Methods -Tokens must implement the `transferWithAuthorization` function from the EIP-3009 standard. This enables: +x402 supports two asset transfer methods on EVM, selected automatically based on token capabilities: -* **Gasless transfers**: The facilitator sponsors gas fees +| Method | When Used | How It Works | +|--------|-----------|--------------| +| **EIP-3009** | Tokens with `transferWithAuthorization` (e.g., USDC) | Single off-chain signature, simplest flow | +| **Permit2** | Any ERC-20 token | Uses Uniswap's [Permit2](https://docs.uniswap.org/contracts/v4/deployments) contract + `x402ExactPermit2Proxy` | + +Both methods provide: + +* **Gasless transfers**: The facilitator sponsors gas for the payment itself. For Permit2, the one-time approval step can also be made gasless via optional [gas sponsoring extensions](/extensions/eip2612-gas-sponsoring) * **Signature-based authorization**: Users sign transfer authorizations off-chain * **Secure payments**: Transfers are authorized by cryptographic signatures +EIP-3009 is preferred when available (simpler, no approval step). Permit2 serves as the universal fallback, enabling any ERC-20 token to work with x402. + +**Permit2 approval**: Permit2 requires a one-time on-chain approval of the Permit2 contract. x402 supports two gas sponsoring extensions that make this step gasless β€” see [EIP-2612 Gas Sponsoring](/extensions/eip2612-gas-sponsoring) and [ERC-20 Approval Gas Sponsoring](/extensions/erc20-approval-gas-sponsoring). + #### Specifying Payment Amounts When configuring payment requirements, you have two options: 1. **Price String** (e.g., `"$0.01"`) - The system infers USDC as the token -2. **TokenAmount** - Specify exact atomic units of any EIP-3009 token +2. **TokenAmount** - Specify exact atomic units of any ERC-20 token -#### Using Custom EIP-3009 Tokens +#### Using Custom ERC-20 Tokens -To use a custom EIP-3009 token, you need three key pieces of information: +To use a custom ERC-20 token, you need three key pieces of information: -1. **Token Address**: The contract address of your EIP-3009 token +1. **Token Address**: The contract address of your ERC-20 token 2. **EIP-712 Name**: The token's name for EIP-712 signatures 3. **EIP-712 Version**: The token's version for EIP-712 signatures @@ -115,19 +126,17 @@ On Stellar, x402 supports all Soroban tokens implementing [SEP-41](https://githu On Aptos, x402 supports all fungible assets using Aptos's native fungible asset framework. Payments use the `primary_fungible_store::transfer` function for automatic store creation and management. The TypeScript SDK supports sponsored transactions where facilitators pay gas fees on behalf of clients. -#### USDC - The Default Token +#### Default Tokens -* **Status**: Supported by default across all networks -* **Why**: USDC implements EIP-3009 and is widely available -* **Networks**: Available on `eip155:8453` (Base), `eip155:84532` (Base Sepolia), and all supported networks +Each network defines its own default token. When you use a price string (e.g., `"$0.01"`), the system uses the network's configured default. USDC is the default on most EVM networks because it implements EIP-3009 (simplest flow) and is widely available, but other networks may define different defaults. -#### Why EIP-3009? +#### Why EIP-3009 + Permit2? -The EIP-3009 standard is essential for x402 because it enables: +These two transfer methods together give x402 full ERC-20 coverage on EVM: 1. **Gas abstraction**: Buyers don't need native tokens (ETH, MATIC, etc.) for gas -2. **One-step payments**: No separate approval transactions required -3. **Universal facilitator support**: Any EIP-3009 token works with any facilitator +2. **EIP-3009**: One-step payments with no approval needed β€” ideal for tokens like USDC +3. **Permit2**: Universal fallback for any ERC-20 token, with optional gas-sponsored approval via [extensions](/extensions/eip2612-gas-sponsoring) ### Quick Reference @@ -137,7 +146,7 @@ The EIP-3009 standard is essential for x402 because it enables: | [Production Facilitators](https://www.x402.org/ecosystem?filter=facilitators) | Various (Base, Solana, Polygon, Avalanche, etc.) | Yes | Varies | | Self-hosted | Any EVM network (CAIP-2 format) | Yes | Technical setup | -**Note**: On EVM networks, facilitators support any EIP-3009 compatible token; on Solana, facilitators support any SPL/Token-2022 token. +**Note**: On EVM networks, facilitators support any ERC-20 token (via EIP-3009 or Permit2); on Solana, facilitators support any SPL/Token-2022 token. ### Adding Support for New Networks @@ -263,7 +272,7 @@ Key takeaways: * Base (`eip155:8453`), Base Sepolia (`eip155:84532`), Solana (`solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`), and Solana Devnet (`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`) have the best out-of-the-box support * Any EVM network can be supported with a custom facilitator using CAIP-2 format -* Any EIP-3009 token (with `transferWithAuthorization`) works on any facilitator +* Any ERC-20 token works on any facilitator (via EIP-3009 or Permit2) * Use price strings for USDC or TokenAmount for custom tokens * Network choice affects gas costs and payment economics * V2 uses CAIP-2 network identifiers for unambiguous cross-chain support diff --git a/docs/docs.json b/docs/docs.json index 2cb4cf1d57..90d8e39cb0 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -69,7 +69,9 @@ "extensions/bazaar", "extensions/payment-identifier", "extensions/sign-in-with-x", - "extensions/offer-receipt" + "extensions/offer-receipt", + "extensions/eip2612-gas-sponsoring", + "extensions/erc20-approval-gas-sponsoring" ] }, { diff --git a/docs/extensions/eip2612-gas-sponsoring.mdx b/docs/extensions/eip2612-gas-sponsoring.mdx new file mode 100644 index 0000000000..7d90ad8a9d --- /dev/null +++ b/docs/extensions/eip2612-gas-sponsoring.mdx @@ -0,0 +1,142 @@ +--- +title: "EIP-2612 Gas Sponsoring" +description: "Gasless Permit2 approval for ERC-20 tokens that implement EIP-2612. The facilitator submits the permit on-chain, so the client never pays gas for the approval step." +--- + +The EIP-2612 gas sponsoring extension enables gasless Permit2 approval for tokens that implement the [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612) `permit()` function (e.g., USDC). The client signs an off-chain permit authorizing the Permit2 contract, and the facilitator submits it atomically during settlement via `x402ExactPermit2Proxy.settleWithPermit`. + +## Overview + +When using the Permit2 asset transfer method, the user must first approve the Permit2 contract to spend their tokens. For tokens that support EIP-2612, this approval can be done entirely off-chain: + +* **For Buyers**: No gas needed β€” sign a permit off-chain and the facilitator handles the rest +* **For Sellers**: Advertise this extension so clients using EIP-2612 tokens get a seamless experience +* **For Facilitators**: Accept the permit signature and call `settleWithPermit` to atomically approve + settle in one transaction + +## How It Works + +1. **Server** advertises `eip2612GasSponsoring` in the `PaymentRequired` response extensions +2. **Client** checks if Permit2 allowance is insufficient; if so, signs an EIP-2612 permit off-chain +3. **Client** includes the permit data in the `extensions.eip2612GasSponsoring.info` field of the payment payload +4. **Facilitator** calls `x402ExactPermit2Proxy.settleWithPermit()`, which atomically submits the EIP-2612 permit and executes the Permit2 transfer in a single transaction + +## Server Usage + +Advertise support for this extension in your route configuration: + + + + ```typescript + import { declareEip2612GasSponsoringExtension } from "@x402/extensions/eip2612-gas-sponsoring"; + + const routes = { + "GET /api/data": { + accepts: [{ + scheme: "exact", + network: "eip155:84532", + price: "$0.01", + payTo: "0xYourAddress", + }], + extensions: { + ...declareEip2612GasSponsoringExtension(), + }, + }, + }; + ``` + + + ```go + import ( + "github.com/coinbase/x402/go/extensions/eip2612gassponsor" + ) + + extensions := eip2612gassponsor.DeclareEip2612GasSponsoringExtension() + // Include in your route's Extensions field + ``` + + + ```python + from x402.extensions.eip2612_gas_sponsoring import declare_eip2612_gas_sponsoring_extension + + routes = { + "GET /api/data": { + "accepts": { + "scheme": "exact", + "network": "eip155:84532", + "price": "$0.01", + "payTo": "0xYourAddress", + }, + "extensions": { + **declare_eip2612_gas_sponsoring_extension(), + }, + }, + } + ``` + + + +## Client Usage + +The `ExactEvmScheme` handles EIP-2612 gas sponsoring automatically. When the server advertises this extension and the client's Permit2 allowance is insufficient, the scheme signs the EIP-2612 permit and includes it in the payment payload. + + + + ```typescript + import { ExactEvmScheme } from "@x402/evm/exact/client"; + + // readContract capability is required for EIP-2612 (to check allowance and nonce) + const scheme = new ExactEvmScheme(signer); + client.register("eip155:*", scheme); + + // The scheme automatically signs an EIP-2612 permit when: + // 1. The server advertises eip2612GasSponsoring + // 2. The asset transfer method is "permit2" + // 3. The client's Permit2 allowance is insufficient + ``` + + + ```go + import ( + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + ) + + scheme := evm.NewExactEvmScheme(signer) + client.Register("eip155:*", scheme) + + // EIP-2612 permit signing is handled automatically + // when the server advertises the extension + ``` + + + ```python + from x402 import x402Client + from x402.mechanisms.evm import EthAccountSignerWithRPC + from x402.mechanisms.evm.exact import register_exact_evm_client + + account = Account.from_key("0xYourPrivateKey") + signer = EthAccountSignerWithRPC(account, rpc_url="https://sepolia.base.org") + + client = x402Client() + register_exact_evm_client(client, signer) + # Automatically signs EIP-2612 permit when needed + ``` + + + +## When to Use + +Use this extension when: + +- Your payment token implements EIP-2612 (has a `permit()` function) +- You want fully gasless Permit2 onboarding for your users +- You're using the `permit2` asset transfer method + +Common EIP-2612 tokens include USDC, DAI, and many modern ERC-20 tokens. + +## SDK Support + +| SDK | Supported | +|-----|-----------| +| TypeScript | βœ… | +| Go | βœ… | +| Python | βœ… | diff --git a/docs/extensions/erc20-approval-gas-sponsoring.mdx b/docs/extensions/erc20-approval-gas-sponsoring.mdx new file mode 100644 index 0000000000..63ddbfadcd --- /dev/null +++ b/docs/extensions/erc20-approval-gas-sponsoring.mdx @@ -0,0 +1,150 @@ +--- +title: "ERC-20 Approval Gas Sponsoring" +description: "Gasless Permit2 approval for any ERC-20 token, including those without EIP-2612. The facilitator sponsors the gas for the approval transaction." +--- + +The ERC-20 approval gas sponsoring extension enables gasless Permit2 approval for **any ERC-20 token**, including those that do not implement EIP-2612. The client signs (but does not broadcast) a standard `approve(Permit2, MaxUint256)` transaction, and the facilitator broadcasts it atomically before settling the Permit2 payment. + +## Overview + +This is the universal fallback for gasless Permit2 onboarding. While [EIP-2612 gas sponsoring](/extensions/eip2612-gas-sponsoring) is preferred for tokens that support it, this extension works with every ERC-20 token: + +* **For Buyers**: No gas needed β€” sign an approval transaction off-chain and the facilitator broadcasts it +* **For Sellers**: Advertise this extension to support the widest range of ERC-20 tokens +* **For Facilitators**: Broadcast the pre-signed approval and settle in an atomic batch, optionally funding the client's gas if needed + +## How It Works + +1. **Server** advertises `erc20ApprovalGasSponsoring` in the `PaymentRequired` response extensions +2. **Client** checks if Permit2 allowance is insufficient; if so, signs a raw `approve(Permit2, MaxUint256)` transaction without broadcasting it +3. **Client** includes the signed transaction in `extensions.erc20ApprovalGasSponsoring.info.signedTransaction` +4. **Facilitator** executes an atomic batch: + - Funds the client's wallet with gas (if needed) + - Broadcasts the client's signed approval transaction + - Calls `x402ExactPermit2Proxy.settle()` to complete the payment + +The atomic batch ensures the approval and settlement happen together β€” there is no window for front-running between the approval and the payment. + +## Server Usage + +Advertise support for this extension in your route configuration: + + + + ```typescript + import { declareErc20ApprovalGasSponsoringExtension } from "@x402/extensions/erc20-approval-gas-sponsoring"; + + const routes = { + "GET /api/data": { + accepts: [{ + scheme: "exact", + network: "eip155:84532", + price: "$0.01", + payTo: "0xYourAddress", + }], + extensions: { + ...declareErc20ApprovalGasSponsoringExtension(), + }, + }, + }; + ``` + + + ```go + import ( + "github.com/coinbase/x402/go/extensions/erc20approvalgassponsor" + ) + + extensions := erc20approvalgassponsor.DeclareExtension() + // Include in your route's Extensions field + ``` + + + ```python + from x402.extensions.erc20_approval_gas_sponsoring import ( + declare_erc20_approval_gas_sponsoring_extension, + ) + + routes = { + "GET /api/data": { + "accepts": { + "scheme": "exact", + "network": "eip155:84532", + "price": "$0.01", + "payTo": "0xYourAddress", + }, + "extensions": { + **declare_erc20_approval_gas_sponsoring_extension(), + }, + }, + } + ``` + + + +## Client Usage + +The `ExactEvmScheme` handles ERC-20 approval gas sponsoring automatically as a fallback when EIP-2612 is not available. + + + + ```typescript + import { ExactEvmScheme } from "@x402/evm/exact/client"; + + // signTransaction and getTransactionCount capabilities are required + const scheme = new ExactEvmScheme(signer); + client.register("eip155:*", scheme); + + // The scheme automatically signs an ERC-20 approval when: + // 1. The server advertises erc20ApprovalGasSponsoring + // 2. The asset transfer method is "permit2" + // 3. The client's Permit2 allowance is insufficient + // 4. EIP-2612 gas sponsoring is not available or not supported by the token + ``` + + + ```go + import ( + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + ) + + scheme := evm.NewExactEvmScheme(signer) + client.Register("eip155:*", scheme) + + // ERC-20 approval gas sponsoring is handled automatically + // as a fallback when EIP-2612 is not available + ``` + + + ```python + from x402 import x402Client + from x402.mechanisms.evm import EthAccountSignerWithRPC + from x402.mechanisms.evm.exact import register_exact_evm_client + + account = Account.from_key("0xYourPrivateKey") + signer = EthAccountSignerWithRPC(account, rpc_url="https://sepolia.base.org") + + client = x402Client() + register_exact_evm_client(client, signer) + # Automatically signs ERC-20 approval transaction when needed + ``` + + + +## When to Use + +Use this extension when: + +- You want to support any ERC-20 token, not just those with EIP-2612 +- You're using the `permit2` asset transfer method +- You want fully gasless onboarding for your users regardless of the token + +This extension is typically advertised alongside [EIP-2612 gas sponsoring](/extensions/eip2612-gas-sponsoring). The client automatically selects the best option: EIP-2612 if the token supports it, ERC-20 approval otherwise. + +## SDK Support + +| SDK | Supported | +|-----|-----------| +| TypeScript | βœ… | +| Go | βœ… | +| Python | βœ… | diff --git a/docs/extensions/overview.mdx b/docs/extensions/overview.mdx index 98b5707088..a6f7ea9454 100644 --- a/docs/extensions/overview.mdx +++ b/docs/extensions/overview.mdx @@ -109,8 +109,8 @@ Bazaar is unique in that it spans both sides: the resource server extension enri | Extension | Type | Description | SDK Support | |-----------|------|-------------|-------------| | [Bazaar](./bazaar) | Server + Facilitator | Discovery layer for x402 endpoints and MCP tools. Makes your services findable by AI agents and developers. | TypeScript, Go, Python | -| EIP-2612 Gas Sponsoring | Facilitator | Sponsors gas for EIP-2612 permit-based token transfers. | TypeScript | -| ERC-20 Approval Gas Sponsoring | Facilitator | Sponsors gas for ERC-20 approval-based token transfers. | TypeScript | +| [EIP-2612 Gas Sponsoring](./eip2612-gas-sponsoring) | Facilitator | Sponsors gas for EIP-2612 permit-based token transfers. | TypeScript, Go, Python | +| [ERC-20 Approval Gas Sponsoring](./erc20-approval-gas-sponsoring) | Facilitator | Sponsors gas for ERC-20 approval-based token transfers. | TypeScript, Go, Python | | [Payment Identifier](./payment-identifier) | Server + Client | Attaches a unique identifier to each payment for tracking, reconciliation, and idempotency. | TypeScript, Go, Python | | [Sign-In-With-X](./sign-in-with-x) | Server + Client | CAIP-122 wallet authentication. Lets clients prove wallet ownership to access previously purchased content without repaying. | TypeScript | | [Signed Offers & Receipts](./offer-receipt) | Server + Client | Signs offers on 402 responses and receipts on 200 responses, producing cryptographic proof-of-interaction artifacts. | TypeScript | diff --git a/docs/faq.md b/docs/faq.md index 99d48960e8..83c80990f8 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -63,8 +63,8 @@ Yes. x402 handles the _payment execution_. You can still meter usage, aggregate | Network | CAIP-2 ID | Asset | Fees\* | Status | | -------------- | --------- | ----- | -------- | ----------- | -| Base | `eip155:8453` | Any EIP-3009 token | fee-free | **Mainnet** | -| Base Sepolia | `eip155:84532` | Any EIP-3009 token | fee-free | **Testnet** | +| Base | `eip155:8453` | Any ERC-20 token | fee-free | **Mainnet** | +| Base Sepolia | `eip155:84532` | Any ERC-20 token | fee-free | **Testnet** | | Solana | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | Any SPL token or Token-2022 token | fee-free | **Mainnet** | | Solana Devnet | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | Any SPL token or Token-2022 | fee-free | **Testnet** | @@ -119,7 +119,7 @@ Yes. Programmatic wallets (e.g., **CDP Wallet API**, **viem**, **ethers‑v6** H Tracked in public GitHub issues + community RFCs. Major themes: * Multi‑asset support -* Additional schemes (`upto`, `stream`, `permit2`) +* Additional schemes (`upto`, `stream`) * Discovery layer for service search & reputation **Why is x402 hosted in the Coinbase GitHub?** diff --git a/docs/sdk-features.md b/docs/sdk-features.md index 3180b97db4..585945ef95 100644 --- a/docs/sdk-features.md +++ b/docs/sdk-features.md @@ -36,6 +36,7 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt | Mechanism | TypeScript | Go | Python | |-----------|------------|-----|--------| | exact/evm (EIP-3009) | βœ… | βœ… | βœ… | +| exact/evm (Permit2) | βœ… | βœ… | βœ… | | exact/svm (SPL) | βœ… | βœ… | βœ… | | exact/stellar (Soroban) | βœ… | ❌ | ❌ | | exact/aptos (Fungible Assets) | βœ… | ❌ | ❌ | @@ -49,6 +50,8 @@ This page tracks which features are implemented in each SDK (TypeScript, Go, Pyt | sign-in-with-x | βœ… | ❌ | ❌ | | payment-identifier | βœ… | βœ… | βœ… | | offer-receipt | βœ… | ❌ | ❌ | +| eip2612-gas-sponsoring | βœ… | βœ… | βœ… | +| erc20-approval-gas-sponsoring | βœ… | βœ… | βœ… | ## Client Hooks From 7826ac3834099e2c4242f5e6ce0ac7572228c152 Mon Sep 17 00:00:00 2001 From: Ash <105402607+Must-be-Ash@users.noreply.github.com> Date: Thu, 19 Mar 2026 22:49:30 -0700 Subject: [PATCH 090/129] feat(site): brand scroller, ecosystem search & UI refresh (#1705) * chore(site): add Conway Automaton, AgentCash, Stellar, AgentMail, Vercel; fix Alchemy link Made-with: Cursor * chore(site): fix Alchemy link with UTM, add Zerion Made-with: Cursor * chore(site): point partner links to x402-specific pages from Slack thread Made-with: Cursor * chore(site): add logos for new ecosystem partners Made-with: Cursor * chore(site): add Cloudflare, featured section with 8 major partners Made-with: Cursor * fix(site): make featured cards uniform height Made-with: Cursor * chore(site): remove highlighted section label, rename featured->highlighted in code Made-with: Cursor * chore(site): rename highlighted->pinned throughout ecosystem Made-with: Cursor * chore(site): rename pinned->topSection/top_section throughout ecosystem Made-with: Cursor * fix(site): align top_section field name between JSON and TypeScript interface Made-with: Cursor * chore(site): add OpenZeppelin facilitator partner Made-with: Cursor * feat(site): add brand scroller, ecosystem search, and UI improvements - Add animated brand scroller carousel on landing page with monocolor logos - Add ecosystem search with dropdown and filtered card results - Redesign facilitator modal to match site's light theme - Remove logo border frames from ecosystem cards - Add new ecosystem partners: Browserbase, Freepik, Hyperbrowser - Equalize card heights across all ecosystem sections * fix(site): fix search dropdown z-index and clear state issues - Move search into its own z-20 stacking context so dropdown overlays cards - Remove AnimatePresence wrapper from search results to prevent exit animation blocking the category view from remounting on clear * fix(site): fix search dropdown z-index and invalid partner JSON - Bump search wrapper to z-30 so dropdown overlays card elements - Fix invalid JSON in crypto-sentiment-api (comment) and quantumshield-api (markdown fence) * feat(site): merge stats and brand scroller into unified social proof section - Combine stats and brand logos into one section with a divider - Move "Adopted by" carousel into StatsSection component - Remove standalone BrandScroller component from page - Fix invalid JSON in crypto-sentiment-api and quantumshield-api metadata --------- Co-authored-by: Ethan Oroshiba --- .../site/app/components/BrandScroller.tsx | 53 ++++++ .../site/app/components/EcosystemCard.tsx | 12 +- .../site/app/components/StatsSection.tsx | 59 +++++- .../site/app/ecosystem/EcosystemClient.tsx | 177 ++++++++++++++++-- typescript/site/app/ecosystem/data.ts | 2 +- .../site/app/ecosystem/facilitator-card.tsx | 117 ++++++------ .../partners-data/agentcash/metadata.json | 7 + .../partners-data/agentmail/metadata.json | 7 + .../partners-data/alchemy/metadata.json | 5 +- .../ecosystem/partners-data/aws/metadata.json | 5 +- .../partners-data/browserbase/metadata.json | 7 + .../partners-data/cloudflare/metadata.json | 8 + .../conway-automaton/metadata.json | 7 + .../crypto-sentiment-api/metadata.json | 2 +- .../partners-data/freepik/metadata.json | 7 + .../partners-data/hyperbrowser/metadata.json | 7 + .../partners-data/messari/metadata.json | 5 +- .../partners-data/nansen/metadata.json | 5 +- .../partners-data/openzeppelin/metadata.json | 7 + .../quantumshield-api/metadata.json | 1 - .../partners-data/stellar/metadata.json | 7 + .../partners-data/stripe/metadata.json | 5 +- .../partners-data/vercel/metadata.json | 8 + .../partners-data/world/metadata.json | 5 +- .../partners-data/zerion/metadata.json | 7 + typescript/site/app/globals.css | 13 ++ typescript/site/app/page.tsx | 2 +- typescript/site/public/logos/agentcash.png | Bin 0 -> 34635 bytes .../site/public/logos/agentmail-mono.svg | 1 + typescript/site/public/logos/agentmail.png | Bin 0 -> 5668 bytes typescript/site/public/logos/alchemy-mono.svg | 24 +++ typescript/site/public/logos/aws.-mono.svg | 1 + .../site/public/logos/browserbase-mono.svg | 26 +++ typescript/site/public/logos/browserbase.png | Bin 0 -> 20360 bytes .../site/public/logos/cloudflare-mono.svg | 26 +++ typescript/site/public/logos/cloudflare.png | Bin 0 -> 2841 bytes .../site/public/logos/conway-automaton.png | Bin 0 -> 3364 bytes typescript/site/public/logos/freepik-mono.svg | 23 +++ typescript/site/public/logos/freepik.png | Bin 0 -> 21462 bytes .../site/public/logos/hyperbrowser-mono.svg | 26 +++ typescript/site/public/logos/hyperbrowser.png | Bin 0 -> 20724 bytes typescript/site/public/logos/messari-mono.svg | 23 +++ typescript/site/public/logos/nansen-mono.svg | 18 ++ typescript/site/public/logos/openzeppelin.png | Bin 0 -> 3433 bytes typescript/site/public/logos/stellar.png | Bin 0 -> 4708 bytes typescript/site/public/logos/stripe-mono.svg | 15 ++ typescript/site/public/logos/vercel-mono.svg | 14 ++ typescript/site/public/logos/vercel.png | Bin 0 -> 1070 bytes typescript/site/public/logos/world-mono.svg | 13 ++ typescript/site/public/logos/zerion.svg | 11 ++ 50 files changed, 658 insertions(+), 110 deletions(-) create mode 100644 typescript/site/app/components/BrandScroller.tsx create mode 100644 typescript/site/app/ecosystem/partners-data/agentcash/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/agentmail/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/browserbase/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/cloudflare/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/conway-automaton/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/freepik/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/hyperbrowser/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/openzeppelin/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/stellar/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/vercel/metadata.json create mode 100644 typescript/site/app/ecosystem/partners-data/zerion/metadata.json create mode 100644 typescript/site/public/logos/agentcash.png create mode 100644 typescript/site/public/logos/agentmail-mono.svg create mode 100644 typescript/site/public/logos/agentmail.png create mode 100644 typescript/site/public/logos/alchemy-mono.svg create mode 100644 typescript/site/public/logos/aws.-mono.svg create mode 100644 typescript/site/public/logos/browserbase-mono.svg create mode 100644 typescript/site/public/logos/browserbase.png create mode 100644 typescript/site/public/logos/cloudflare-mono.svg create mode 100644 typescript/site/public/logos/cloudflare.png create mode 100644 typescript/site/public/logos/conway-automaton.png create mode 100644 typescript/site/public/logos/freepik-mono.svg create mode 100644 typescript/site/public/logos/freepik.png create mode 100644 typescript/site/public/logos/hyperbrowser-mono.svg create mode 100644 typescript/site/public/logos/hyperbrowser.png create mode 100644 typescript/site/public/logos/messari-mono.svg create mode 100644 typescript/site/public/logos/nansen-mono.svg create mode 100644 typescript/site/public/logos/openzeppelin.png create mode 100644 typescript/site/public/logos/stellar.png create mode 100644 typescript/site/public/logos/stripe-mono.svg create mode 100644 typescript/site/public/logos/vercel-mono.svg create mode 100644 typescript/site/public/logos/vercel.png create mode 100644 typescript/site/public/logos/world-mono.svg create mode 100644 typescript/site/public/logos/zerion.svg diff --git a/typescript/site/app/components/BrandScroller.tsx b/typescript/site/app/components/BrandScroller.tsx new file mode 100644 index 0000000000..d75f553cff --- /dev/null +++ b/typescript/site/app/components/BrandScroller.tsx @@ -0,0 +1,53 @@ +"use client"; + +import Link from "next/link"; +import Image from "next/image"; + +const brands = [ + { name: "Stripe", logo: "/logos/stripe-mono.svg" }, + { name: "AWS", logo: "/logos/aws.-mono.svg", className: "h-8" }, + { name: "Messari", logo: "/logos/messari-mono.svg" }, + { name: "Alchemy", logo: "/logos/alchemy-mono.svg" }, + { name: "Nansen", logo: "/logos/nansen-mono.svg" }, + { name: "Vercel", logo: "/logos/vercel-mono.svg" }, + { name: "Cloudflare", logo: "/logos/cloudflare-mono.svg", className: "h-7" }, + { name: "World", logo: "/logos/world-mono.svg" }, +]; + +function BrandSet() { + return ( +
    + {brands.map((brand) => ( + {brand.name} + ))} +
    + ); +} + +export function BrandScroller() { + return ( + +

    + Adopted by +

    +
    +
    + {Array.from({ length: 4 }).map((_, i) => ( + + ))} +
    +
    + + ); +} diff --git a/typescript/site/app/components/EcosystemCard.tsx b/typescript/site/app/components/EcosystemCard.tsx index 8c5f375442..e6f3aac7b0 100644 --- a/typescript/site/app/components/EcosystemCard.tsx +++ b/typescript/site/app/components/EcosystemCard.tsx @@ -6,17 +6,17 @@ import type { Partner } from "../ecosystem/data"; interface EcosystemCardProps { partner: Partner; - variant?: "featured" | "standard"; + variant?: "top_section" | "standard"; } export function EcosystemCard({ partner, variant = "standard" }: EcosystemCardProps) { const isExternal = partner.websiteUrl.startsWith("http"); - const isFeatured = variant === "featured"; + const isFeatured = variant === "top_section"; const tagLabel = partner.typeLabel ?? partner.category; return (
    @@ -37,7 +37,7 @@ export function EcosystemCard({ partner, variant = "standard" }: EcosystemCardPr > {partner.logoUrl ? (
    @@ -51,7 +51,7 @@ export function EcosystemCard({ partner, variant = "standard" }: EcosystemCardPr
    ) : ( -
    +

    + {brands.map((brand) => ( + {brand.name} + ))} +

    + ); +} + export function StatsSection() { return (
    +

    Last 30 days

    - - - - -
    -
    0
    -
    Last 30 days
    -
    + + + + +
    + +
    + +

    Adopted by

    +
    +
    + {Array.from({ length: 4 }).map((_, i) => ( + + ))} +
    +
    +
    ); diff --git a/typescript/site/app/ecosystem/EcosystemClient.tsx b/typescript/site/app/ecosystem/EcosystemClient.tsx index 5879e33f04..a40eed318a 100644 --- a/typescript/site/app/ecosystem/EcosystemClient.tsx +++ b/typescript/site/app/ecosystem/EcosystemClient.tsx @@ -1,6 +1,6 @@ "use client"; -import { useMemo, useState } from "react"; +import { useMemo, useRef, useState, useEffect } from "react"; import Image from "next/image"; import { useRouter, useSearchParams } from "next/navigation"; import { AnimatePresence, motion } from "motion/react"; @@ -10,6 +10,93 @@ import { EcosystemCard } from "../components/EcosystemCard"; import FacilitatorCard from "./facilitator-card"; import type { Partner, CategoryInfo } from "./data"; +function SearchIcon({ className }: { className?: string }) { + return ( + + + + ); +} + +function EcosystemSearch({ partners, onQueryChange, onSelect }: { partners: Partner[]; onQueryChange: (q: string) => void; onSelect: (name: string) => void }) { + const [query, setQuery] = useState(""); + const [isOpen, setIsOpen] = useState(false); + const ref = useRef(null); + + useEffect(() => { + function handleClickOutside(e: MouseEvent) { + if (ref.current && !ref.current.contains(e.target as Node)) { + setIsOpen(false); + } + } + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + const results = useMemo(() => { + if (!query.trim()) return []; + const q = query.toLowerCase(); + return partners.filter((p) => p.name.toLowerCase().includes(q)).slice(0, 8); + }, [query, partners]); + + return ( +
    +
    + + { + setQuery(e.target.value); + onQueryChange(e.target.value); + onSelect(""); + setIsOpen(true); + }} + onFocus={() => query.trim() && setIsOpen(true)} + placeholder="Search ecosystem..." + className="w-full border border-foreground bg-background pl-10 pr-4 py-2.5 text-sm font-mono placeholder:text-gray-40 focus:outline-none focus:border-accent-orange transition-colors" + /> +
    + {isOpen && results.length > 0 && ( +
    + {results.map((partner) => ( + + ))} +
    + )} + {isOpen && query.trim() && results.length === 0 && ( +
    +

    No results found

    +
    + )} +
    + ); +} + interface EcosystemClientProps { initialPartners: Partner[]; categories: CategoryInfo[]; @@ -17,7 +104,7 @@ interface EcosystemClientProps { } type PartitionResult = { - featured: Partner[]; + topSection: Partner[]; byCategory: Record; }; @@ -65,9 +152,9 @@ function partitionPartners(partners: Partner[], categories: CategoryInfo[]): Par } } - const featured = partners.filter((partner) => partner.featured); + const topSection = partners.filter((partner) => partner.top_section); - return { featured, byCategory }; + return { topSection, byCategory }; } export default function EcosystemClient({ @@ -79,11 +166,14 @@ export default function EcosystemClient({ const router = useRouter(); const [isExpanded, setIsExpanded] = useState(true); + const [isSearching, setIsSearching] = useState(false); + const [searchQuery, setSearchQuery] = useState(""); + const [selectedPartner, setSelectedPartner] = useState(""); const activeFilter = (searchParams.get("filter") ?? initialSelectedCategory ?? "everything") || "everything"; - const { featured, byCategory } = useMemo( + const { topSection, byCategory } = useMemo( () => partitionPartners(initialPartners, categories), [initialPartners, categories], ); @@ -100,10 +190,21 @@ export default function EcosystemClient({ }); }; - const filteredPartners = + const basePartners = activeFilter === "everything" - ? initialPartners.filter((partner) => !partner.featured) - : (byCategory[activeFilter] ?? []).filter((partner) => !partner.featured); + ? initialPartners.filter((partner) => !partner.top_section) + : (byCategory[activeFilter] ?? []).filter((partner) => !partner.top_section); + + const filteredPartners = useMemo(() => { + if (selectedPartner) { + return initialPartners.filter((p) => p.name === selectedPartner); + } + if (searchQuery.trim()) { + const q = searchQuery.toLowerCase(); + return initialPartners.filter((p) => p.name.toLowerCase().includes(q)); + } + return basePartners; + }, [selectedPartner, searchQuery, basePartners, initialPartners]); return (
    @@ -130,27 +231,39 @@ export default function EcosystemClient({ of partners and developers leveraging x402 technology.

    +
    + +
    + { + setSearchQuery(q); + setIsSearching(q.trim().length > 0); + if (!q.trim()) setSelectedPartner(""); + }} + onSelect={(name) => setSelectedPartner(name)} + /> +
    - {featured.length > 0 && ( -
    -

    Featured projects

    + {!isSearching && topSection.length > 0 && ( +
    - {featured.slice(0, 4).map((partner) => ( + {topSection.map((partner) => ( {partner.facilitator ? ( - + ) : ( - + )} ))}
    )} -
    {/* Sidebar + main content */} @@ -201,6 +314,32 @@ export default function EcosystemClient({
    + {isSearching ? ( +
    +

    + {selectedPartner ? selectedPartner : `Results for "${searchQuery}"`} +

    + {filteredPartners.length > 0 ? ( + + {filteredPartners.map((partner) => ( + + {partner.facilitator ? ( + + ) : ( + + )} + + ))} + + ) : ( +

    No results found.

    + )} +
    + ) : ( {activeFilter === "everything" ? ( {categories.map((category) => { const partners = (byCategory[category.id] ?? []).filter( - (partner) => !partner.featured, + (partner) => !partner.top_section, ); if (!partners.length) return null; @@ -233,6 +372,7 @@ export default function EcosystemClient({ {partner.facilitator ? ( @@ -265,6 +405,7 @@ export default function EcosystemClient({ {partner.facilitator ? ( @@ -281,7 +422,7 @@ export default function EcosystemClient({ )} - + )}
    diff --git a/typescript/site/app/ecosystem/data.ts b/typescript/site/app/ecosystem/data.ts index f3c3ede1ff..e37b40061f 100644 --- a/typescript/site/app/ecosystem/data.ts +++ b/typescript/site/app/ecosystem/data.ts @@ -21,7 +21,7 @@ export interface Partner { websiteUrl: string; category: string; // Main category name as defined in categories array typeLabel?: string; - featured?: boolean; + top_section?: boolean; // Additional fields like a slug for directory name can be added if needed for linking or lookup slug?: string; // Facilitator-specific data (only present for facilitators) diff --git a/typescript/site/app/ecosystem/facilitator-card.tsx b/typescript/site/app/ecosystem/facilitator-card.tsx index 4017b27700..f816c9fbcc 100644 --- a/typescript/site/app/ecosystem/facilitator-card.tsx +++ b/typescript/site/app/ecosystem/facilitator-card.tsx @@ -7,7 +7,7 @@ import type { Partner } from './data'; interface FacilitatorCardProps { partner: Partner; - variant?: 'standard' | 'featured'; + variant?: 'standard' | 'top_section'; } export default function FacilitatorCard({ partner, variant = 'standard' }: FacilitatorCardProps) { @@ -18,7 +18,7 @@ export default function FacilitatorCard({ partner, variant = 'standard' }: Facil } const { facilitator } = partner; - const isFeatured = variant === 'featured'; + const isFeatured = variant === 'top_section'; const tagLabel = partner.typeLabel ?? partner.category; const handleOpen = () => setIsModalOpen(true); const handleKeyDown = (event: KeyboardEvent) => { @@ -38,7 +38,7 @@ export default function FacilitatorCard({ partner, variant = 'standard' }: Facil tabIndex={0} onClick={handleOpen} onKeyDown={handleKeyDown} - className={`group relative w-full flex flex-col border border-foreground bg-background cursor-pointer outline-none transition-all duration-200 hover:bg-gray-10 hover:border-accent-orange hover:shadow-lg focus-visible:ring-2 focus-visible:ring-foreground focus-visible:ring-offset-2 focus-visible:ring-offset-background ${ + className={`group relative w-full h-full flex flex-col border border-foreground bg-background cursor-pointer outline-none transition-all duration-200 hover:bg-gray-10 hover:border-accent-orange hover:shadow-lg focus-visible:ring-2 focus-visible:ring-foreground focus-visible:ring-offset-2 focus-visible:ring-offset-background ${ isFeatured ? 'px-3 pt-4 pb-5' : 'px-4 pt-5 pb-6' }`} > @@ -51,7 +51,7 @@ export default function FacilitatorCard({ partner, variant = 'standard' }: Facil > {partner.logoUrl ? (
    @@ -65,7 +65,7 @@ export default function FacilitatorCard({ partner, variant = 'standard' }: Facil
    ) : ( -
    +

    - {/* Backdrop */}
    setIsModalOpen(false)} /> - {/* Modal Content */} -
    +
    +

    !s6N$Q)T4KKj~#z zK)<@58y*onW7Yz5@mOJaT`Fx%0(a}d6lZK9hE?Nh&LS~)68u7zin0ils`WG%j~1;+ zHQ#Z3RE_o+o2Z1Xt>&$CGPue+lU1hddtr~lD92p^lERkkHB{iE3Ba7P;5?j zfJ#iik!IP!)m3r_=!N1+GX+ksI3SnYA%jy(&(w~>0VV1`cpH3=I2u`WFXCWe+oXZV zN?M*%%(VLXjNap7y>#73CN#VLQ#k&nNw!sdGT{l8xyoZe-QGy2nM4%5(az58v-@Gj z^(@b#DDD=o8m9wl5inIam^C*jE`dxlPg==-)G0Y&F zZBQ9uNVjN*M=@CMAuP+4fsR%guIFC=rpV7;31oSyfO0u6Z{KH6NsR;=zn>*F;@k)8auE8q5r?N#58z%4=>U9+ab$3{ zO{kbf*>^RA>&xlHx~O#`4~*#E#8hh+;$lzdr_&J!jeVKtxS z<~n6Z*pc~`UC@$D=XFzW4;*Tl9A53b}bI^@Ld3X1^&jD~14w>WV>`(@(|X@+jvt${W4q!Gswks)U*0Tlev$c!TZv~8XHLc&Jaa`yg>*|xbrxy4<{b>YG; zB!ZnKWXS=RuZsCDlL~m3;pLQ$^l32oQTK>Xa%);rw@DBI1)yv<-Mc|Q7FZi4()pv<;4`IrI1i`A^p5_$+gNlMKW#PvNF@9 zH&2-Z=j2M#KN8>d?qMD@sFi|{c=L(te}_Mg1o5>vnes5PdNG*_sX*=c?Gqa3b zmnq+`-pHG3hX;Y2`D>tGxNt)%Gz}D)zx5pDzqiaIxmy8vsPF44*4b^@IP7zuxCNm* zB)U(AYrktVpL&{DiR30b(qk4R;h|;0%*i%6UY2StwXG`w!*TO z=+6^u_KogPhHu|9(Zrgws^Hq<=MPe|9Bkj-W{+aH>&rcvBshGzp6n-VgeKBr92{WO zyU!I(wu~r79Wd*My%_n;jZlxwi?YD9BDbGpBAVJ$+)MqmsUOZWqJp3wv+7UowH}LK#Kv$Qe|u3lGQ{ox$9nI^UZ(}+!m8lE@+rJCIJi&j z%};ODn@g@_hz#~n_4tX{GQmB2tb(2R^G zXLwqm$CSOpybV7*TeY*~RZF#m`(SW$8(-CUM(Fo(-!a#z+0fMQpSu`mwwyw4hTWn- z%(sPxEcXXazbJ(#3NUKKn>Gz1DL~jbCKVADz2jU;2j+H;qnNz-z<;`7;CV=%}wHbW(RH^^sk04-LUO|{V zlDaSE5Scn-MR|f+nU8H9)l}VpS~6|>OIOKKx!mCz5d4 z4jYlBjVO$?-|yfhwI~Ly88T*zdFbT}I;l-8MC40r>OFT3I&brH#{2w+(YfgY%m8mz z@X-U3s_zWA8$;Q$xHV7Za;+(kzvI#;+vKv{HT2Npqi@|PkU?=gy6%|#z#2E2K9?Sn zi;A|oZG<5anTrm(krBR7N6NG*-~q_m;T-%Fkvj-mvF}7ad*QbA+dgigK@ax*5yfd3AU7gY6$q4D+^+_ZO5U)wnbDIobFG_0;tzr8 zh)c&4`QP!t|?DeGP8ug*z5T#k63yx}PhN;*s(g2(fzrs78S zbEj*51gWGhBwN0r{W6`jfF8Uf zTl-+v7_9DYS7j3S2Bqnq;zte*_1nbtx1{Or6A!*64K8Qj60g>lG`A%{q|=h`Up&71 z`=ohcoU{U#xQ)6ucbq%+IWyPr(@$JgDQV%xUaKcw1v(@~lM7+WtMgfhy-zO) zU&@-2V#}Nn>L>5Ey`Gx+-FEdap}_XpT-P14H;m7$I@+s?#nA^BB3vKp$W5Kd%Qt=Q z>DV?#+#nJ0@0F8@bC&RX%W;mMVwf0>qdFc)G-urxbsS_pX1%ulC=E0kY#%$&@T)l= zhRTP@A#dxp-^6Ad?bs6|XJ|FFxwk+Y`Nq#rs%7c4(dxWO%jhM`qUaQo&Eu2f+qBfo zGfF-wJZo%eT(JT-hIuo$3Jm;vZWvi>&VO;T=S?b3HJfubP~?&~Zt@fP5aeH=k;3=G zEHda`yL^x^dBsy63X_p1tX2aIhZ=$}Ygj67uK&a(pBcLzs~%H>Hf8!%pJcOLWljyD zAL5-;=YFJuzx{5*(&B^UHO^uUOidYZTl1V5X{}`Q!cxk0*UFlCujDzqAI{;aq^M-i zg1X-)zv(w$P@DSOD+>9=p>G&{eTS(R6iuWM2?>K5-9d<{Eq00u%X-yc;vBtg>SL;o zH&R}x8NbS?VF*zphjRU8x1ik=rYsv)p33LQcwO6>unU~UD(hH;Y3WqsDa?Dlj>x5j z_3BLTt$;YfWD*~`h5v*3eA#D@y?eJQ0k9B5M7w;qz;_PvzquWQDvz`$j(SbOs%umL zR!~nB>7v$c#>sMd2aXs&Spp`!<|H$#cKoB2&>xc@fS)C^J({JsM2HF*=mi$&IXP;g z%^6M}n*ocpHjv!ct3&QQH2c@6j{A*yY6rcu#%$$ybFJ`;=Ve`;rS|4WjsCz=;Nhn~ z6Lr#L_Xq+AP^7@|7uTf5g@+o3ie2|IQg(2YM^j3K!`{lhxetCqcENb4VnZx{aRBg< zw_LMGR=O;!3#aared!BT`!UXOiJ+I`$lQD@9e(~cs@5KE&ukE-Rmt_2i6t9j%LE(! z3{dAMf|m?eiHpkBl?Mm;dyzqDjcihF^#qD$DxQ?)whTDd2=jC#czr=wn_X)%@m8u3>}3vfDd-%+jEm0B>Mt;FayoTLND8nG(f;V5y+w10vD``wc-bQjJHBuLiR!DBB~ z8jxJEtJA8MW!|b*nd4= z<4LHvH0vsENTf?6QqQ=+{CoDqf{A##$`8NX$_*T(U}tvg>QtM?tIetc<@~(-xA{xJ zUtxm!UjKgkJmBidb|lwhhzJ7O2~HOBy(zMPJRspN@&I}we`=P=FlBXM!@xXcNa{v% z&`$7$H}8KS?nxpAX^xuH@P`=V~IC_tt( zrl0hb70SdVD(>81sYZ#cFc99T)7kHj+qjW$2LXN6{zt?uM-aQQJw;ac`P=f26^^ z$SFc`SquUWK?Uov^N#U~+OAjfkCy)37g+lbgh+$l^i>J+Iq4_0HJOhz6K97nhi8~V zw;xi-Z%6+PTRZuhjGB{9=~@j>+UMdCVSn+4|J4G?=bP>5-)9vj0d>3q7qnv_KI*}g zL#V;0=I%^%K4HGr$EQS^9ZxQkq-C=l+48p+2H@skj>YlGd1Dlnj!t={8*yn;IV1FC zkO%C4MilhIrC>1B$L^{iqDCB zX$2Oe<1SnZ=^66{=f5StlHRVPAFE6i3cduohC{g^J-;G{R@-T$yZww*_F;eB8sv{R zjH55xLm`*dm$<*PwnnX4!crSlWYHd;cPXg$b|dJjBWR-2uH+MMfO8TGe&KUzgpuPX zTp{LI?Sw8+gic;pz(xseGd8y;jMC3zyEDrfBw&b?~{O1o*Ar!fH{v zu?r4Dg=m7qTy<+CTLAM!FqhJ06?k(n)gB0YfI#V_S=e}qX!V~E(L&aW244d|UM)R# z7X1^c7|F+HTUd`8Z3ggLpGhBGi7zT{dVL4^^^4#U33m_g5A!noz#9yr&CDEcoH-gU z#vEEnx?laOwIGC^1r>AL|F!ySQ>3n<>HYYwz6gK$5%ZCaD345a>LU>LVCHnGE5&f8 z(LVjlUe)^SL;b-ef~*kwJ1>xRJGE#m%(_^REe1!8tRx#!FyHj?wiZf9-@A|0=Bhc+XLv ze`<@78*nz<9lS>PE>)ctL5@p0;zyOHh9)LGEcWE0?S;q+2s53b<}LlkQA_~o$WDKUA0 zpYSlKsORd7NLWil_O&nC1~*j#Ga`^TK6q_bGZeE_ze;7)H_V2cVlsrl#QCNmW=JvW z27MVAH^b_CGljH%A=&YHsLI@!0Qb@;yMBS&Mil49-BA2fMF`Or0=GfKm048@Ywem7@ z^}@IE)L<+!UP+Xr7L(WM`GPZQpulQ){>wLy|3IfTcaMIAL;+~J%i5ox#HdyFE*2UN za92;zceCCRXCRgBJJp@Z((>OGGk>F=(?0s`yb;AUei|lEcJO;{@B-n?k5oWZFx_(BNK$)lk@0QXIUuwkz==N5$neg`(VJe^~(l$SX zPkCf(aj(zKNrhCxU&aireQDr%aM=aah*V*-_*Wa~QjYRZ66Wls7H4h>YzNq+DGY8w z;e*BkmkN$?4xAAzt}0`Qdy1-KTxegJ_^x{ODL=QubDO>2=(}baVQynKhEazfyKOHD zQkTOl#k36nH0F|Q+sn>Yy#>v?hTdX&nx18~THdExP^Ol@W+fWVr7f~{K$xN2xeq3j ziB@W>ct{7d+?kJQ*@9wurnsk_Q+lsuQc}TnG73sKir~m&Et?w3q_>5zdb%l@!>&l! z7+c%4@J?7S8Cdftn$mG$)h^_1&Gq@rmCCs~6Z<)oCLW$TNd~89^zH?r_-pmtPi)2N z&0XtKlfe&LFlY7>glQB<1J5B3+~MibwRm`vPB$ehAKBx#ThaMgbZ98TLn-!DP<183 zp*%;X1am2?7ny^3s~BVBA{P27J6hrdWh&wX6zO2F5nf;NXZ77~)(S>chv{IOv!_IpRoF!zU!` zu{6dh2;U;2^XiZr{p|@o`=7iyQ`T9B>C(cFar^fUr~H?14lWM9jWN8kd@@+;;!`}$ zsz*-OcV*Gc z!fyV(VIRvU=ECz}Hh-RE>Ut>b<2)Uu-g^5Kt)EO;l1y|`SIEo)7dzjbX1*xuiMM!`_K4RoL)E1+mVRalKltl4fRD72(+l_SX=QUe%S?w1dj0KU_Uu>0(Pwy2Zxpp?acf+U&wVqp{^kljy9cI18FI;1@Q~hDSfJ$Po=J%Rv3LZZJ zRP(BtNzA*aXhngA8=Y2&M%r+BHA9-hA1&|Ul zX15uW9Out$Ngmsbr-^J+H*q_Xz53$)*S3BXTlduiKwLd?%>kmBt;hfq{$Ifs6sQig zxuwF>hf84`hy&4QA;qRQ&pJM}e6G&;j&?w~^$&>_NiZWG~W9PPk^PF!ZQo8~x)Z=9;zoPr}FNHqiY>wrv-%6@Qix!QDneQ+D6`3AQ zeb++#OzEmTMi@a)m9EBPX~XN^|G(6*Sv~C(T@cyVq>({-`dEwQb1OT#6~Ytkg6y;j(7AzU6A(%DT@P;??4@!n#*`A+A&y&7ZBTkT(I1Dylx}KkQ(6b#L z9IkS1Z~wFRUtqV$TmS1@@)4j&$(OYr@>sb6tr@oItqg5D&4k`XZCf3CctFp!sBq~# z_?k~PFNkXt##loGwwK23z2tla09K(!eRsL1a()+I86R%M&Wg1aZK~|;W{Wn{P&%Ls z@$vX)@eXyLgtV5EhSwgbQQg8nyKt5@uNZg^l$*cmTnX*fJC6!4xz=GB=J?Prj+?-` zQ1tIu(n_kL|Cq-Ok#*s-r-Muvs~Uu=kO_Xg&F>M4khAKlQFXt>wY(fK!zYqI`VUkB zs!6@;E`%m)lnagkM|0-)l*nKJ5zG_I{z|%jpZ(0M9;hic9VKbaaNejL!244em*)lBVG+nIg)o^& zTiWhk5Osd4|E7YS6Z*A3zI|2FC8b?Q`4SNc6EAsJXVlEs#YPVd7T*r~ukH@)=?l&E z{(Guw*(m#{_9sL=F9W`n&)32g6Jgq)%At9QGcnm0YmU25obD>L#AtwuySLlR`k1e) z9Fc@Gf|N5x%!17Z_Ldzjs#=iu3IN0B^UdT6e;)W! z)mIU1hr&fW9(mVCE_#p&|K_KMR28C~Z*AqX#>sS8G;@2R7iC^#{0FjLyv=3-IhO_j9XcedC%d!@1w5lmS3g#+q6hp=ZqR0* z=`ilkf6XQ2Ox-J9;^pHSSkb$sFkaYgMTn+6qo+DuR=cJ>F2%xVQ?wB&q=STxOAxB_ zYh%5i7sW>`9h%Ruh(^q&v0wiYvXXr5eGp^J^v7!;y1(C_8tq_cLg)R36zyn+{DFug zmgk}NR$^^sBI%vEHkZ-6Edw)G5$GsjX{UaN=T6EE4X;5uy{n*B8)^9TE@JWWV+@av zK#ITr4EIsi#4jFFC)6y|q{)%jvyNAB>~llFeEA=#E`Td;@Z^fV#iqB4ZwJ+pl9QO? zw^4*pu$z0b5W9}sIKrKpmpQ`Jo9*;9o;SQJA$2Co?|4;VSjEY74E(Wo6KK-#g{3gMfggax}Gm}>I32sIOS`H2A^25Pfg&E(Ap=2l;UP_RnC z6R)7{S4tEAzWiDB{Xx|=p_)S_b_{|K_D_2#-jxw^r98TNqJP>SVzOyjb+TjZ{#<`M zWMGN^Hpc*F4kPs+C^-JwTSIxe5av2c%JX;-YO%1tBS^Q((%jn1cGvpjwldiS-q0-Z z&5lVk;cb$(oYmikE|H(UlxGm0tOJo3-^r#`vdJLYn`8=?fRo+l$6Qq~#ygnH(p&(X z6)?CKo(zX=O``0TJjoTAbB}u-9mcHsSsvcN4Bo}K3kq^#a^t%x)3P7LSy%KWe>lf$ zr|7FiwifcVw=74N8Xk^_U5gZ0Lz^Gus@+@CC%Q)X*5&rd`5o@Yx_x_2B?KcGMqhT3 z9Xsa;Gh->y&-KK6GQ}v!pYJX8w&{`i+czebRGbnI#Iz9^^LT0A3+g6C7gGmrIh zbze(V0f{U&VjGF4Id5Z*tOFAGYK7zzp^k*}nWAm{m}W>A z(It&tI@kQcqkHNMKu=l?%$&MP>Pxs1RrQLdba?*V@&&ZH|G~hjIMOjCp(r)Jo+bx) zF3?tjj2OKmJ%Kye$7zdoK$u4lRb6v1Uzj2HfvoK4s zy;mYZqXV?r-}9g3C1w-YH@;wBBJ;oPehW|jHexfbRJlu0NsWx~P;83C7m;2AY24*yzKKV$HO|Iv> zR8Ux~Z4A_*(kCEaLovv%354vw8Z|X5QtBG8n7@XDU^-Kb)+`fuC^hY=X@piywAeX{ zn#q^4PDbUh=Qdni^+g|~cnC1lchi?@9Cq_Ob8Oc>?Bd7*hZR_Peusy?y{KnUPuMET zC+>@?p_WtP#{3Wuhgst*pyv@8`QL+==LQzgA*cdO&jYd@5b)3=J(_lOX+i`x#2b06 z{kx;AK4&~Mz|tK4LrI)z1{K-LtzP)tVdQbk9d z!Dy)=(&63*+^eX{91bYY7GPzlv~L{Dl2)+m?OLDLFxz#n2v7PV{L_?@$uF8pD$+XA zuz`-d;5GeV>!)n1Aaf^medBD5MWVO^^$1+%i`^LYp6$h_+#=7%-s^})Pte!B!%1ff z@sGbExauu>JtzqVwB^^u(kv1RKUp=<}=FroeA8+*CmlN5EYy&{<8HXkuj?>X~`upI-61oKbkh_ z+asawz=l*)-W&P#xp&RFdv9J#B{$xp&HQR&N80*xwp^Q6?y3eN#hJ2|xz!)VWk93FSw&*{|$d1+8SCo5z$V_c{2y@W@8iPH_w-=d52n z5uNCQ4S-CgfeHu~4V_%MKj&H+k%vHkW70TT{NORP{wwN`9p$h*XjDNnQbhXxYVFZ# zC|HeW;c&bFcM*db(t_uTu?tAtw0Vd_(WdTo^@Qo~O1C)dN z3j@X`RTWHEBt;EU-}nuKAZq>^{zj^Tq+f)_wy=KDR-8s|4x<9u{8r*APvtwY)vWKm zzV~ZrKpgvV38Vhd)-2IR>j%KALWF9rwi2#@_>Jpydgo%G-zG~LdGVLTD=am|TC#3n z>Dp8*GXB%<4n+;eJM8TCLYo{8ek5<(>OqTDU^j-TbyIQ=Rr~E}C zN1uh5Wq94ZxFD3r{YoADyhQRtOZM8gqnCBNbvt&U+ki76cs16n-`eU$rF}qFM(c+#VFq2UlFHsv2n{*e>Q+8`$k1p%-x`**KB z)0~`s=IL_&FsV6&%!8Ck;{Co@e+HSM$cH(Y`g}H=UzA#eF1;0?bFCVtk%T2~s@D zeD#DGmh)FliY(GpZPQkc)5Ul}Lh{@t9_ee!DV=^ff*^67*T z{T`H%kgUqqB|>dV`s12DE)I8#p}KbU#S4pU&X+#-M@w*w3S1_kXyy%^V<0O8Sih7H zUNUenERE`j!E;8}RFdW8%mz=Z!viWPpLtZ1=_st{OQPUZPNvb!(sc|%E`iyM0zlO#hK+nJ!h{T+q@2@hk%Tky@&)9Y&A%)xp8Dhv z`xMM9Y=HVuXWMc;O+Z^_X0L0ZjziEMJ$FP>YDwD5_iRd+ zOW?hUanj-V0@=9hZ+ksO+8j5rFolE#RpGgJz(SfVE3_98kfOKO#QvfF!yC;}#!?UO z>M!qIi5ZQMV@4}+r9^!nKbaKXftIL_9d8)`E|9X1>S1K!eJxiw)PjFMMHa255*WPP zBIgh^YWrfgF`leM_#|BKsq?<+{_mf{(D3f5K25iR45BWuE_pO7WQOb+0=W|X5APA{ zElL`;ht5KdyL6`?2$Q(CC#hw!k^Y7w4HX?(JXC2l@5zUQs8~PZh!lsU7Y|N4BqT5H zrc{z}DYQif^&)xAmOOqrqf4j|e*pNreK?@1$V{Lxo|78?o3AoxtrhprhVE%T-L=_( zCRYOGHYIg*ft62qkmL>n&_n$4m1R$5cvzi)7s9#Jle*8)uiTR#dA)Eq#$8QC;6e`A zm!PP}C5QpuFP)}9^!=#fG9-<{nf=h;iW}xyS>+<@vyQq)BIOJ8UVc@_{5Ma!M7g}2 z`Pz3N5uIm|bWMl&e-vc56%*1;w5M#=5aqUVUguE%t(VWJUmHOF9aGHnysPgFMmJfI zi7cLE#ALg<`ZZbzM1(L;(JpWr=V4g7A&9eb5@`@s@;N<@5<4hBQA71_oYJ2os8>7( zWFK^9Tj{YX%YSM+FU`2XFWJk6$%=FVW1W2ZOii3I1D^(3IPN}s7NlBt*-Xzk1L_h$ zPs8e1TgVoUx@-QvW1M%{h-*S`=AKL1G@c>)PrPCV*RJ?cJN z^NGuM3H|6ItkmWl^Vpsa>i~~dG4FfDrXsP@rN0`*lVx@TW*$1AEOnXPGH6*gY+jL7}V^*35Dx%6y>qvvglaqMuAf8QaLQ`5i8U?~Vzhu+wY zn0jd(bGl=guVE!DlYxC?_0{r*kJ3ZVNJpb#MMA%v!l)Yjx4k?+WS%vsG1hR~d<=ZU zMRVxFx0@rMAXXJb?kmq})zEb;XP$>*?1C}Bb(6|a0U8acY5nZWFA(&x5l*p=@H80h zmBPxrd`INNfy!GAePod}U+1=VsCL-x-V{}`f|U}3D7GP>TO~3SrB{AGx>tMhw-3{{e(Ybq_mhBFI$3{G_s#R}fe(1R2MwIjh z$em|ZNs^*}&obwee?$Lj&4jM$U8!ui-BL%9W5pxGCN!yln2wDqEw%D{X!XE*)mp7G zu4SI_VX@epF13pcg|>X{noW|&)w-S<=Sx*B05#2%Dpr}^*n9xW%Z|`?wBwEN2z%$w zirWc1VaBM!hg4|@*UNi6>b)1D24sKUV1CsyRU_(Kc}r7rP0{b#%W`F0II`wV&Hd?= zl!3`&-H!B4uy%!}Cvw@*SLF%E8NlL$tJf>4e23jR=+CSkD|hE@PPvj3MOZ*|(U@DN z+5*lSQ`cU+*+t$O3Q>hNC#om956x10?8CuEs4#+AOUMkt=eavO7@otitUOCdW7jWz z+Pz$9@^H9jw54r2aj)j*OQa450};Z2OP$)2*XR$)yC}Pk0hM9 zdQCWkv|>3*T(q0~NDpF*^VH*tyBj5!yOf+Z4+$c#%!y_X%w^*G12i(^YHu9$dK=j6 zr=^N+CGbJkO8J0Ey8Y30mebK(T-7?R(~U-a@0)I=wn&MVYWNgeh>jv5xAA(6n0~KF zt%q*;?{KmyNW^pYicWjDL(AWBB_8*z8jgV|)dl+>ehDLx=**5__4lPhUA8Z(UMvfY za6SLmV?n-ykERjf6IMzXr=*NxY-A_}qqK}rIpO(G`Yx{Kq3bY+o5BhvhtI)TIRVg5 z6c@kXID5@TFUs|oGtJCIz>|+s+ovmffE?YX^?N)OMP8qRBS%}0`bWzf@7VbKxG6-3 zu-|(ASk!8P<<~*&pmoh7cd5+e`jptCN*2Kc;A3+zhDLJVP54Q)A>MlHG%mH8$SwPB zLW(t;EO~a$xvV!s_Z$A5n!q{DMUMjh&M0?G;8vuF%;?>xTUVHUFQE5A`biDHpI2pu zOVy9E&5~Cti?+F${{0cUJFX@Pw6Y1xb%D|CZ-V6Qs#|_9|3`9$PTU|MG2ZahO^WE!kg?Ghm)$Uz26j)nMPbE}Ny$-j1!8B*1<3;d zzeO$a=F|+Gby{#Vpm;tDgcG_z+=?)JDS4HW&Pr_#sX6_}ws_h-wjrC)MH|)A1l$i2apek1uDcO5N%3rE^)&j-&dX#4OpS z{WUcpj>%5Q|K>+b8foe|gw@+cd|Zf?7NQ)pPQKOff<7NzDan%tMzXN_|9B$D;QjDt`+WHmO= zZ@7`*7LOSb$F;r-a;nfIr!riyl_#a?Ge2ddA6bKCnWcUDMy@*0%lS5}uuDM?$alDW z%othJDT?-9-G)~et~H!SenX3u$;|~-$9~gbBZmZ0a2jNDNY30;2<>oO4D(@i_V|@w zTB78KtNiJ6kzu+!vL^f5Xn3LjA?h2JcF+~M6w4dQgR@e> zoz;B;;G@wsWK*|DOfw;=8ke#3Nqf+%{2X6q75pdNCp7r&bF z-?v_Kq)8fn?ZbiXzO-$S186fOH{|<Xs?@H$i-=wSY{|`Swz`j<`sRO1T;dZH=N?6KbQMFUt5z_#b%Sjo?`r!d~ zYS6H$7?P?O%WYGqt_dAT+nnkCV+&IJm$Q3mrnN5a-GZ!=euDuSjEtF zcbxGc09gA}_XGS4D{Yomn9FR$eRazlTo&9%O(UdXN!&^kxlC!$3m-n}^$$bNFDW0q5=qDFdhdF#PU+I{tqx(FL5&Q?=I>twL4{w3tNzFJXjsP*vE* zeR_i$eQ;D8D!#!BSjYuAi8CY-sKoDxIT51{;yYn0W|LqJhu5K>Tswv;fs}kfi*${| z9^LUr1B1r5$#OYuvyH&0Z?eM#oq%-^P94=6+Ug`Z{OK7GM!6hj+bxf6pu-PeTnhOE za-aQoE{r`eGsxyWG5wp_a_=DhLB`&14!a;hy07iO^2;CnFOwW=bY4Fw5kE&6W8}An z*3lpP=_1AY%He_^!1VMOA;yvc8iVVCjaV!FaNt$&Ti!A_Yijpa54DDP3vekPn0jC( z@ZFn3gJQPH8Me6jDqocp>W5M4F!kJ}S+p?+3~7IvGk|h2f*A^#n8)1**8rEE_|2v; zbA=rz0vMR@jig6>Wg$;f+Xvm#rajDkaV|lOz1S&OF3}K!{P5IOR?vN{PGn%0u$|h@ zGpyK0Kqm;iZy#%pfGI!air0nV?4q~K@-81555=&YpWOaTTyiIgMoT@59M9p32MU45 zqLoT`^(1Xjf(c=+nq!g3t7pT)3U1uMG2UQpU0d+Ltr=CqvoqL2ue3}9-?w}j%5*-5 z0L*12gyo5`3fDVDk&!XD3GW9LR?}rw63JeWTT(u_%Q9#A^qehfLY5Fo=sJ@fv1iO% zbQ4=o=JoW#U1b5d%F|~Nou%^o1A!uY^un82lBPcLf=Z7-b-;)tAP$7bQaj?cvrM9U zb~v?y1S+{Vd|11oLmj{N#e!uU?f(EBG2pm&S6ZJ5L-E$i=|taKJgH_}+<-GD{P1@w zx(4?loXli0!`?%Dd~&J2Cck!zJq!&n!Pkz|dmLwdwu*2jCP+WKb0 zv|zCJS1=#cU=>noPzbD5{e)IrpDY>buw|n@jf=6pUHV!ejXi6 z>VcjKjqXB$0On2{?_jkC5&+48fsyqGOj#S1@?C&?V^crng(XS`%}Zq}+7UfF90c1W z=F8SU&|=;X8TnLS&b>!E%I_=3zl?+1O_UF~hs-fLW0K0m3tWp-9igDi5IbUyapPP1 z8(Hb2l*|3QEu;o@R_e+Kk$@A)@%at#CEn2E-tja^A9D5Sgf2H$Bv!$uNX7T@XuFZd z;glSnMQT_l%66b~KiqN{D_v!+LH*QG?oc(|^p3c%qgVE_^z=B|{{VEh*6e=1xHURt zVCEplLO!^#vD!Z6o}lR%wG>A2wTDPLgZ04uwAU*5TDix`jv%cGURzi37x^Q6ZOd%H zzzDM*<5@q60QSQ=AWDe#*U%oBk=w2mfIw|E&PKmnTWGEa9H6?uNB;mJg%Ez4kH-~m zP^P2^AOVujv8m58am4aoKbL2Z@;n;_oIYI#ZIsvn0hH$&oEr<99i5)mV=~N1W+$%W znK%W4mGtTUG{U0U@<;?Y5GFHR{{XHwlMHiM?;0E_0vLA7>HPA+JELiajN);wnn{u} z%Me;gQV0Szk)+Q<)-ab;!7i+=h)4%%)N49+I4scLC-)fWNn=05A3w#qgl(2Kdv`D- zFXA)C#!aF@goB-kJW13b^Bn6=S!MF!J4XW0728fHd&hDY%qjs=(4^3}ys zWU%W8pcoe|fTFh7O$f>){e3V{q!=L=Ksz5(hL3CoQrbsz{{T!?cOR2yACp4^P1QNA zmAbOJ!3Hp1n@qIJjSpC9@9TqQpV_s&$zte!xE~<-=x%^$f6E^)65`0D2CmGEo`B