@t2000/x402 0.2.4 → 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
@@ -100,36 +100,43 @@ const res = await client.fetch('https://api.example.com/data', {
100
100
  });
101
101
  ```
102
102
 
103
- ### `parsePaymentRequired(response)`
103
+ ### `parsePaymentRequired(headerValue, maxPrice?)`
104
104
 
105
- Parses a 402 response into structured payment terms.
105
+ Parses the `PAYMENT-REQUIRED` header from a 402 response into structured payment terms. Validates network (must be `sui`), asset (must be `USDC`), expiry, and price limit.
106
106
 
107
107
  ```typescript
108
108
  import { parsePaymentRequired } from '@t2000/x402';
109
109
 
110
- const terms = parsePaymentRequired(response);
111
- // { amount: 10000, recipient: '0x...', network: 'sui', ... }
110
+ const headerValue = response.headers.get('payment-required');
111
+ const terms = parsePaymentRequired(headerValue, 1.0);
112
+ // { amount: '0.01', payTo: '0x...', network: 'sui', nonce: '...', expiresAt: 1709... }
112
113
  ```
113
114
 
114
115
  ## Facilitator API (Server-Side)
115
116
 
116
117
  For API providers who want to accept x402 payments:
117
118
 
118
- ### `verifyPayment(params)`
119
+ ### `verifyPayment(client, request)`
119
120
 
120
- Verify that an on-chain payment transaction is valid.
121
+ Verify that an on-chain payment transaction is valid. Checks the transaction for a `PaymentReceipt` event and validates amount, recipient, and nonce.
121
122
 
122
123
  ```typescript
123
124
  import { verifyPayment } from '@t2000/x402';
125
+ import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
124
126
 
125
- const result = await verifyPayment({
126
- txDigest: 'ABC123...',
127
- expectedAmount: 10000, // 0.01 USDC in raw units (6 decimals)
128
- expectedRecipient: '0x...',
129
- client: suiClient, // SuiClient instance
127
+ const client = new SuiJsonRpcClient({ url: getJsonRpcFullnodeUrl('mainnet'), network: 'mainnet' });
128
+
129
+ const result = await verifyPayment(client, {
130
+ txHash: 'ABC123...',
131
+ amount: '0.01',
132
+ asset: 'USDC',
133
+ payTo: '0x...',
134
+ nonce: 'unique-nonce',
135
+ expiresAt: 1709500000,
136
+ network: 'sui',
130
137
  });
131
138
 
132
- if (result.valid) {
139
+ if (result.verified) {
133
140
  // Payment verified — serve the resource
134
141
  }
135
142
  ```
@@ -148,14 +155,15 @@ Payments are executed on-chain via the [Sui Payment Kit](https://docs.sui.io/sta
148
155
 
149
156
  ```typescript
150
157
  import { buildPaymentTransaction } from '@t2000/x402';
158
+ import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
159
+
160
+ const client = new SuiJsonRpcClient({ url: getJsonRpcFullnodeUrl('mainnet'), network: 'mainnet' });
151
161
 
152
162
  // Build a payment transaction (advanced usage)
153
- const tx = buildPaymentTransaction({
154
- registryId: '0x...',
155
- recipient: '0x...',
156
- amount: 10000n, // raw USDC units
163
+ const tx = await buildPaymentTransaction(client, senderAddress, {
157
164
  nonce: 'unique-nonce',
158
- coinObjectId: '0x...',
165
+ amount: '0.01', // USDC as string (converted to raw internally)
166
+ payTo: '0x...',
159
167
  });
160
168
  ```
161
169
 
@@ -180,7 +188,7 @@ Any wallet implementing `X402Wallet` can be used as a payment source:
180
188
 
181
189
  ```typescript
182
190
  interface X402Wallet {
183
- client: SuiClient;
191
+ client: SuiJsonRpcClient;
184
192
  keypair: Ed25519Keypair;
185
193
  address(): string;
186
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":";;;;;;;;AAwEO,IAAM,YAAA,GAAe;AAAA,EAC1B,gBAAA,EAAkB,kBAAA;AAAA,EAClB,SAAA,EAAW;AACb;AAEO,IAAM,iBAAA,GAAoB;AAC1B,IAAM,eAAA,GAAkB;;;AC1ExB,IAAM,mBAAA,GACX,OAAA,CAAQ,GAAA,CAAI,mBAAA,IACZ;AAOK,IAAM,yBAAA,GACX,OAAA,CAAQ,GAAA,CAAI,yBAAA,IACZ;AAEK,IAAM,SAAA,GACX;AAEK,IAAM,QAAA,GAAW;AAEjB,IAAM,uBAAA,GAA0B;AAEhC,IAAM,kBAAA,GAAqB;AAC3B,IAAM,oBAAA,GAAuB;AAC7B,IAAM,0BAAA,GAA6B,CAAA,EAAG,mBAAmB,CAAA,EAAA,EAAK,kBAAkB,CAAA,gBAAA;;;ACOvF,eAAsB,uBAAA,CACpB,MAAA,EACA,aAAA,EACA,MAAA,EACsB;AACtB,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAM,GAAI,MAAA;AACjC,EAAA,MAAM,SAAA,GAAYA,aAAA,CAAU,MAAA,CAAO,MAAM,CAAC,CAAA;AAE1C,EAAA,IAAI,CAAC,yBAAA,EAA2B;AAC9B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,QAAA,CAAS;AAAA,IAClC,KAAA,EAAO,aAAA;AAAA,IACP,QAAA,EAAU;AAAA,GACX,CAAA;AAED,EAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,EAAA,GAAK,IAAIC,wBAAA,EAAY;AAE3B,EAAA,IAAI,cAAc,EAAA,CAAG,MAAA,CAAO,MAAM,IAAA,CAAK,CAAC,EAAE,YAAY,CAAA;AACtD,EAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG;AACzB,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,EAAA,CAAG,MAAA,CAAO,CAAA,CAAE,YAAY,CAAC,CAAA;AACzE,IAAA,EAAA,CAAG,UAAA,CAAW,aAAa,UAAU,CAAA;AAAA,EACvC;AAEA,EAAA,MAAM,CAAC,WAAW,CAAA,GAAI,EAAA,CAAG,UAAA,CAAW,WAAA,EAAa,CAAC,EAAA,CAAG,IAAA,CAAK,GAAA,CAAI,SAAS,CAAC,CAAC,CAAA;AAEzE,EAAA,EAAA,CAAG,QAAA,CAAS;AAAA,IACV,QAAQ,CAAA,EAAG,mBAAmB,CAAA,EAAA,EAAK,kBAAkB,KAAK,oBAAoB,CAAA,CAAA;AAAA,IAC9E,SAAA,EAAW;AAAA,MACT,EAAA,CAAG,OAAO,yBAAyB,CAAA;AAAA,MACnC,EAAA,CAAG,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAAA,MACpB,EAAA,CAAG,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA;AAAA,MACrB,WAAA;AAAA,MACA,EAAA,CAAG,IAAA,CAAK,MAAA,CAAO,SAAA,EAAW,KAAK,CAAA;AAAA,MAC/B,EAAA,CAAG,OAAO,QAAQ;AAAA,KACpB;AAAA,IACA,aAAA,EAAe,CAAC,SAAS;AAAA,GAC1B,CAAA;AAED,EAAA,OAAO,EAAA;AACT;;;AC7DO,SAAS,oBAAA,CACd,WAAA,EACA,QAAA,GAAmB,iBAAA,EACF;AACjB,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,MAAM,IAAIC,cAAA;AAAA,MACR,oBAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,WAAW,CAAA;AAAA,EACjC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAIA,cAAA;AAAA,MACR,oBAAA;AAAA,MACA,iDAAA;AAAA,MACA,EAAE,KAAK,WAAA;AAAY,KACrB;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,CAAC,OAAO,MAAA,IAAU,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO,aAAa,IAAA,EAAM;AACnG,IAAA,MAAM,IAAIA,cAAA;AAAA,MACR,oBAAA;AAAA,MACA,iDAAA;AAAA,MACA,EAAE,MAAA;AAAO,KACX;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,YAAY,KAAA,EAAO;AAC5B,IAAA,MAAM,IAAIA,cAAA;AAAA,MACR,qBAAA;AAAA,MACA,CAAA,uBAAA,EAA0B,OAAO,OAAO,CAAA,2BAAA,CAAA;AAAA,MACxC,EAAE,OAAA,EAAS,MAAA,CAAO,OAAA;AAAQ,KAC5B;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO,KAAA,KAAU,MAAA,EAAQ;AAC3C,IAAA,MAAM,IAAIA,cAAA;AAAA,MACR,oBAAA;AAAA,MACA,CAAA,qBAAA,EAAwB,OAAO,KAAK,CAAA,4BAAA,CAAA;AAAA,MACpC,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA;AAAM,KACxB;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,SAAA,GAAY,IAAA,CAAK,GAAA,KAAQ,GAAA,EAAM;AACxC,IAAA,MAAM,IAAIA,cAAA;AAAA,MACR,iBAAA;AAAA,MACA,oCAAA;AAAA,MACA,EAAE,SAAA,EAAW,MAAA,CAAO,SAAA;AAAU,KAChC;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA;AAClC,EAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,IAAA,MAAM,IAAIA,cAAA;AAAA,MACR,qBAAA;AAAA,MACA,CAAA,iBAAA,EAAoB,MAAA,CAAO,MAAM,CAAA,oBAAA,EAAuB,QAAQ,CAAA,CAAA;AAAA,MAChE,EAAE,SAAA,EAAW,MAAA,CAAO,MAAA,EAAQ,OAAO,QAAA;AAAS,KAC9C;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAiBO,IAAM,aAAN,MAAiB;AAAA,EACd,MAAA;AAAA,EAER,YAAY,MAAA,EAAoB;AAC9B,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAA,CAAM,GAAA,EAAa,OAAA,GAA4B,EAAC,EAAsB;AAC1E,IAAA,MAAM;AAAA,MACJ,QAAA,GAAW,iBAAA;AAAA,MACX,MAAA,GAAS,KAAA;AAAA,MACT,UAAU,EAAC;AAAA,MACX,IAAA;AAAA,MACA,OAAA,GAAU,eAAA;AAAA,MACV,MAAA,GAAS,KAAA;AAAA,MACT;AAAA,KACF,GAAI,OAAA;AAEJ,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,YAAY,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,OAAO,CAAA;AAE9D,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,KAAA,CAAM,GAAA,EAAK;AAAA,QAC1C,MAAA;AAAA,QACA,OAAA;AAAA,QACA,IAAA;AAAA,QACA,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAED,MAAA,IAAI,OAAA,CAAQ,WAAW,GAAA,EAAK;AAC1B,QAAA,OAAO,OAAA;AAAA,MACT;AAEA,MAAA,MAAM,eAAA,GAAkB,oBAAA;AAAA,QACtB,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,YAAA,CAAa,gBAAgB,CAAA;AAAA,QACjD;AAAA,OACF;AAEA,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,OAAO,IAAI,QAAA;AAAA,UACT,KAAK,SAAA,CAAU;AAAA,YACb,MAAA,EAAQ,IAAA;AAAA,YACR,QAAQ,eAAA,CAAgB,MAAA;AAAA,YACxB,OAAO,eAAA,CAAgB,KAAA;AAAA,YACvB,OAAO,eAAA,CAAgB,KAAA;AAAA,YACvB,SAAS,eAAA,CAAgB;AAAA,WAC1B,CAAA;AAAA,UACD,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,cAAA,EAAgB,oBAAmB;AAAE,SACjE;AAAA,MACF;AAEA,MAAA,MAAM,KAAK,MAAM,uBAAA;AAAA,QACf,KAAK,MAAA,CAAO,MAAA;AAAA,QACZ,IAAA,CAAK,OAAO,OAAA,EAAQ;AAAA,QACpB;AAAA,UACE,OAAO,eAAA,CAAgB,KAAA;AAAA,UACvB,QAAQ,eAAA,CAAgB,MAAA;AAAA,UACxB,OAAO,eAAA,CAAgB;AAAA;AACzB,OACF;AAEA,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,cAAA,CAAe,EAAE,CAAA;AAAA,MAC9C,SAAS,GAAA,EAAK;AACZ,QAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,QAAA,IAAI,IAAI,QAAA,CAAS,mBAAmB,KAAK,GAAA,CAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAClE,UAAA,MAAM,IAAIA,cAAA;AAAA,YACR,mBAAA;AAAA,YACA,qCAAA;AAAA,YACA,EAAE,KAAA,EAAO,eAAA,CAAgB,KAAA;AAAM,WACjC;AAAA,QACF;AACA,QAAA,IAAI,IAAI,QAAA,CAAS,yBAAyB,KAAK,GAAA,CAAI,QAAA,CAAS,cAAc,CAAA,EAAG;AAC3E,UAAA,MAAM,IAAIA,cAAA;AAAA,YACR,sBAAA;AAAA,YACA,qCAAA;AAAA,YACA,EAAE,QAAA,EAAU,eAAA,CAAgB,MAAA;AAAO,WACrC;AAAA,QACF;AACA,QAAA,MAAM,IAAIA,cAAA;AAAA,UACR,oBAAA;AAAA,UACA,+BAA+B,GAAG,CAAA,CAAA;AAAA,UAClC,EAAE,KAAA,EAAO,eAAA,CAAgB,KAAA;AAAM,SACjC;AAAA,MACF;AAEA,MAAA,MAAM,cAAA,GAAiC;AAAA,QACrC,QAAQ,eAAA,CAAgB,MAAA;AAAA,QACxB,KAAA,EAAO,gBAAgB,KAAA,IAAS,MAAA;AAAA,QAChC,OAAO,eAAA,CAAgB,KAAA;AAAA,QACvB,OAAO,eAAA,CAAgB,KAAA;AAAA,QACvB,QAAQ,MAAA,CAAO;AAAA,OACjB;AAEA,MAAA,SAAA,GAAY,cAAc,CAAA;AAE1B,MAAA,MAAM,cAAA,GAAiC;AAAA,QACrC,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,OAAA,EAAS,KAAA;AAAA,QACT,QAAQ,eAAA,CAAgB,MAAA;AAAA,QACxB,OAAO,eAAA,CAAgB;AAAA,OACzB;AAEA,MAAA,MAAM,KAAA,GAAQ,MAAM,UAAA,CAAW,KAAA,CAAM,GAAA,EAAK;AAAA,QACxC,MAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,GAAG,OAAA;AAAA,UACH,CAAC,YAAA,CAAa,SAAS,GAAG,IAAA,CAAK,UAAU,cAAc;AAAA,SACzD;AAAA,QACA,IAAA;AAAA,QACA,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAED,MAAA,OAAO,KAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,SAAS,CAAA;AAAA,IACxB;AAAA,EACF;AACF;AC/MA,SAAS,iBAAiB,KAAA,EAA0B;AAClD,EAAA,OAAO,MAAM,IAAA,KAAS,0BAAA;AACxB;AAEA,SAAS,0BAA0B,KAAA,EAA8C;AAC/E,EAAA,MAAM,OAAO,KAAA,CAAM,UAAA;AACnB,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,OAAO;AAAA,IACL,cAAA,EAAgB,MAAA,CAAO,IAAA,CAAK,cAAA,IAAkB,EAAE,CAAA;AAAA,IAChD,QAAA,EAAU,MAAA,CAAO,IAAA,CAAK,QAAA,IAAY,EAAE,CAAA;AAAA,IACpC,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,KAAA,IAAS,EAAE,CAAA;AAAA,IAC9B,WAAW,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA,GAAI,MAAA;AAAA,IACrD,cAAc,IAAA,CAAK,YAAA,GAAe,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,GAAI;AAAA,GAChE;AACF;AAcA,eAAsB,aAAA,CACpB,QACA,GAAA,EACyB;AACzB,EAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,GAAA,GAAO,IAAI,SAAA,EAAW;AACrC,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,SAAA,EAAU;AAAA,EAC9C;AAEA,EAAA,IAAI,EAAA;AACJ,EAAA,IAAI;AACF,IAAA,EAAA,GAAK,MAAM,OAAO,mBAAA,CAAoB;AAAA,MACpC,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,OAAA,EAAS,EAAE,WAAA,EAAa,IAAA,EAAM,YAAY,IAAA;AAAK,KAChD,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,cAAA,EAAe;AAAA,EACnD;AAEA,EAAA,IAAI,CAAC,EAAA,EAAI;AACP,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,cAAA,EAAe;AAAA,EACnD;AAEA,EAAA,MAAM,YAAA,GAAe,EAAA,CAAG,MAAA,EAAQ,IAAA,CAAK,gBAAgB,CAAA;AACrD,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,kBAAA,EAAmB;AAAA,EACvD;AAEA,EAAA,MAAM,MAAA,GAAS,0BAA0B,YAAY,CAAA;AACrD,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,kBAAA,EAAmB;AAAA,EACvD;AAEA,EAAA,MAAM,cAAA,GAAiBF,aAAAA,CAAU,MAAA,CAAO,GAAA,CAAI,MAAM,CAAC,CAAA;AACnD,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,cAAc,CAAA,KAAM,cAAA,EAAgB;AACpD,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,iBAAA,EAAkB;AAAA,EACtD;AAEA,EAAA,IAAI,MAAA,CAAO,QAAA,KAAa,GAAA,CAAI,KAAA,EAAO;AACjC,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,iBAAA,EAAkB;AAAA,EACtD;AAEA,EAAA,IAAI,MAAA,CAAO,KAAA,KAAU,GAAA,CAAI,KAAA,EAAO;AAC9B,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,gBAAA,EAAwC;AAAA,EAC5E;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,IAAA;AAAA,IACV,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,eAAe,GAAA,CAAI,MAAA;AAAA,IACnB,WAAW,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI;AAAA,GACzC;AACF","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.4",
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.4"
38
+ "@mysten/sui": "^2",
39
+ "@t2000/sdk": "0.5.2"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^22",