@dexterai/x402 1.8.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/index.cjs +15 -3
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +5 -5
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/index.js +5 -3
- package/dist/adapters/index.js.map +1 -1
- package/dist/client/index.cjs +22 -9
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +6 -6
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.js +12 -9
- package/dist/client/index.js.map +1 -1
- package/dist/react/index.cjs +24 -11
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +4 -4
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +14 -11
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +30 -20
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +3 -3
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.js +28 -18
- package/dist/server/index.js.map +1 -1
- package/dist/{solana-BeGAqPta.d.cts → solana-CfHuiW2H.d.cts} +2 -2
- package/dist/{solana-CQD9yMju.d.ts → solana-kZcwbUK9.d.ts} +2 -2
- package/dist/{types-DYLi7SuF.d.cts → types-BQvaF8lB.d.cts} +7 -5
- package/dist/{types-DYLi7SuF.d.ts → types-BQvaF8lB.d.ts} +7 -5
- package/dist/{types-B477nBpg.d.cts → types-DmqH9yD8.d.cts} +1 -1
- package/dist/{types-BWnUAPvD.d.ts → types-ENcnkof8.d.ts} +1 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/{x402-client-Dk9q2QQF.d.cts → x402-client-BDaOwfgE.d.cts} +2 -2
- package/dist/{x402-client-D9b3PHai.d.ts → x402-client-DIcp-PvX.d.ts} +2 -2
- package/package.json +1 -1
package/dist/adapters/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/adapters/index.ts
|
|
@@ -136,7 +146,7 @@ var SolanaAdapter = class {
|
|
|
136
146
|
const connection = new import_web3.Connection(url, "confirmed");
|
|
137
147
|
const userPubkey = new import_web3.PublicKey(wallet.publicKey.toBase58());
|
|
138
148
|
const { payTo, asset, extra } = accept;
|
|
139
|
-
const amount = accept.amount
|
|
149
|
+
const amount = accept.amount ?? accept.maxAmountRequired;
|
|
140
150
|
if (!amount) {
|
|
141
151
|
throw new Error("Missing amount in payment requirements");
|
|
142
152
|
}
|
|
@@ -374,7 +384,7 @@ var EvmAdapter = class {
|
|
|
374
384
|
throw new Error("Wallet not connected");
|
|
375
385
|
}
|
|
376
386
|
const { payTo, asset, extra } = accept;
|
|
377
|
-
const amount = accept.amount
|
|
387
|
+
const amount = accept.amount ?? accept.maxAmountRequired;
|
|
378
388
|
if (!amount) {
|
|
379
389
|
throw new Error("Missing amount in payment requirements");
|
|
380
390
|
}
|
|
@@ -402,7 +412,9 @@ var EvmAdapter = class {
|
|
|
402
412
|
{ name: "nonce", type: "bytes32" }
|
|
403
413
|
]
|
|
404
414
|
};
|
|
405
|
-
const
|
|
415
|
+
const nonceBytes = new Uint8Array(32);
|
|
416
|
+
(globalThis.crypto ?? (await import("crypto")).webcrypto).getRandomValues(nonceBytes);
|
|
417
|
+
const nonce = "0x" + [...nonceBytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
406
418
|
const now = Math.floor(Date.now() / 1e3);
|
|
407
419
|
const authorization = {
|
|
408
420
|
from: wallet.address,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/index.ts","../../src/adapters/solana.ts","../../src/adapters/evm.ts"],"sourcesContent":["/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\nimport { createSolanaAdapter as _createSolanaAdapter } from './solana';\nimport { createEvmAdapter as _createEvmAdapter } from './evm';\nimport { USDC_ADDRESSES as _USDC_ADDRESSES } from './evm';\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ARBITRUM_ONE,\n POLYGON,\n OPTIMISM,\n AVALANCHE,\n SKALE_BASE,\n SKALE_BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n USDC_ADDRESSES,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Check if an asset address is a known USDC contract (any chain).\n * Single source of truth for decimal inference in the client.\n */\nexport function isKnownUSDC(asset: string): boolean {\n // Solana mints\n if (asset === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') return true; // mainnet\n if (asset === '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU') return true; // devnet\n // All EVM USDC addresses (case-insensitive for EVM)\n const lc = asset.toLowerCase();\n for (const addr of Object.values(_USDC_ADDRESSES)) {\n if (addr.toLowerCase() === lc) return true;\n }\n return false;\n}\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n return [\n _createSolanaAdapter({ verbose }),\n _createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n\n\n","/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n * Mainnet uses Dexter's RPC proxy for reliability and zero-config setup\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.dexter.cash/api/solana/rpc',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields (amount or maxAmountRequired for x402 spec compatibility)\n const { payTo, asset, extra } = accept;\n const amount = accept.amount || accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n // Note: decimals is optional - we fetch from mint on-chain if not provided\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to get decimals (required for TransferChecked)\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (typeof extra?.decimals === 'number' && mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains.\n * Mirrors dexter-facilitator/src/config/chains.ts — update both when adding chains.\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ARBITRUM_ONE = 'eip155:42161';\nexport const POLYGON = 'eip155:137';\nexport const OPTIMISM = 'eip155:10';\nexport const AVALANCHE = 'eip155:43114';\nexport const SKALE_BASE = 'eip155:1187947933';\nexport const SKALE_BASE_SEPOLIA = 'eip155:324705682';\n\n/** @deprecated Not supported by the Dexter facilitator. Use BASE_MAINNET for EVM payments. */\nexport const ETHEREUM_MAINNET = 'eip155:1';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ARBITRUM_ONE]: 42161,\n [POLYGON]: 137,\n [OPTIMISM]: 10,\n [AVALANCHE]: 43114,\n [SKALE_BASE]: 1187947933,\n [SKALE_BASE_SEPOLIA]: 324705682,\n [ETHEREUM_MAINNET]: 1,\n};\n\n/**\n * Default RPC URLs.\n * Base mainnet uses Dexter's RPC proxy for reliability and zero-config setup.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://api.dexter.cash/api/base/rpc',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n [POLYGON]: 'https://polygon-rpc.com',\n [OPTIMISM]: 'https://mainnet.optimism.io',\n [AVALANCHE]: 'https://api.avax.network/ext/bc/C/rpc',\n [SKALE_BASE]: 'https://skale-base.skalenodes.com/v1/base',\n [SKALE_BASE_SEPOLIA]: 'https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n};\n\n/**\n * USDC contract addresses by chain.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [BASE_SEPOLIA]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n [POLYGON]: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n [OPTIMISM]: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n [AVALANCHE]: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n [SKALE_BASE]: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n [SKALE_BASE_SEPOLIA]: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, extra } = accept;\n const amount = accept.amount || accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a random nonce (32 bytes hex)\n const nonce = '0x' + [...Array(32)]\n .map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, '0'))\n .join('') as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/index.ts","../../src/adapters/solana.ts","../../src/adapters/evm.ts"],"sourcesContent":["/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\nimport { createSolanaAdapter as _createSolanaAdapter } from './solana';\nimport { createEvmAdapter as _createEvmAdapter } from './evm';\nimport { USDC_ADDRESSES as _USDC_ADDRESSES } from './evm';\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ARBITRUM_ONE,\n POLYGON,\n OPTIMISM,\n AVALANCHE,\n SKALE_BASE,\n SKALE_BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n USDC_ADDRESSES,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Check if an asset address is a known USDC contract (any chain).\n * Single source of truth for decimal inference in the client.\n */\nexport function isKnownUSDC(asset: string): boolean {\n // Solana mints\n if (asset === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') return true; // mainnet\n if (asset === '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU') return true; // devnet\n // All EVM USDC addresses (case-insensitive for EVM)\n const lc = asset.toLowerCase();\n for (const addr of Object.values(_USDC_ADDRESSES)) {\n if (addr.toLowerCase() === lc) return true;\n }\n return false;\n}\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n return [\n _createSolanaAdapter({ verbose }),\n _createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n\n\n","/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n * Mainnet uses Dexter's RPC proxy for reliability and zero-config setup\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.dexter.cash/api/solana/rpc',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields — amount is the v2 spec field, maxAmountRequired is v1 fallback\n const { payTo, asset, extra } = accept;\n const amount = accept.amount ?? accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n // Note: decimals is optional - we fetch from mint on-chain if not provided\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to get decimals (required for TransferChecked)\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (typeof extra?.decimals === 'number' && mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains.\n * Mirrors dexter-facilitator/src/config/chains.ts — update both when adding chains.\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ARBITRUM_ONE = 'eip155:42161';\nexport const POLYGON = 'eip155:137';\nexport const OPTIMISM = 'eip155:10';\nexport const AVALANCHE = 'eip155:43114';\nexport const SKALE_BASE = 'eip155:1187947933';\nexport const SKALE_BASE_SEPOLIA = 'eip155:324705682';\n\n/** @deprecated Not supported by the Dexter facilitator. Use BASE_MAINNET for EVM payments. */\nexport const ETHEREUM_MAINNET = 'eip155:1';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ARBITRUM_ONE]: 42161,\n [POLYGON]: 137,\n [OPTIMISM]: 10,\n [AVALANCHE]: 43114,\n [SKALE_BASE]: 1187947933,\n [SKALE_BASE_SEPOLIA]: 324705682,\n [ETHEREUM_MAINNET]: 1,\n};\n\n/**\n * Default RPC URLs.\n * Base mainnet uses Dexter's RPC proxy for reliability and zero-config setup.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://api.dexter.cash/api/base/rpc',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n [POLYGON]: 'https://polygon-rpc.com',\n [OPTIMISM]: 'https://mainnet.optimism.io',\n [AVALANCHE]: 'https://api.avax.network/ext/bc/C/rpc',\n [SKALE_BASE]: 'https://skale-base.skalenodes.com/v1/base',\n [SKALE_BASE_SEPOLIA]: 'https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n};\n\n/**\n * USDC contract addresses by chain.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [BASE_SEPOLIA]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n [POLYGON]: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n [OPTIMISM]: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n [AVALANCHE]: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n [SKALE_BASE]: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n [SKALE_BASE_SEPOLIA]: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, extra } = accept;\n // amount is the v2 spec field, maxAmountRequired is v1 fallback\n const amount = accept.amount ?? accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a cryptographically secure random nonce (32 bytes hex)\n const nonceBytes = new Uint8Array(32);\n (globalThis.crypto ?? (await import('crypto')).webcrypto).getRandomValues(nonceBytes);\n const nonce = ('0x' + [...nonceBytes].map(b => b.toString(16).padStart(2, '0')).join('')) as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { C as ChainAdapter } from '../types-
|
|
2
|
-
export { A as AdapterConfig, B as BalanceInfo, G as GenericWallet, S as SignedTransaction, W as WalletSet } from '../types-
|
|
3
|
-
import { b as SolanaAdapter, d as EvmAdapter } from '../solana-
|
|
4
|
-
export { A as ARBITRUM_ONE, k as AVALANCHE, B as BASE_MAINNET, j as BASE_SEPOLIA, n as ETHEREUM_MAINNET, E as EvmWallet, O as OPTIMISM, P as POLYGON, l as SKALE_BASE, m as SKALE_BASE_SEPOLIA, e as SOLANA_DEVNET, S as SOLANA_MAINNET, f as SOLANA_TESTNET, g as SolanaWallet, U as USDC_ADDRESSES, a as createEvmAdapter, c as createSolanaAdapter, h as isEvmWallet, i as isSolanaWallet } from '../solana-
|
|
5
|
-
import '../types-
|
|
1
|
+
import { C as ChainAdapter } from '../types-DmqH9yD8.cjs';
|
|
2
|
+
export { A as AdapterConfig, B as BalanceInfo, G as GenericWallet, S as SignedTransaction, W as WalletSet } from '../types-DmqH9yD8.cjs';
|
|
3
|
+
import { b as SolanaAdapter, d as EvmAdapter } from '../solana-CfHuiW2H.cjs';
|
|
4
|
+
export { A as ARBITRUM_ONE, k as AVALANCHE, B as BASE_MAINNET, j as BASE_SEPOLIA, n as ETHEREUM_MAINNET, E as EvmWallet, O as OPTIMISM, P as POLYGON, l as SKALE_BASE, m as SKALE_BASE_SEPOLIA, e as SOLANA_DEVNET, S as SOLANA_MAINNET, f as SOLANA_TESTNET, g as SolanaWallet, U as USDC_ADDRESSES, a as createEvmAdapter, c as createSolanaAdapter, h as isEvmWallet, i as isSolanaWallet } from '../solana-CfHuiW2H.cjs';
|
|
5
|
+
import '../types-BQvaF8lB.cjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Check if an asset address is a known USDC contract (any chain).
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { C as ChainAdapter } from '../types-
|
|
2
|
-
export { A as AdapterConfig, B as BalanceInfo, G as GenericWallet, S as SignedTransaction, W as WalletSet } from '../types-
|
|
3
|
-
import { b as SolanaAdapter, d as EvmAdapter } from '../solana-
|
|
4
|
-
export { A as ARBITRUM_ONE, k as AVALANCHE, B as BASE_MAINNET, j as BASE_SEPOLIA, n as ETHEREUM_MAINNET, E as EvmWallet, O as OPTIMISM, P as POLYGON, l as SKALE_BASE, m as SKALE_BASE_SEPOLIA, e as SOLANA_DEVNET, S as SOLANA_MAINNET, f as SOLANA_TESTNET, g as SolanaWallet, U as USDC_ADDRESSES, a as createEvmAdapter, c as createSolanaAdapter, h as isEvmWallet, i as isSolanaWallet } from '../solana-
|
|
5
|
-
import '../types-
|
|
1
|
+
import { C as ChainAdapter } from '../types-ENcnkof8.js';
|
|
2
|
+
export { A as AdapterConfig, B as BalanceInfo, G as GenericWallet, S as SignedTransaction, W as WalletSet } from '../types-ENcnkof8.js';
|
|
3
|
+
import { b as SolanaAdapter, d as EvmAdapter } from '../solana-kZcwbUK9.js';
|
|
4
|
+
export { A as ARBITRUM_ONE, k as AVALANCHE, B as BASE_MAINNET, j as BASE_SEPOLIA, n as ETHEREUM_MAINNET, E as EvmWallet, O as OPTIMISM, P as POLYGON, l as SKALE_BASE, m as SKALE_BASE_SEPOLIA, e as SOLANA_DEVNET, S as SOLANA_MAINNET, f as SOLANA_TESTNET, g as SolanaWallet, U as USDC_ADDRESSES, a as createEvmAdapter, c as createSolanaAdapter, h as isEvmWallet, i as isSolanaWallet } from '../solana-kZcwbUK9.js';
|
|
5
|
+
import '../types-BQvaF8lB.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Check if an asset address is a known USDC contract (any chain).
|
package/dist/adapters/index.js
CHANGED
|
@@ -102,7 +102,7 @@ var SolanaAdapter = class {
|
|
|
102
102
|
const connection = new Connection(url, "confirmed");
|
|
103
103
|
const userPubkey = new PublicKey(wallet.publicKey.toBase58());
|
|
104
104
|
const { payTo, asset, extra } = accept;
|
|
105
|
-
const amount = accept.amount
|
|
105
|
+
const amount = accept.amount ?? accept.maxAmountRequired;
|
|
106
106
|
if (!amount) {
|
|
107
107
|
throw new Error("Missing amount in payment requirements");
|
|
108
108
|
}
|
|
@@ -340,7 +340,7 @@ var EvmAdapter = class {
|
|
|
340
340
|
throw new Error("Wallet not connected");
|
|
341
341
|
}
|
|
342
342
|
const { payTo, asset, extra } = accept;
|
|
343
|
-
const amount = accept.amount
|
|
343
|
+
const amount = accept.amount ?? accept.maxAmountRequired;
|
|
344
344
|
if (!amount) {
|
|
345
345
|
throw new Error("Missing amount in payment requirements");
|
|
346
346
|
}
|
|
@@ -368,7 +368,9 @@ var EvmAdapter = class {
|
|
|
368
368
|
{ name: "nonce", type: "bytes32" }
|
|
369
369
|
]
|
|
370
370
|
};
|
|
371
|
-
const
|
|
371
|
+
const nonceBytes = new Uint8Array(32);
|
|
372
|
+
(globalThis.crypto ?? (await import("crypto")).webcrypto).getRandomValues(nonceBytes);
|
|
373
|
+
const nonce = "0x" + [...nonceBytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
372
374
|
const now = Math.floor(Date.now() / 1e3);
|
|
373
375
|
const authorization = {
|
|
374
376
|
from: wallet.address,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/solana.ts","../../src/adapters/evm.ts","../../src/adapters/index.ts"],"sourcesContent":["/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n * Mainnet uses Dexter's RPC proxy for reliability and zero-config setup\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.dexter.cash/api/solana/rpc',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields (amount or maxAmountRequired for x402 spec compatibility)\n const { payTo, asset, extra } = accept;\n const amount = accept.amount || accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n // Note: decimals is optional - we fetch from mint on-chain if not provided\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to get decimals (required for TransferChecked)\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (typeof extra?.decimals === 'number' && mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains.\n * Mirrors dexter-facilitator/src/config/chains.ts — update both when adding chains.\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ARBITRUM_ONE = 'eip155:42161';\nexport const POLYGON = 'eip155:137';\nexport const OPTIMISM = 'eip155:10';\nexport const AVALANCHE = 'eip155:43114';\nexport const SKALE_BASE = 'eip155:1187947933';\nexport const SKALE_BASE_SEPOLIA = 'eip155:324705682';\n\n/** @deprecated Not supported by the Dexter facilitator. Use BASE_MAINNET for EVM payments. */\nexport const ETHEREUM_MAINNET = 'eip155:1';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ARBITRUM_ONE]: 42161,\n [POLYGON]: 137,\n [OPTIMISM]: 10,\n [AVALANCHE]: 43114,\n [SKALE_BASE]: 1187947933,\n [SKALE_BASE_SEPOLIA]: 324705682,\n [ETHEREUM_MAINNET]: 1,\n};\n\n/**\n * Default RPC URLs.\n * Base mainnet uses Dexter's RPC proxy for reliability and zero-config setup.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://api.dexter.cash/api/base/rpc',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n [POLYGON]: 'https://polygon-rpc.com',\n [OPTIMISM]: 'https://mainnet.optimism.io',\n [AVALANCHE]: 'https://api.avax.network/ext/bc/C/rpc',\n [SKALE_BASE]: 'https://skale-base.skalenodes.com/v1/base',\n [SKALE_BASE_SEPOLIA]: 'https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n};\n\n/**\n * USDC contract addresses by chain.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [BASE_SEPOLIA]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n [POLYGON]: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n [OPTIMISM]: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n [AVALANCHE]: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n [SKALE_BASE]: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n [SKALE_BASE_SEPOLIA]: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, extra } = accept;\n const amount = accept.amount || accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a random nonce (32 bytes hex)\n const nonce = '0x' + [...Array(32)]\n .map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, '0'))\n .join('') as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n","/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\nimport { createSolanaAdapter as _createSolanaAdapter } from './solana';\nimport { createEvmAdapter as _createEvmAdapter } from './evm';\nimport { USDC_ADDRESSES as _USDC_ADDRESSES } from './evm';\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ARBITRUM_ONE,\n POLYGON,\n OPTIMISM,\n AVALANCHE,\n SKALE_BASE,\n SKALE_BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n USDC_ADDRESSES,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Check if an asset address is a known USDC contract (any chain).\n * Single source of truth for decimal inference in the client.\n */\nexport function isKnownUSDC(asset: string): boolean {\n // Solana mints\n if (asset === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') return true; // mainnet\n if (asset === '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU') return true; // devnet\n // All EVM USDC addresses (case-insensitive for EVM)\n const lc = asset.toLowerCase();\n for (const addr of Object.values(_USDC_ADDRESSES)) {\n if (addr.toLowerCase() === lc) return true;\n }\n return false;\n}\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n return [\n _createSolanaAdapter({ verbose }),\n _createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n\n\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/solana.ts","../../src/adapters/evm.ts","../../src/adapters/index.ts"],"sourcesContent":["/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n * Mainnet uses Dexter's RPC proxy for reliability and zero-config setup\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.dexter.cash/api/solana/rpc',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields — amount is the v2 spec field, maxAmountRequired is v1 fallback\n const { payTo, asset, extra } = accept;\n const amount = accept.amount ?? accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n // Note: decimals is optional - we fetch from mint on-chain if not provided\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to get decimals (required for TransferChecked)\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (typeof extra?.decimals === 'number' && mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains.\n * Mirrors dexter-facilitator/src/config/chains.ts — update both when adding chains.\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ARBITRUM_ONE = 'eip155:42161';\nexport const POLYGON = 'eip155:137';\nexport const OPTIMISM = 'eip155:10';\nexport const AVALANCHE = 'eip155:43114';\nexport const SKALE_BASE = 'eip155:1187947933';\nexport const SKALE_BASE_SEPOLIA = 'eip155:324705682';\n\n/** @deprecated Not supported by the Dexter facilitator. Use BASE_MAINNET for EVM payments. */\nexport const ETHEREUM_MAINNET = 'eip155:1';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ARBITRUM_ONE]: 42161,\n [POLYGON]: 137,\n [OPTIMISM]: 10,\n [AVALANCHE]: 43114,\n [SKALE_BASE]: 1187947933,\n [SKALE_BASE_SEPOLIA]: 324705682,\n [ETHEREUM_MAINNET]: 1,\n};\n\n/**\n * Default RPC URLs.\n * Base mainnet uses Dexter's RPC proxy for reliability and zero-config setup.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://api.dexter.cash/api/base/rpc',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n [POLYGON]: 'https://polygon-rpc.com',\n [OPTIMISM]: 'https://mainnet.optimism.io',\n [AVALANCHE]: 'https://api.avax.network/ext/bc/C/rpc',\n [SKALE_BASE]: 'https://skale-base.skalenodes.com/v1/base',\n [SKALE_BASE_SEPOLIA]: 'https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n};\n\n/**\n * USDC contract addresses by chain.\n * Source of truth: dexter-facilitator/src/config/chains.ts\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [BASE_SEPOLIA]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n [POLYGON]: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n [OPTIMISM]: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n [AVALANCHE]: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n [SKALE_BASE]: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n [SKALE_BASE_SEPOLIA]: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, extra } = accept;\n // amount is the v2 spec field, maxAmountRequired is v1 fallback\n const amount = accept.amount ?? accept.maxAmountRequired;\n if (!amount) {\n throw new Error('Missing amount in payment requirements');\n }\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a cryptographically secure random nonce (32 bytes hex)\n const nonceBytes = new Uint8Array(32);\n (globalThis.crypto ?? (await import('crypto')).webcrypto).getRandomValues(nonceBytes);\n const nonce = ('0x' + [...nonceBytes].map(b => b.toString(16).padStart(2, '0')).join('')) as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n","/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\nimport { createSolanaAdapter as _createSolanaAdapter } from './solana';\nimport { createEvmAdapter as _createEvmAdapter } from './evm';\nimport { USDC_ADDRESSES as _USDC_ADDRESSES } from './evm';\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ARBITRUM_ONE,\n POLYGON,\n OPTIMISM,\n AVALANCHE,\n SKALE_BASE,\n SKALE_BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n USDC_ADDRESSES,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Check if an asset address is a known USDC contract (any chain).\n * Single source of truth for decimal inference in the client.\n */\nexport function isKnownUSDC(asset: string): boolean {\n // Solana mints\n if (asset === 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') return true; // mainnet\n if (asset === '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU') return true; // devnet\n // All EVM USDC addresses (case-insensitive for EVM)\n const lc = asset.toLowerCase();\n for (const addr of Object.values(_USDC_ADDRESSES)) {\n if (addr.toLowerCase() === lc) return true;\n }\n return false;\n}\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n return [\n _createSolanaAdapter({ verbose }),\n _createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n\n\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}
|
package/dist/client/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __esm = (fn, res) => function __init() {
|
|
7
9
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -18,6 +20,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
20
|
}
|
|
19
21
|
return to;
|
|
20
22
|
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
21
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
32
|
|
|
23
33
|
// node_modules/base-x/src/esm/index.js
|
|
@@ -300,7 +310,7 @@ var SolanaAdapter = class {
|
|
|
300
310
|
const connection = new import_web3.Connection(url, "confirmed");
|
|
301
311
|
const userPubkey = new import_web3.PublicKey(wallet.publicKey.toBase58());
|
|
302
312
|
const { payTo, asset, extra } = accept;
|
|
303
|
-
const amount = accept.amount
|
|
313
|
+
const amount = accept.amount ?? accept.maxAmountRequired;
|
|
304
314
|
if (!amount) {
|
|
305
315
|
throw new Error("Missing amount in payment requirements");
|
|
306
316
|
}
|
|
@@ -538,7 +548,7 @@ var EvmAdapter = class {
|
|
|
538
548
|
throw new Error("Wallet not connected");
|
|
539
549
|
}
|
|
540
550
|
const { payTo, asset, extra } = accept;
|
|
541
|
-
const amount = accept.amount
|
|
551
|
+
const amount = accept.amount ?? accept.maxAmountRequired;
|
|
542
552
|
if (!amount) {
|
|
543
553
|
throw new Error("Missing amount in payment requirements");
|
|
544
554
|
}
|
|
@@ -566,7 +576,9 @@ var EvmAdapter = class {
|
|
|
566
576
|
{ name: "nonce", type: "bytes32" }
|
|
567
577
|
]
|
|
568
578
|
};
|
|
569
|
-
const
|
|
579
|
+
const nonceBytes = new Uint8Array(32);
|
|
580
|
+
(globalThis.crypto ?? (await import("crypto")).webcrypto).getRandomValues(nonceBytes);
|
|
581
|
+
const nonce = "0x" + [...nonceBytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
570
582
|
const now = Math.floor(Date.now() / 1e3);
|
|
571
583
|
const authorization = {
|
|
572
584
|
from: wallet.address,
|
|
@@ -661,10 +673,11 @@ function createX402Client(config) {
|
|
|
661
673
|
const parts = jwt.split(".");
|
|
662
674
|
if (parts.length === 3) {
|
|
663
675
|
const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
}
|
|
676
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
677
|
+
const maxExp = now + 86400;
|
|
678
|
+
const expiresAt = Math.min(typeof payload.exp === "number" ? payload.exp : now, maxExp);
|
|
679
|
+
passCache.set(host, { jwt, expiresAt });
|
|
680
|
+
log("Access pass cached for", host, "| expires:", new Date(expiresAt * 1e3).toISOString());
|
|
668
681
|
}
|
|
669
682
|
} catch {
|
|
670
683
|
log("Failed to cache access pass");
|
|
@@ -745,7 +758,7 @@ function createX402Client(config) {
|
|
|
745
758
|
if (adapter.name === "Solana" && !accept.extra?.feePayer) return null;
|
|
746
759
|
const decimals = accept.extra?.decimals ?? (isKnownUSDC(accept.asset) ? 6 : void 0);
|
|
747
760
|
if (typeof decimals !== "number") return null;
|
|
748
|
-
const paymentAmount = accept.amount
|
|
761
|
+
const paymentAmount = accept.amount ?? accept.maxAmountRequired;
|
|
749
762
|
if (!paymentAmount) return null;
|
|
750
763
|
const rpcUrl = getRpcUrl(accept.network, adapter);
|
|
751
764
|
const balance = await adapter.getBalance(accept, wallet, rpcUrl);
|
|
@@ -889,7 +902,7 @@ function createX402Client(config) {
|
|
|
889
902
|
"Payment option missing decimals - provide in extra or use a known stablecoin"
|
|
890
903
|
);
|
|
891
904
|
}
|
|
892
|
-
const paymentAmount = accept.amount
|
|
905
|
+
const paymentAmount = accept.amount ?? accept.maxAmountRequired;
|
|
893
906
|
if (!paymentAmount) {
|
|
894
907
|
throw new X402Error("missing_amount", "Payment option missing amount");
|
|
895
908
|
}
|