@t2000/x402 0.2.6 → 0.3.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/README.md CHANGED
@@ -122,9 +122,9 @@ Verify that an on-chain payment transaction is valid. Checks the transaction for
122
122
 
123
123
  ```typescript
124
124
  import { verifyPayment } from '@t2000/x402';
125
- import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
125
+ import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
126
126
 
127
- const client = new SuiClient({ url: getFullnodeUrl('mainnet') });
127
+ const client = new SuiJsonRpcClient({ url: getJsonRpcFullnodeUrl('mainnet'), network: 'mainnet' });
128
128
 
129
129
  const result = await verifyPayment(client, {
130
130
  txHash: 'ABC123...',
@@ -155,9 +155,9 @@ Payments are executed on-chain via the [Sui Payment Kit](https://docs.sui.io/sta
155
155
 
156
156
  ```typescript
157
157
  import { buildPaymentTransaction } from '@t2000/x402';
158
- import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
158
+ import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
159
159
 
160
- const client = new SuiClient({ url: getFullnodeUrl('mainnet') });
160
+ const client = new SuiJsonRpcClient({ url: getJsonRpcFullnodeUrl('mainnet'), network: 'mainnet' });
161
161
 
162
162
  // Build a payment transaction (advanced usage)
163
163
  const tx = await buildPaymentTransaction(client, senderAddress, {
@@ -188,7 +188,7 @@ Any wallet implementing `X402Wallet` can be used as a payment source:
188
188
 
189
189
  ```typescript
190
190
  interface X402Wallet {
191
- client: SuiClient;
191
+ client: SuiJsonRpcClient;
192
192
  keypair: Ed25519Keypair;
193
193
  address(): string;
194
194
  signAndExecute(tx: unknown): Promise<{ digest: string }>;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/payment-kit.ts","../src/client.ts","../src/facilitator.ts"],"names":["usdcToRaw","Transaction","T2000Error"],"mappings":"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","file":"index.cjs","sourcesContent":["export interface PaymentRequired {\n amount: string;\n asset: string;\n network: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n description?: string;\n}\n\nexport interface PaymentPayload {\n txHash: string;\n network: string;\n amount: string;\n nonce: string;\n}\n\nexport interface VerifyRequest {\n txHash: string;\n network: string;\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n}\n\nexport interface VerifyResponse {\n verified: boolean;\n txHash?: string;\n settledAmount?: string;\n settledAt?: number;\n reason?: VerifyFailureReason;\n}\n\nexport type VerifyFailureReason =\n | 'expired'\n | 'tx_not_found'\n | 'no_payment_event'\n | 'amount_mismatch'\n | 'wrong_recipient'\n | 'nonce_mismatch';\n\nexport interface SettleRequest {\n txHash: string;\n nonce: string;\n}\n\nexport interface SettleResponse {\n settled: boolean;\n}\n\nexport interface X402ClientOptions {\n maxPrice?: number;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeout?: number;\n dryRun?: boolean;\n onPayment?: (details: PaymentDetails) => void;\n}\n\nexport interface PaymentDetails {\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n txHash: string;\n}\n\nexport type X402FetchOptions = X402ClientOptions;\n\nexport const X402_HEADERS = {\n PAYMENT_REQUIRED: 'payment-required',\n X_PAYMENT: 'x-payment',\n} as const;\n\nexport const DEFAULT_MAX_PRICE = 1.0;\nexport const DEFAULT_TIMEOUT = 30_000;\n","/**\n * Sui Payment Kit package ID (mainnet).\n * Source: github.com/MystenLabs/sui-payment-kit Move.lock `original-published-id`.\n */\nexport const PAYMENT_KIT_PACKAGE =\n process.env.PAYMENT_KIT_PACKAGE ??\n '0xbc126f1535fba7d641cb9150ad9eae93b104972586ba20f3c60bfe0e53b69bc6';\n\n/**\n * t2000's PaymentRegistry object ID (mainnet).\n * Created via `create_registry` on Payment Kit Namespace.\n * Tx: 666ZX1PhfV3PVJtqVZfuToHoVGoTDeWCxzZb1u8aRgmL\n */\nexport const T2000_PAYMENT_REGISTRY_ID =\n process.env.T2000_PAYMENT_REGISTRY_ID ??\n '0x4009dd17305ed1b33352b808e9d0e9eb94d09085b2d5ec0f395c5cdfa2271291';\n\nexport const USDC_TYPE =\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC';\n\nexport const CLOCK_ID = '0x6';\n\nexport const DEFAULT_FACILITATOR_URL = 'https://api.t2000.ai/x402';\n\nexport const PAYMENT_KIT_MODULE = 'payment_kit';\nexport const PAYMENT_KIT_FUNCTION = 'process_registry_payment';\nexport const PAYMENT_RECEIPT_EVENT_TYPE = `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::PaymentReceipt`;\n","import { Transaction } from '@mysten/sui/transactions';\nimport type { SuiClient } from '@mysten/sui/client';\nimport { usdcToRaw } from '@t2000/sdk';\nimport {\n PAYMENT_KIT_PACKAGE,\n PAYMENT_KIT_MODULE,\n PAYMENT_KIT_FUNCTION,\n T2000_PAYMENT_REGISTRY_ID,\n USDC_TYPE,\n CLOCK_ID,\n} from './constants.js';\n\nexport interface PaymentPTBParams {\n nonce: string;\n amount: string;\n payTo: string;\n}\n\n/**\n * Builds a payment PTB using USDC coins from the wallet.\n *\n * The Move function signature:\n * process_registry_payment<CoinType>(\n * registry: &mut PaymentRegistry<CoinType>,\n * nonce: String,\n * amount: u64,\n * coin: Coin<CoinType>,\n * receiver: Option<address>,\n * clock: &Clock\n * )\n *\n * Move enforces nonce uniqueness atomically via EDuplicatePayment.\n */\nexport async function buildPaymentTransaction(\n client: SuiClient,\n senderAddress: string,\n params: PaymentPTBParams,\n): Promise<Transaction> {\n const { nonce, amount, payTo } = params;\n const rawAmount = usdcToRaw(Number(amount));\n\n if (!T2000_PAYMENT_REGISTRY_ID) {\n throw new Error(\n 'T2000_PAYMENT_REGISTRY_ID is not set. ' +\n 'Create a PaymentRegistry<USDC> via Payment Kit before using x402.'\n );\n }\n\n const coins = await client.getCoins({\n owner: senderAddress,\n coinType: USDC_TYPE,\n });\n\n if (coins.data.length === 0) {\n throw new Error('No USDC coins found in wallet');\n }\n\n const tx = new Transaction();\n\n let primaryCoin = tx.object(coins.data[0].coinObjectId);\n if (coins.data.length > 1) {\n const otherCoins = coins.data.slice(1).map(c => tx.object(c.coinObjectId));\n tx.mergeCoins(primaryCoin, otherCoins);\n }\n\n const [paymentCoin] = tx.splitCoins(primaryCoin, [tx.pure.u64(rawAmount)]);\n\n tx.moveCall({\n target: `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::${PAYMENT_KIT_FUNCTION}`,\n arguments: [\n tx.object(T2000_PAYMENT_REGISTRY_ID),\n tx.pure.string(nonce),\n tx.pure.u64(rawAmount),\n paymentCoin,\n tx.pure.option('address', payTo),\n tx.object(CLOCK_ID),\n ],\n typeArguments: [USDC_TYPE],\n });\n\n return tx;\n}\n","import type { SuiClient } from '@mysten/sui/client';\nimport type { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { T2000Error } from '@t2000/sdk';\nimport type {\n PaymentRequired,\n PaymentPayload,\n X402FetchOptions,\n PaymentDetails,\n} from './types.js';\nimport {\n X402_HEADERS,\n DEFAULT_MAX_PRICE,\n DEFAULT_TIMEOUT,\n} from './types.js';\nimport { buildPaymentTransaction } from './payment-kit.js';\n\n/**\n * Parses the PAYMENT-REQUIRED header from a 402 response.\n * Validates network, asset, expiry, and price constraints.\n */\nexport function parsePaymentRequired(\n headerValue: string | null,\n maxPrice: number = DEFAULT_MAX_PRICE,\n): PaymentRequired {\n if (!headerValue) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n '402 response missing PAYMENT-REQUIRED header',\n );\n }\n\n let parsed: PaymentRequired;\n try {\n parsed = JSON.parse(headerValue);\n } catch {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'Malformed PAYMENT-REQUIRED header: invalid JSON',\n { raw: headerValue },\n );\n }\n\n if (!parsed.network || !parsed.amount || !parsed.payTo || !parsed.nonce || parsed.expiresAt == null) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'PAYMENT-REQUIRED header missing required fields',\n { parsed },\n );\n }\n\n if (parsed.network !== 'sui') {\n throw new T2000Error(\n 'UNSUPPORTED_NETWORK',\n `x402 requires network \"${parsed.network}\" but only Sui is supported`,\n { network: parsed.network },\n );\n }\n\n if (parsed.asset && parsed.asset !== 'USDC') {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `x402 requires asset \"${parsed.asset}\" but only USDC is supported`,\n { asset: parsed.asset },\n );\n }\n\n if (parsed.expiresAt < Date.now() / 1000) {\n throw new T2000Error(\n 'PAYMENT_EXPIRED',\n 'x402 payment challenge has expired',\n { expiresAt: parsed.expiresAt },\n );\n }\n\n const price = Number(parsed.amount);\n if (price > maxPrice) {\n throw new T2000Error(\n 'PRICE_EXCEEDS_LIMIT',\n `Requested price $${parsed.amount} exceeds max price $${maxPrice}`,\n { requested: parsed.amount, limit: maxPrice },\n );\n }\n\n return parsed;\n}\n\nexport interface X402Wallet {\n client: SuiClient;\n keypair: Ed25519Keypair;\n address(): string;\n signAndExecute(tx: unknown): Promise<{ digest: string }>;\n}\n\n/**\n * x402 client for Sui. Handles the full 402 payment flow:\n * 1. Sends initial request\n * 2. Detects 402 Payment Required\n * 3. Parses payment terms\n * 4. Builds and executes Payment Kit PTB\n * 5. Retries with X-PAYMENT proof header\n */\nexport class x402Client {\n private wallet: X402Wallet;\n\n constructor(wallet: X402Wallet) {\n this.wallet = wallet;\n }\n\n /**\n * Makes an HTTP request, handling x402 payment if required.\n * Non-402 responses pass through unmodified.\n */\n async fetch(url: string, options: X402FetchOptions = {}): Promise<Response> {\n const {\n maxPrice = DEFAULT_MAX_PRICE,\n method = 'GET',\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n dryRun = false,\n onPayment,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const initial = await globalThis.fetch(url, {\n method,\n headers,\n body,\n signal: controller.signal,\n });\n\n if (initial.status !== 402) {\n return initial;\n }\n\n const paymentRequired = parsePaymentRequired(\n initial.headers.get(X402_HEADERS.PAYMENT_REQUIRED),\n maxPrice,\n );\n\n if (dryRun) {\n return new Response(\n JSON.stringify({\n dryRun: true,\n amount: paymentRequired.amount,\n asset: paymentRequired.asset,\n payTo: paymentRequired.payTo,\n network: paymentRequired.network,\n }),\n { status: 200, headers: { 'content-type': 'application/json' } },\n );\n }\n\n const tx = await buildPaymentTransaction(\n this.wallet.client,\n this.wallet.address(),\n {\n nonce: paymentRequired.nonce,\n amount: paymentRequired.amount,\n payTo: paymentRequired.payTo,\n },\n );\n\n let result: { digest: string };\n try {\n result = await this.wallet.signAndExecute(tx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('EDuplicatePayment') || msg.includes('duplicate')) {\n throw new T2000Error(\n 'DUPLICATE_PAYMENT',\n 'Payment nonce already used on-chain',\n { nonce: paymentRequired.nonce },\n );\n }\n if (msg.includes('InsufficientCoinBalance') || msg.includes('Insufficient')) {\n throw new T2000Error(\n 'INSUFFICIENT_BALANCE',\n 'Not enough USDC to complete payment',\n { required: paymentRequired.amount },\n );\n }\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `Payment transaction failed: ${msg}`,\n { nonce: paymentRequired.nonce },\n );\n }\n\n const paymentDetails: PaymentDetails = {\n amount: paymentRequired.amount,\n asset: paymentRequired.asset || 'USDC',\n payTo: paymentRequired.payTo,\n nonce: paymentRequired.nonce,\n txHash: result.digest,\n };\n\n onPayment?.(paymentDetails);\n\n const paymentPayload: PaymentPayload = {\n txHash: result.digest,\n network: 'sui',\n amount: paymentRequired.amount,\n nonce: paymentRequired.nonce,\n };\n\n const retry = await globalThis.fetch(url, {\n method,\n headers: {\n ...headers,\n [X402_HEADERS.X_PAYMENT]: JSON.stringify(paymentPayload),\n },\n body,\n signal: controller.signal,\n });\n\n return retry;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","import type { SuiClient, SuiEvent } from '@mysten/sui/client';\nimport { usdcToRaw } from '@t2000/sdk';\nimport type {\n VerifyRequest,\n VerifyResponse,\n VerifyFailureReason,\n} from './types.js';\nimport { PAYMENT_RECEIPT_EVENT_TYPE } from './constants.js';\n\ninterface PaymentReceiptFields {\n payment_amount: string;\n receiver: string;\n nonce: string;\n coin_type?: string;\n timestamp_ms?: string;\n}\n\nfunction isPaymentReceipt(event: SuiEvent): boolean {\n return event.type === PAYMENT_RECEIPT_EVENT_TYPE;\n}\n\nfunction parsePaymentReceiptFields(event: SuiEvent): PaymentReceiptFields | null {\n const json = event.parsedJson as Record<string, unknown> | undefined;\n if (!json) return null;\n\n return {\n payment_amount: String(json.payment_amount ?? ''),\n receiver: String(json.receiver ?? ''),\n nonce: String(json.nonce ?? ''),\n coin_type: json.coin_type ? String(json.coin_type) : undefined,\n timestamp_ms: json.timestamp_ms ? String(json.timestamp_ms) : undefined,\n };\n}\n\n/**\n * Verifies an x402 payment by checking the Sui transaction on-chain.\n *\n * Verification steps:\n * 1. Check if the challenge has expired\n * 2. Fetch the transaction from Sui RPC\n * 3. Find the PaymentReceipt event emitted by Payment Kit\n * 4. Validate amount, recipient, and nonce match the request\n *\n * Duplicate nonces are already prevented by Move's EDuplicatePayment.\n * This function only verifies payments that successfully landed on-chain.\n */\nexport async function verifyPayment(\n client: SuiClient,\n req: VerifyRequest,\n): Promise<VerifyResponse> {\n if (Date.now() / 1000 > req.expiresAt) {\n return { verified: false, reason: 'expired' };\n }\n\n let tx;\n try {\n tx = await client.getTransactionBlock({\n digest: req.txHash,\n options: { showEffects: true, showEvents: true },\n });\n } catch {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n if (!tx) {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n const receiptEvent = tx.events?.find(isPaymentReceipt);\n if (!receiptEvent) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const fields = parsePaymentReceiptFields(receiptEvent);\n if (!fields) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const expectedAmount = usdcToRaw(Number(req.amount));\n if (BigInt(fields.payment_amount) !== expectedAmount) {\n return { verified: false, reason: 'amount_mismatch' };\n }\n\n if (fields.receiver !== req.payTo) {\n return { verified: false, reason: 'wrong_recipient' };\n }\n\n if (fields.nonce !== req.nonce) {\n return { verified: false, reason: 'nonce_mismatch' as VerifyFailureReason };\n }\n\n return {\n verified: true,\n txHash: req.txHash,\n settledAmount: req.amount,\n settledAt: Math.floor(Date.now() / 1000),\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/payment-kit.ts","../src/client.ts","../src/facilitator.ts"],"names":["usdcToRaw","Transaction","T2000Error"],"mappings":"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","file":"index.cjs","sourcesContent":["export interface PaymentRequired {\n amount: string;\n asset: string;\n network: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n description?: string;\n}\n\nexport interface PaymentPayload {\n txHash: string;\n network: string;\n amount: string;\n nonce: string;\n}\n\nexport interface VerifyRequest {\n txHash: string;\n network: string;\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n}\n\nexport interface VerifyResponse {\n verified: boolean;\n txHash?: string;\n settledAmount?: string;\n settledAt?: number;\n reason?: VerifyFailureReason;\n}\n\nexport type VerifyFailureReason =\n | 'expired'\n | 'tx_not_found'\n | 'no_payment_event'\n | 'amount_mismatch'\n | 'wrong_recipient'\n | 'nonce_mismatch';\n\nexport interface SettleRequest {\n txHash: string;\n nonce: string;\n}\n\nexport interface SettleResponse {\n settled: boolean;\n}\n\nexport interface X402ClientOptions {\n maxPrice?: number;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeout?: number;\n dryRun?: boolean;\n onPayment?: (details: PaymentDetails) => void;\n}\n\nexport interface PaymentDetails {\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n txHash: string;\n}\n\nexport type X402FetchOptions = X402ClientOptions;\n\nexport const X402_HEADERS = {\n PAYMENT_REQUIRED: 'payment-required',\n X_PAYMENT: 'x-payment',\n} as const;\n\nexport const DEFAULT_MAX_PRICE = 1.0;\nexport const DEFAULT_TIMEOUT = 30_000;\n","/**\n * Sui Payment Kit package ID (mainnet).\n * Source: github.com/MystenLabs/sui-payment-kit Move.lock `original-published-id`.\n */\nexport const PAYMENT_KIT_PACKAGE =\n process.env.PAYMENT_KIT_PACKAGE ??\n '0xbc126f1535fba7d641cb9150ad9eae93b104972586ba20f3c60bfe0e53b69bc6';\n\n/**\n * t2000's PaymentRegistry object ID (mainnet).\n * Created via `create_registry` on Payment Kit Namespace.\n * Tx: 666ZX1PhfV3PVJtqVZfuToHoVGoTDeWCxzZb1u8aRgmL\n */\nexport const T2000_PAYMENT_REGISTRY_ID =\n process.env.T2000_PAYMENT_REGISTRY_ID ??\n '0x4009dd17305ed1b33352b808e9d0e9eb94d09085b2d5ec0f395c5cdfa2271291';\n\nexport const USDC_TYPE =\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC';\n\nexport const CLOCK_ID = '0x6';\n\nexport const DEFAULT_FACILITATOR_URL = 'https://api.t2000.ai/x402';\n\nexport const PAYMENT_KIT_MODULE = 'payment_kit';\nexport const PAYMENT_KIT_FUNCTION = 'process_registry_payment';\nexport const PAYMENT_RECEIPT_EVENT_TYPE = `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::PaymentReceipt`;\n","import { Transaction } from '@mysten/sui/transactions';\nimport type { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';\nimport { usdcToRaw } from '@t2000/sdk';\nimport {\n PAYMENT_KIT_PACKAGE,\n PAYMENT_KIT_MODULE,\n PAYMENT_KIT_FUNCTION,\n T2000_PAYMENT_REGISTRY_ID,\n USDC_TYPE,\n CLOCK_ID,\n} from './constants.js';\n\nexport interface PaymentPTBParams {\n nonce: string;\n amount: string;\n payTo: string;\n}\n\n/**\n * Builds a payment PTB using USDC coins from the wallet.\n *\n * The Move function signature:\n * process_registry_payment<CoinType>(\n * registry: &mut PaymentRegistry<CoinType>,\n * nonce: String,\n * amount: u64,\n * coin: Coin<CoinType>,\n * receiver: Option<address>,\n * clock: &Clock\n * )\n *\n * Move enforces nonce uniqueness atomically via EDuplicatePayment.\n */\nexport async function buildPaymentTransaction(\n client: SuiJsonRpcClient,\n senderAddress: string,\n params: PaymentPTBParams,\n): Promise<Transaction> {\n const { nonce, amount, payTo } = params;\n const rawAmount = usdcToRaw(Number(amount));\n\n if (!T2000_PAYMENT_REGISTRY_ID) {\n throw new Error(\n 'T2000_PAYMENT_REGISTRY_ID is not set. ' +\n 'Create a PaymentRegistry<USDC> via Payment Kit before using x402.'\n );\n }\n\n const coins = await client.getCoins({\n owner: senderAddress,\n coinType: USDC_TYPE,\n });\n\n if (coins.data.length === 0) {\n throw new Error('No USDC coins found in wallet');\n }\n\n const tx = new Transaction();\n\n let primaryCoin = tx.object(coins.data[0].coinObjectId);\n if (coins.data.length > 1) {\n const otherCoins = coins.data.slice(1).map(c => tx.object(c.coinObjectId));\n tx.mergeCoins(primaryCoin, otherCoins);\n }\n\n const [paymentCoin] = tx.splitCoins(primaryCoin, [tx.pure.u64(rawAmount)]);\n\n tx.moveCall({\n target: `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::${PAYMENT_KIT_FUNCTION}`,\n arguments: [\n tx.object(T2000_PAYMENT_REGISTRY_ID),\n tx.pure.string(nonce),\n tx.pure.u64(rawAmount),\n paymentCoin,\n tx.pure.option('address', payTo),\n tx.object(CLOCK_ID),\n ],\n typeArguments: [USDC_TYPE],\n });\n\n return tx;\n}\n","import type { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';\nimport type { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { T2000Error } from '@t2000/sdk';\nimport type {\n PaymentRequired,\n PaymentPayload,\n X402FetchOptions,\n PaymentDetails,\n} from './types.js';\nimport {\n X402_HEADERS,\n DEFAULT_MAX_PRICE,\n DEFAULT_TIMEOUT,\n} from './types.js';\nimport { buildPaymentTransaction } from './payment-kit.js';\n\n/**\n * Parses the PAYMENT-REQUIRED header from a 402 response.\n * Validates network, asset, expiry, and price constraints.\n */\nexport function parsePaymentRequired(\n headerValue: string | null,\n maxPrice: number = DEFAULT_MAX_PRICE,\n): PaymentRequired {\n if (!headerValue) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n '402 response missing PAYMENT-REQUIRED header',\n );\n }\n\n let parsed: PaymentRequired;\n try {\n parsed = JSON.parse(headerValue);\n } catch {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'Malformed PAYMENT-REQUIRED header: invalid JSON',\n { raw: headerValue },\n );\n }\n\n if (!parsed.network || !parsed.amount || !parsed.payTo || !parsed.nonce || parsed.expiresAt == null) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'PAYMENT-REQUIRED header missing required fields',\n { parsed },\n );\n }\n\n if (parsed.network !== 'sui') {\n throw new T2000Error(\n 'UNSUPPORTED_NETWORK',\n `x402 requires network \"${parsed.network}\" but only Sui is supported`,\n { network: parsed.network },\n );\n }\n\n if (parsed.asset && parsed.asset !== 'USDC') {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `x402 requires asset \"${parsed.asset}\" but only USDC is supported`,\n { asset: parsed.asset },\n );\n }\n\n if (parsed.expiresAt < Date.now() / 1000) {\n throw new T2000Error(\n 'PAYMENT_EXPIRED',\n 'x402 payment challenge has expired',\n { expiresAt: parsed.expiresAt },\n );\n }\n\n const price = Number(parsed.amount);\n if (price > maxPrice) {\n throw new T2000Error(\n 'PRICE_EXCEEDS_LIMIT',\n `Requested price $${parsed.amount} exceeds max price $${maxPrice}`,\n { requested: parsed.amount, limit: maxPrice },\n );\n }\n\n return parsed;\n}\n\nexport interface X402Wallet {\n client: SuiJsonRpcClient;\n keypair: Ed25519Keypair;\n address(): string;\n signAndExecute(tx: unknown): Promise<{ digest: string }>;\n}\n\n/**\n * x402 client for Sui. Handles the full 402 payment flow:\n * 1. Sends initial request\n * 2. Detects 402 Payment Required\n * 3. Parses payment terms\n * 4. Builds and executes Payment Kit PTB\n * 5. Retries with X-PAYMENT proof header\n */\nexport class x402Client {\n private wallet: X402Wallet;\n\n constructor(wallet: X402Wallet) {\n this.wallet = wallet;\n }\n\n /**\n * Makes an HTTP request, handling x402 payment if required.\n * Non-402 responses pass through unmodified.\n */\n async fetch(url: string, options: X402FetchOptions = {}): Promise<Response> {\n const {\n maxPrice = DEFAULT_MAX_PRICE,\n method = 'GET',\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n dryRun = false,\n onPayment,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const initial = await globalThis.fetch(url, {\n method,\n headers,\n body,\n signal: controller.signal,\n });\n\n if (initial.status !== 402) {\n return initial;\n }\n\n const paymentRequired = parsePaymentRequired(\n initial.headers.get(X402_HEADERS.PAYMENT_REQUIRED),\n maxPrice,\n );\n\n if (dryRun) {\n return new Response(\n JSON.stringify({\n dryRun: true,\n amount: paymentRequired.amount,\n asset: paymentRequired.asset,\n payTo: paymentRequired.payTo,\n network: paymentRequired.network,\n }),\n { status: 200, headers: { 'content-type': 'application/json' } },\n );\n }\n\n const tx = await buildPaymentTransaction(\n this.wallet.client,\n this.wallet.address(),\n {\n nonce: paymentRequired.nonce,\n amount: paymentRequired.amount,\n payTo: paymentRequired.payTo,\n },\n );\n\n let result: { digest: string };\n try {\n result = await this.wallet.signAndExecute(tx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('EDuplicatePayment') || msg.includes('duplicate')) {\n throw new T2000Error(\n 'DUPLICATE_PAYMENT',\n 'Payment nonce already used on-chain',\n { nonce: paymentRequired.nonce },\n );\n }\n if (msg.includes('InsufficientCoinBalance') || msg.includes('Insufficient')) {\n throw new T2000Error(\n 'INSUFFICIENT_BALANCE',\n 'Not enough USDC to complete payment',\n { required: paymentRequired.amount },\n );\n }\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `Payment transaction failed: ${msg}`,\n { nonce: paymentRequired.nonce },\n );\n }\n\n const paymentDetails: PaymentDetails = {\n amount: paymentRequired.amount,\n asset: paymentRequired.asset || 'USDC',\n payTo: paymentRequired.payTo,\n nonce: paymentRequired.nonce,\n txHash: result.digest,\n };\n\n onPayment?.(paymentDetails);\n\n const paymentPayload: PaymentPayload = {\n txHash: result.digest,\n network: 'sui',\n amount: paymentRequired.amount,\n nonce: paymentRequired.nonce,\n };\n\n const retry = await globalThis.fetch(url, {\n method,\n headers: {\n ...headers,\n [X402_HEADERS.X_PAYMENT]: JSON.stringify(paymentPayload),\n },\n body,\n signal: controller.signal,\n });\n\n return retry;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","import type { SuiJsonRpcClient, SuiEvent } from '@mysten/sui/jsonRpc';\nimport { usdcToRaw } from '@t2000/sdk';\nimport type {\n VerifyRequest,\n VerifyResponse,\n VerifyFailureReason,\n} from './types.js';\nimport { PAYMENT_RECEIPT_EVENT_TYPE } from './constants.js';\n\ninterface PaymentReceiptFields {\n payment_amount: string;\n receiver: string;\n nonce: string;\n coin_type?: string;\n timestamp_ms?: string;\n}\n\nfunction isPaymentReceipt(event: SuiEvent): boolean {\n return event.type === PAYMENT_RECEIPT_EVENT_TYPE;\n}\n\nfunction parsePaymentReceiptFields(event: SuiEvent): PaymentReceiptFields | null {\n const json = event.parsedJson as Record<string, unknown> | undefined;\n if (!json) return null;\n\n return {\n payment_amount: String(json.payment_amount ?? ''),\n receiver: String(json.receiver ?? ''),\n nonce: String(json.nonce ?? ''),\n coin_type: json.coin_type ? String(json.coin_type) : undefined,\n timestamp_ms: json.timestamp_ms ? String(json.timestamp_ms) : undefined,\n };\n}\n\n/**\n * Verifies an x402 payment by checking the Sui transaction on-chain.\n *\n * Verification steps:\n * 1. Check if the challenge has expired\n * 2. Fetch the transaction from Sui RPC\n * 3. Find the PaymentReceipt event emitted by Payment Kit\n * 4. Validate amount, recipient, and nonce match the request\n *\n * Duplicate nonces are already prevented by Move's EDuplicatePayment.\n * This function only verifies payments that successfully landed on-chain.\n */\nexport async function verifyPayment(\n client: SuiJsonRpcClient,\n req: VerifyRequest,\n): Promise<VerifyResponse> {\n if (Date.now() / 1000 > req.expiresAt) {\n return { verified: false, reason: 'expired' };\n }\n\n let tx;\n try {\n tx = await client.getTransactionBlock({\n digest: req.txHash,\n options: { showEffects: true, showEvents: true },\n });\n } catch {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n if (!tx) {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n const receiptEvent = tx.events?.find(isPaymentReceipt);\n if (!receiptEvent) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const fields = parsePaymentReceiptFields(receiptEvent);\n if (!fields) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const expectedAmount = usdcToRaw(Number(req.amount));\n if (BigInt(fields.payment_amount) !== expectedAmount) {\n return { verified: false, reason: 'amount_mismatch' };\n }\n\n if (fields.receiver !== req.payTo) {\n return { verified: false, reason: 'wrong_recipient' };\n }\n\n if (fields.nonce !== req.nonce) {\n return { verified: false, reason: 'nonce_mismatch' as VerifyFailureReason };\n }\n\n return {\n verified: true,\n txHash: req.txHash,\n settledAmount: req.amount,\n settledAt: Math.floor(Date.now() / 1000),\n };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { SuiClient } from '@mysten/sui/client';
1
+ import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
2
2
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
3
3
  import { Transaction } from '@mysten/sui/transactions';
4
4
 
@@ -71,7 +71,7 @@ declare const DEFAULT_TIMEOUT = 30000;
71
71
  */
72
72
  declare function parsePaymentRequired(headerValue: string | null, maxPrice?: number): PaymentRequired;
73
73
  interface X402Wallet {
74
- client: SuiClient;
74
+ client: SuiJsonRpcClient;
75
75
  keypair: Ed25519Keypair;
76
76
  address(): string;
77
77
  signAndExecute(tx: unknown): Promise<{
@@ -116,7 +116,7 @@ interface PaymentPTBParams {
116
116
  *
117
117
  * Move enforces nonce uniqueness atomically via EDuplicatePayment.
118
118
  */
119
- declare function buildPaymentTransaction(client: SuiClient, senderAddress: string, params: PaymentPTBParams): Promise<Transaction>;
119
+ declare function buildPaymentTransaction(client: SuiJsonRpcClient, senderAddress: string, params: PaymentPTBParams): Promise<Transaction>;
120
120
 
121
121
  /**
122
122
  * Verifies an x402 payment by checking the Sui transaction on-chain.
@@ -130,7 +130,7 @@ declare function buildPaymentTransaction(client: SuiClient, senderAddress: strin
130
130
  * Duplicate nonces are already prevented by Move's EDuplicatePayment.
131
131
  * This function only verifies payments that successfully landed on-chain.
132
132
  */
133
- declare function verifyPayment(client: SuiClient, req: VerifyRequest): Promise<VerifyResponse>;
133
+ declare function verifyPayment(client: SuiJsonRpcClient, req: VerifyRequest): Promise<VerifyResponse>;
134
134
 
135
135
  /**
136
136
  * Sui Payment Kit package ID (mainnet).
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SuiClient } from '@mysten/sui/client';
1
+ import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
2
2
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
3
3
  import { Transaction } from '@mysten/sui/transactions';
4
4
 
@@ -71,7 +71,7 @@ declare const DEFAULT_TIMEOUT = 30000;
71
71
  */
72
72
  declare function parsePaymentRequired(headerValue: string | null, maxPrice?: number): PaymentRequired;
73
73
  interface X402Wallet {
74
- client: SuiClient;
74
+ client: SuiJsonRpcClient;
75
75
  keypair: Ed25519Keypair;
76
76
  address(): string;
77
77
  signAndExecute(tx: unknown): Promise<{
@@ -116,7 +116,7 @@ interface PaymentPTBParams {
116
116
  *
117
117
  * Move enforces nonce uniqueness atomically via EDuplicatePayment.
118
118
  */
119
- declare function buildPaymentTransaction(client: SuiClient, senderAddress: string, params: PaymentPTBParams): Promise<Transaction>;
119
+ declare function buildPaymentTransaction(client: SuiJsonRpcClient, senderAddress: string, params: PaymentPTBParams): Promise<Transaction>;
120
120
 
121
121
  /**
122
122
  * Verifies an x402 payment by checking the Sui transaction on-chain.
@@ -130,7 +130,7 @@ declare function buildPaymentTransaction(client: SuiClient, senderAddress: strin
130
130
  * Duplicate nonces are already prevented by Move's EDuplicatePayment.
131
131
  * This function only verifies payments that successfully landed on-chain.
132
132
  */
133
- declare function verifyPayment(client: SuiClient, req: VerifyRequest): Promise<VerifyResponse>;
133
+ declare function verifyPayment(client: SuiJsonRpcClient, req: VerifyRequest): Promise<VerifyResponse>;
134
134
 
135
135
  /**
136
136
  * Sui Payment Kit package ID (mainnet).
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/payment-kit.ts","../src/client.ts","../src/facilitator.ts"],"names":["usdcToRaw"],"mappings":"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","file":"index.js","sourcesContent":["export interface PaymentRequired {\n amount: string;\n asset: string;\n network: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n description?: string;\n}\n\nexport interface PaymentPayload {\n txHash: string;\n network: string;\n amount: string;\n nonce: string;\n}\n\nexport interface VerifyRequest {\n txHash: string;\n network: string;\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n}\n\nexport interface VerifyResponse {\n verified: boolean;\n txHash?: string;\n settledAmount?: string;\n settledAt?: number;\n reason?: VerifyFailureReason;\n}\n\nexport type VerifyFailureReason =\n | 'expired'\n | 'tx_not_found'\n | 'no_payment_event'\n | 'amount_mismatch'\n | 'wrong_recipient'\n | 'nonce_mismatch';\n\nexport interface SettleRequest {\n txHash: string;\n nonce: string;\n}\n\nexport interface SettleResponse {\n settled: boolean;\n}\n\nexport interface X402ClientOptions {\n maxPrice?: number;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeout?: number;\n dryRun?: boolean;\n onPayment?: (details: PaymentDetails) => void;\n}\n\nexport interface PaymentDetails {\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n txHash: string;\n}\n\nexport type X402FetchOptions = X402ClientOptions;\n\nexport const X402_HEADERS = {\n PAYMENT_REQUIRED: 'payment-required',\n X_PAYMENT: 'x-payment',\n} as const;\n\nexport const DEFAULT_MAX_PRICE = 1.0;\nexport const DEFAULT_TIMEOUT = 30_000;\n","/**\n * Sui Payment Kit package ID (mainnet).\n * Source: github.com/MystenLabs/sui-payment-kit Move.lock `original-published-id`.\n */\nexport const PAYMENT_KIT_PACKAGE =\n process.env.PAYMENT_KIT_PACKAGE ??\n '0xbc126f1535fba7d641cb9150ad9eae93b104972586ba20f3c60bfe0e53b69bc6';\n\n/**\n * t2000's PaymentRegistry object ID (mainnet).\n * Created via `create_registry` on Payment Kit Namespace.\n * Tx: 666ZX1PhfV3PVJtqVZfuToHoVGoTDeWCxzZb1u8aRgmL\n */\nexport const T2000_PAYMENT_REGISTRY_ID =\n process.env.T2000_PAYMENT_REGISTRY_ID ??\n '0x4009dd17305ed1b33352b808e9d0e9eb94d09085b2d5ec0f395c5cdfa2271291';\n\nexport const USDC_TYPE =\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC';\n\nexport const CLOCK_ID = '0x6';\n\nexport const DEFAULT_FACILITATOR_URL = 'https://api.t2000.ai/x402';\n\nexport const PAYMENT_KIT_MODULE = 'payment_kit';\nexport const PAYMENT_KIT_FUNCTION = 'process_registry_payment';\nexport const PAYMENT_RECEIPT_EVENT_TYPE = `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::PaymentReceipt`;\n","import { Transaction } from '@mysten/sui/transactions';\nimport type { SuiClient } from '@mysten/sui/client';\nimport { usdcToRaw } from '@t2000/sdk';\nimport {\n PAYMENT_KIT_PACKAGE,\n PAYMENT_KIT_MODULE,\n PAYMENT_KIT_FUNCTION,\n T2000_PAYMENT_REGISTRY_ID,\n USDC_TYPE,\n CLOCK_ID,\n} from './constants.js';\n\nexport interface PaymentPTBParams {\n nonce: string;\n amount: string;\n payTo: string;\n}\n\n/**\n * Builds a payment PTB using USDC coins from the wallet.\n *\n * The Move function signature:\n * process_registry_payment<CoinType>(\n * registry: &mut PaymentRegistry<CoinType>,\n * nonce: String,\n * amount: u64,\n * coin: Coin<CoinType>,\n * receiver: Option<address>,\n * clock: &Clock\n * )\n *\n * Move enforces nonce uniqueness atomically via EDuplicatePayment.\n */\nexport async function buildPaymentTransaction(\n client: SuiClient,\n senderAddress: string,\n params: PaymentPTBParams,\n): Promise<Transaction> {\n const { nonce, amount, payTo } = params;\n const rawAmount = usdcToRaw(Number(amount));\n\n if (!T2000_PAYMENT_REGISTRY_ID) {\n throw new Error(\n 'T2000_PAYMENT_REGISTRY_ID is not set. ' +\n 'Create a PaymentRegistry<USDC> via Payment Kit before using x402.'\n );\n }\n\n const coins = await client.getCoins({\n owner: senderAddress,\n coinType: USDC_TYPE,\n });\n\n if (coins.data.length === 0) {\n throw new Error('No USDC coins found in wallet');\n }\n\n const tx = new Transaction();\n\n let primaryCoin = tx.object(coins.data[0].coinObjectId);\n if (coins.data.length > 1) {\n const otherCoins = coins.data.slice(1).map(c => tx.object(c.coinObjectId));\n tx.mergeCoins(primaryCoin, otherCoins);\n }\n\n const [paymentCoin] = tx.splitCoins(primaryCoin, [tx.pure.u64(rawAmount)]);\n\n tx.moveCall({\n target: `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::${PAYMENT_KIT_FUNCTION}`,\n arguments: [\n tx.object(T2000_PAYMENT_REGISTRY_ID),\n tx.pure.string(nonce),\n tx.pure.u64(rawAmount),\n paymentCoin,\n tx.pure.option('address', payTo),\n tx.object(CLOCK_ID),\n ],\n typeArguments: [USDC_TYPE],\n });\n\n return tx;\n}\n","import type { SuiClient } from '@mysten/sui/client';\nimport type { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { T2000Error } from '@t2000/sdk';\nimport type {\n PaymentRequired,\n PaymentPayload,\n X402FetchOptions,\n PaymentDetails,\n} from './types.js';\nimport {\n X402_HEADERS,\n DEFAULT_MAX_PRICE,\n DEFAULT_TIMEOUT,\n} from './types.js';\nimport { buildPaymentTransaction } from './payment-kit.js';\n\n/**\n * Parses the PAYMENT-REQUIRED header from a 402 response.\n * Validates network, asset, expiry, and price constraints.\n */\nexport function parsePaymentRequired(\n headerValue: string | null,\n maxPrice: number = DEFAULT_MAX_PRICE,\n): PaymentRequired {\n if (!headerValue) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n '402 response missing PAYMENT-REQUIRED header',\n );\n }\n\n let parsed: PaymentRequired;\n try {\n parsed = JSON.parse(headerValue);\n } catch {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'Malformed PAYMENT-REQUIRED header: invalid JSON',\n { raw: headerValue },\n );\n }\n\n if (!parsed.network || !parsed.amount || !parsed.payTo || !parsed.nonce || parsed.expiresAt == null) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'PAYMENT-REQUIRED header missing required fields',\n { parsed },\n );\n }\n\n if (parsed.network !== 'sui') {\n throw new T2000Error(\n 'UNSUPPORTED_NETWORK',\n `x402 requires network \"${parsed.network}\" but only Sui is supported`,\n { network: parsed.network },\n );\n }\n\n if (parsed.asset && parsed.asset !== 'USDC') {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `x402 requires asset \"${parsed.asset}\" but only USDC is supported`,\n { asset: parsed.asset },\n );\n }\n\n if (parsed.expiresAt < Date.now() / 1000) {\n throw new T2000Error(\n 'PAYMENT_EXPIRED',\n 'x402 payment challenge has expired',\n { expiresAt: parsed.expiresAt },\n );\n }\n\n const price = Number(parsed.amount);\n if (price > maxPrice) {\n throw new T2000Error(\n 'PRICE_EXCEEDS_LIMIT',\n `Requested price $${parsed.amount} exceeds max price $${maxPrice}`,\n { requested: parsed.amount, limit: maxPrice },\n );\n }\n\n return parsed;\n}\n\nexport interface X402Wallet {\n client: SuiClient;\n keypair: Ed25519Keypair;\n address(): string;\n signAndExecute(tx: unknown): Promise<{ digest: string }>;\n}\n\n/**\n * x402 client for Sui. Handles the full 402 payment flow:\n * 1. Sends initial request\n * 2. Detects 402 Payment Required\n * 3. Parses payment terms\n * 4. Builds and executes Payment Kit PTB\n * 5. Retries with X-PAYMENT proof header\n */\nexport class x402Client {\n private wallet: X402Wallet;\n\n constructor(wallet: X402Wallet) {\n this.wallet = wallet;\n }\n\n /**\n * Makes an HTTP request, handling x402 payment if required.\n * Non-402 responses pass through unmodified.\n */\n async fetch(url: string, options: X402FetchOptions = {}): Promise<Response> {\n const {\n maxPrice = DEFAULT_MAX_PRICE,\n method = 'GET',\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n dryRun = false,\n onPayment,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const initial = await globalThis.fetch(url, {\n method,\n headers,\n body,\n signal: controller.signal,\n });\n\n if (initial.status !== 402) {\n return initial;\n }\n\n const paymentRequired = parsePaymentRequired(\n initial.headers.get(X402_HEADERS.PAYMENT_REQUIRED),\n maxPrice,\n );\n\n if (dryRun) {\n return new Response(\n JSON.stringify({\n dryRun: true,\n amount: paymentRequired.amount,\n asset: paymentRequired.asset,\n payTo: paymentRequired.payTo,\n network: paymentRequired.network,\n }),\n { status: 200, headers: { 'content-type': 'application/json' } },\n );\n }\n\n const tx = await buildPaymentTransaction(\n this.wallet.client,\n this.wallet.address(),\n {\n nonce: paymentRequired.nonce,\n amount: paymentRequired.amount,\n payTo: paymentRequired.payTo,\n },\n );\n\n let result: { digest: string };\n try {\n result = await this.wallet.signAndExecute(tx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('EDuplicatePayment') || msg.includes('duplicate')) {\n throw new T2000Error(\n 'DUPLICATE_PAYMENT',\n 'Payment nonce already used on-chain',\n { nonce: paymentRequired.nonce },\n );\n }\n if (msg.includes('InsufficientCoinBalance') || msg.includes('Insufficient')) {\n throw new T2000Error(\n 'INSUFFICIENT_BALANCE',\n 'Not enough USDC to complete payment',\n { required: paymentRequired.amount },\n );\n }\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `Payment transaction failed: ${msg}`,\n { nonce: paymentRequired.nonce },\n );\n }\n\n const paymentDetails: PaymentDetails = {\n amount: paymentRequired.amount,\n asset: paymentRequired.asset || 'USDC',\n payTo: paymentRequired.payTo,\n nonce: paymentRequired.nonce,\n txHash: result.digest,\n };\n\n onPayment?.(paymentDetails);\n\n const paymentPayload: PaymentPayload = {\n txHash: result.digest,\n network: 'sui',\n amount: paymentRequired.amount,\n nonce: paymentRequired.nonce,\n };\n\n const retry = await globalThis.fetch(url, {\n method,\n headers: {\n ...headers,\n [X402_HEADERS.X_PAYMENT]: JSON.stringify(paymentPayload),\n },\n body,\n signal: controller.signal,\n });\n\n return retry;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","import type { SuiClient, SuiEvent } from '@mysten/sui/client';\nimport { usdcToRaw } from '@t2000/sdk';\nimport type {\n VerifyRequest,\n VerifyResponse,\n VerifyFailureReason,\n} from './types.js';\nimport { PAYMENT_RECEIPT_EVENT_TYPE } from './constants.js';\n\ninterface PaymentReceiptFields {\n payment_amount: string;\n receiver: string;\n nonce: string;\n coin_type?: string;\n timestamp_ms?: string;\n}\n\nfunction isPaymentReceipt(event: SuiEvent): boolean {\n return event.type === PAYMENT_RECEIPT_EVENT_TYPE;\n}\n\nfunction parsePaymentReceiptFields(event: SuiEvent): PaymentReceiptFields | null {\n const json = event.parsedJson as Record<string, unknown> | undefined;\n if (!json) return null;\n\n return {\n payment_amount: String(json.payment_amount ?? ''),\n receiver: String(json.receiver ?? ''),\n nonce: String(json.nonce ?? ''),\n coin_type: json.coin_type ? String(json.coin_type) : undefined,\n timestamp_ms: json.timestamp_ms ? String(json.timestamp_ms) : undefined,\n };\n}\n\n/**\n * Verifies an x402 payment by checking the Sui transaction on-chain.\n *\n * Verification steps:\n * 1. Check if the challenge has expired\n * 2. Fetch the transaction from Sui RPC\n * 3. Find the PaymentReceipt event emitted by Payment Kit\n * 4. Validate amount, recipient, and nonce match the request\n *\n * Duplicate nonces are already prevented by Move's EDuplicatePayment.\n * This function only verifies payments that successfully landed on-chain.\n */\nexport async function verifyPayment(\n client: SuiClient,\n req: VerifyRequest,\n): Promise<VerifyResponse> {\n if (Date.now() / 1000 > req.expiresAt) {\n return { verified: false, reason: 'expired' };\n }\n\n let tx;\n try {\n tx = await client.getTransactionBlock({\n digest: req.txHash,\n options: { showEffects: true, showEvents: true },\n });\n } catch {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n if (!tx) {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n const receiptEvent = tx.events?.find(isPaymentReceipt);\n if (!receiptEvent) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const fields = parsePaymentReceiptFields(receiptEvent);\n if (!fields) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const expectedAmount = usdcToRaw(Number(req.amount));\n if (BigInt(fields.payment_amount) !== expectedAmount) {\n return { verified: false, reason: 'amount_mismatch' };\n }\n\n if (fields.receiver !== req.payTo) {\n return { verified: false, reason: 'wrong_recipient' };\n }\n\n if (fields.nonce !== req.nonce) {\n return { verified: false, reason: 'nonce_mismatch' as VerifyFailureReason };\n }\n\n return {\n verified: true,\n txHash: req.txHash,\n settledAmount: req.amount,\n settledAt: Math.floor(Date.now() / 1000),\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/constants.ts","../src/payment-kit.ts","../src/client.ts","../src/facilitator.ts"],"names":["usdcToRaw"],"mappings":"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","file":"index.js","sourcesContent":["export interface PaymentRequired {\n amount: string;\n asset: string;\n network: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n description?: string;\n}\n\nexport interface PaymentPayload {\n txHash: string;\n network: string;\n amount: string;\n nonce: string;\n}\n\nexport interface VerifyRequest {\n txHash: string;\n network: string;\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n expiresAt: number;\n}\n\nexport interface VerifyResponse {\n verified: boolean;\n txHash?: string;\n settledAmount?: string;\n settledAt?: number;\n reason?: VerifyFailureReason;\n}\n\nexport type VerifyFailureReason =\n | 'expired'\n | 'tx_not_found'\n | 'no_payment_event'\n | 'amount_mismatch'\n | 'wrong_recipient'\n | 'nonce_mismatch';\n\nexport interface SettleRequest {\n txHash: string;\n nonce: string;\n}\n\nexport interface SettleResponse {\n settled: boolean;\n}\n\nexport interface X402ClientOptions {\n maxPrice?: number;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeout?: number;\n dryRun?: boolean;\n onPayment?: (details: PaymentDetails) => void;\n}\n\nexport interface PaymentDetails {\n amount: string;\n asset: string;\n payTo: string;\n nonce: string;\n txHash: string;\n}\n\nexport type X402FetchOptions = X402ClientOptions;\n\nexport const X402_HEADERS = {\n PAYMENT_REQUIRED: 'payment-required',\n X_PAYMENT: 'x-payment',\n} as const;\n\nexport const DEFAULT_MAX_PRICE = 1.0;\nexport const DEFAULT_TIMEOUT = 30_000;\n","/**\n * Sui Payment Kit package ID (mainnet).\n * Source: github.com/MystenLabs/sui-payment-kit Move.lock `original-published-id`.\n */\nexport const PAYMENT_KIT_PACKAGE =\n process.env.PAYMENT_KIT_PACKAGE ??\n '0xbc126f1535fba7d641cb9150ad9eae93b104972586ba20f3c60bfe0e53b69bc6';\n\n/**\n * t2000's PaymentRegistry object ID (mainnet).\n * Created via `create_registry` on Payment Kit Namespace.\n * Tx: 666ZX1PhfV3PVJtqVZfuToHoVGoTDeWCxzZb1u8aRgmL\n */\nexport const T2000_PAYMENT_REGISTRY_ID =\n process.env.T2000_PAYMENT_REGISTRY_ID ??\n '0x4009dd17305ed1b33352b808e9d0e9eb94d09085b2d5ec0f395c5cdfa2271291';\n\nexport const USDC_TYPE =\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC';\n\nexport const CLOCK_ID = '0x6';\n\nexport const DEFAULT_FACILITATOR_URL = 'https://api.t2000.ai/x402';\n\nexport const PAYMENT_KIT_MODULE = 'payment_kit';\nexport const PAYMENT_KIT_FUNCTION = 'process_registry_payment';\nexport const PAYMENT_RECEIPT_EVENT_TYPE = `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::PaymentReceipt`;\n","import { Transaction } from '@mysten/sui/transactions';\nimport type { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';\nimport { usdcToRaw } from '@t2000/sdk';\nimport {\n PAYMENT_KIT_PACKAGE,\n PAYMENT_KIT_MODULE,\n PAYMENT_KIT_FUNCTION,\n T2000_PAYMENT_REGISTRY_ID,\n USDC_TYPE,\n CLOCK_ID,\n} from './constants.js';\n\nexport interface PaymentPTBParams {\n nonce: string;\n amount: string;\n payTo: string;\n}\n\n/**\n * Builds a payment PTB using USDC coins from the wallet.\n *\n * The Move function signature:\n * process_registry_payment<CoinType>(\n * registry: &mut PaymentRegistry<CoinType>,\n * nonce: String,\n * amount: u64,\n * coin: Coin<CoinType>,\n * receiver: Option<address>,\n * clock: &Clock\n * )\n *\n * Move enforces nonce uniqueness atomically via EDuplicatePayment.\n */\nexport async function buildPaymentTransaction(\n client: SuiJsonRpcClient,\n senderAddress: string,\n params: PaymentPTBParams,\n): Promise<Transaction> {\n const { nonce, amount, payTo } = params;\n const rawAmount = usdcToRaw(Number(amount));\n\n if (!T2000_PAYMENT_REGISTRY_ID) {\n throw new Error(\n 'T2000_PAYMENT_REGISTRY_ID is not set. ' +\n 'Create a PaymentRegistry<USDC> via Payment Kit before using x402.'\n );\n }\n\n const coins = await client.getCoins({\n owner: senderAddress,\n coinType: USDC_TYPE,\n });\n\n if (coins.data.length === 0) {\n throw new Error('No USDC coins found in wallet');\n }\n\n const tx = new Transaction();\n\n let primaryCoin = tx.object(coins.data[0].coinObjectId);\n if (coins.data.length > 1) {\n const otherCoins = coins.data.slice(1).map(c => tx.object(c.coinObjectId));\n tx.mergeCoins(primaryCoin, otherCoins);\n }\n\n const [paymentCoin] = tx.splitCoins(primaryCoin, [tx.pure.u64(rawAmount)]);\n\n tx.moveCall({\n target: `${PAYMENT_KIT_PACKAGE}::${PAYMENT_KIT_MODULE}::${PAYMENT_KIT_FUNCTION}`,\n arguments: [\n tx.object(T2000_PAYMENT_REGISTRY_ID),\n tx.pure.string(nonce),\n tx.pure.u64(rawAmount),\n paymentCoin,\n tx.pure.option('address', payTo),\n tx.object(CLOCK_ID),\n ],\n typeArguments: [USDC_TYPE],\n });\n\n return tx;\n}\n","import type { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';\nimport type { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { T2000Error } from '@t2000/sdk';\nimport type {\n PaymentRequired,\n PaymentPayload,\n X402FetchOptions,\n PaymentDetails,\n} from './types.js';\nimport {\n X402_HEADERS,\n DEFAULT_MAX_PRICE,\n DEFAULT_TIMEOUT,\n} from './types.js';\nimport { buildPaymentTransaction } from './payment-kit.js';\n\n/**\n * Parses the PAYMENT-REQUIRED header from a 402 response.\n * Validates network, asset, expiry, and price constraints.\n */\nexport function parsePaymentRequired(\n headerValue: string | null,\n maxPrice: number = DEFAULT_MAX_PRICE,\n): PaymentRequired {\n if (!headerValue) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n '402 response missing PAYMENT-REQUIRED header',\n );\n }\n\n let parsed: PaymentRequired;\n try {\n parsed = JSON.parse(headerValue);\n } catch {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'Malformed PAYMENT-REQUIRED header: invalid JSON',\n { raw: headerValue },\n );\n }\n\n if (!parsed.network || !parsed.amount || !parsed.payTo || !parsed.nonce || parsed.expiresAt == null) {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n 'PAYMENT-REQUIRED header missing required fields',\n { parsed },\n );\n }\n\n if (parsed.network !== 'sui') {\n throw new T2000Error(\n 'UNSUPPORTED_NETWORK',\n `x402 requires network \"${parsed.network}\" but only Sui is supported`,\n { network: parsed.network },\n );\n }\n\n if (parsed.asset && parsed.asset !== 'USDC') {\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `x402 requires asset \"${parsed.asset}\" but only USDC is supported`,\n { asset: parsed.asset },\n );\n }\n\n if (parsed.expiresAt < Date.now() / 1000) {\n throw new T2000Error(\n 'PAYMENT_EXPIRED',\n 'x402 payment challenge has expired',\n { expiresAt: parsed.expiresAt },\n );\n }\n\n const price = Number(parsed.amount);\n if (price > maxPrice) {\n throw new T2000Error(\n 'PRICE_EXCEEDS_LIMIT',\n `Requested price $${parsed.amount} exceeds max price $${maxPrice}`,\n { requested: parsed.amount, limit: maxPrice },\n );\n }\n\n return parsed;\n}\n\nexport interface X402Wallet {\n client: SuiJsonRpcClient;\n keypair: Ed25519Keypair;\n address(): string;\n signAndExecute(tx: unknown): Promise<{ digest: string }>;\n}\n\n/**\n * x402 client for Sui. Handles the full 402 payment flow:\n * 1. Sends initial request\n * 2. Detects 402 Payment Required\n * 3. Parses payment terms\n * 4. Builds and executes Payment Kit PTB\n * 5. Retries with X-PAYMENT proof header\n */\nexport class x402Client {\n private wallet: X402Wallet;\n\n constructor(wallet: X402Wallet) {\n this.wallet = wallet;\n }\n\n /**\n * Makes an HTTP request, handling x402 payment if required.\n * Non-402 responses pass through unmodified.\n */\n async fetch(url: string, options: X402FetchOptions = {}): Promise<Response> {\n const {\n maxPrice = DEFAULT_MAX_PRICE,\n method = 'GET',\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n dryRun = false,\n onPayment,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const initial = await globalThis.fetch(url, {\n method,\n headers,\n body,\n signal: controller.signal,\n });\n\n if (initial.status !== 402) {\n return initial;\n }\n\n const paymentRequired = parsePaymentRequired(\n initial.headers.get(X402_HEADERS.PAYMENT_REQUIRED),\n maxPrice,\n );\n\n if (dryRun) {\n return new Response(\n JSON.stringify({\n dryRun: true,\n amount: paymentRequired.amount,\n asset: paymentRequired.asset,\n payTo: paymentRequired.payTo,\n network: paymentRequired.network,\n }),\n { status: 200, headers: { 'content-type': 'application/json' } },\n );\n }\n\n const tx = await buildPaymentTransaction(\n this.wallet.client,\n this.wallet.address(),\n {\n nonce: paymentRequired.nonce,\n amount: paymentRequired.amount,\n payTo: paymentRequired.payTo,\n },\n );\n\n let result: { digest: string };\n try {\n result = await this.wallet.signAndExecute(tx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes('EDuplicatePayment') || msg.includes('duplicate')) {\n throw new T2000Error(\n 'DUPLICATE_PAYMENT',\n 'Payment nonce already used on-chain',\n { nonce: paymentRequired.nonce },\n );\n }\n if (msg.includes('InsufficientCoinBalance') || msg.includes('Insufficient')) {\n throw new T2000Error(\n 'INSUFFICIENT_BALANCE',\n 'Not enough USDC to complete payment',\n { required: paymentRequired.amount },\n );\n }\n throw new T2000Error(\n 'TRANSACTION_FAILED',\n `Payment transaction failed: ${msg}`,\n { nonce: paymentRequired.nonce },\n );\n }\n\n const paymentDetails: PaymentDetails = {\n amount: paymentRequired.amount,\n asset: paymentRequired.asset || 'USDC',\n payTo: paymentRequired.payTo,\n nonce: paymentRequired.nonce,\n txHash: result.digest,\n };\n\n onPayment?.(paymentDetails);\n\n const paymentPayload: PaymentPayload = {\n txHash: result.digest,\n network: 'sui',\n amount: paymentRequired.amount,\n nonce: paymentRequired.nonce,\n };\n\n const retry = await globalThis.fetch(url, {\n method,\n headers: {\n ...headers,\n [X402_HEADERS.X_PAYMENT]: JSON.stringify(paymentPayload),\n },\n body,\n signal: controller.signal,\n });\n\n return retry;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","import type { SuiJsonRpcClient, SuiEvent } from '@mysten/sui/jsonRpc';\nimport { usdcToRaw } from '@t2000/sdk';\nimport type {\n VerifyRequest,\n VerifyResponse,\n VerifyFailureReason,\n} from './types.js';\nimport { PAYMENT_RECEIPT_EVENT_TYPE } from './constants.js';\n\ninterface PaymentReceiptFields {\n payment_amount: string;\n receiver: string;\n nonce: string;\n coin_type?: string;\n timestamp_ms?: string;\n}\n\nfunction isPaymentReceipt(event: SuiEvent): boolean {\n return event.type === PAYMENT_RECEIPT_EVENT_TYPE;\n}\n\nfunction parsePaymentReceiptFields(event: SuiEvent): PaymentReceiptFields | null {\n const json = event.parsedJson as Record<string, unknown> | undefined;\n if (!json) return null;\n\n return {\n payment_amount: String(json.payment_amount ?? ''),\n receiver: String(json.receiver ?? ''),\n nonce: String(json.nonce ?? ''),\n coin_type: json.coin_type ? String(json.coin_type) : undefined,\n timestamp_ms: json.timestamp_ms ? String(json.timestamp_ms) : undefined,\n };\n}\n\n/**\n * Verifies an x402 payment by checking the Sui transaction on-chain.\n *\n * Verification steps:\n * 1. Check if the challenge has expired\n * 2. Fetch the transaction from Sui RPC\n * 3. Find the PaymentReceipt event emitted by Payment Kit\n * 4. Validate amount, recipient, and nonce match the request\n *\n * Duplicate nonces are already prevented by Move's EDuplicatePayment.\n * This function only verifies payments that successfully landed on-chain.\n */\nexport async function verifyPayment(\n client: SuiJsonRpcClient,\n req: VerifyRequest,\n): Promise<VerifyResponse> {\n if (Date.now() / 1000 > req.expiresAt) {\n return { verified: false, reason: 'expired' };\n }\n\n let tx;\n try {\n tx = await client.getTransactionBlock({\n digest: req.txHash,\n options: { showEffects: true, showEvents: true },\n });\n } catch {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n if (!tx) {\n return { verified: false, reason: 'tx_not_found' };\n }\n\n const receiptEvent = tx.events?.find(isPaymentReceipt);\n if (!receiptEvent) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const fields = parsePaymentReceiptFields(receiptEvent);\n if (!fields) {\n return { verified: false, reason: 'no_payment_event' };\n }\n\n const expectedAmount = usdcToRaw(Number(req.amount));\n if (BigInt(fields.payment_amount) !== expectedAmount) {\n return { verified: false, reason: 'amount_mismatch' };\n }\n\n if (fields.receiver !== req.payTo) {\n return { verified: false, reason: 'wrong_recipient' };\n }\n\n if (fields.nonce !== req.nonce) {\n return { verified: false, reason: 'nonce_mismatch' as VerifyFailureReason };\n }\n\n return {\n verified: true,\n txHash: req.txHash,\n settledAmount: req.amount,\n settledAt: Math.floor(Date.now() / 1000),\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t2000/x402",
3
- "version": "0.2.6",
3
+ "version": "0.3.0",
4
4
  "description": "x402 payment protocol client for AI agents on Sui — pay for API resources with USDC",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -35,8 +35,8 @@
35
35
  },
36
36
  "homepage": "https://t2000.ai",
37
37
  "dependencies": {
38
- "@mysten/sui": "^1",
39
- "@t2000/sdk": "0.2.6"
38
+ "@mysten/sui": "^2",
39
+ "@t2000/sdk": "0.5.2"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^22",