@paynodelabs/sdk-js 2.2.0 → 2.2.2

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
@@ -3,7 +3,7 @@
3
3
  [![Official Documentation](https://img.shields.io/badge/Docs-docs.paynode.dev-00ff88?style=for-the-badge&logo=readthedocs)](https://docs.paynode.dev)
4
4
  [![NPM Version](https://img.shields.io/npm/v/@paynodelabs/sdk-js.svg?style=for-the-badge)](https://www.npmjs.com/package/@paynodelabs/sdk-js)
5
5
 
6
- The official TypeScript/JavaScript SDK for the **PayNode Protocol (v2.2.0)**. PayNode is a stateless, non-custodial M2M payment gateway that standardizes the HTTP 402 "Payment Required" flow for AI Agents, with support for both on-chain receipts and off-chain signatures (EIP-3009).
6
+ The official TypeScript/JavaScript SDK for the **PayNode Protocol (v2.2.1)**. PayNode is a stateless, non-custodial M2M payment gateway that standardizes the HTTP 402 "Payment Required" flow for AI Agents, with support for both on-chain receipts and off-chain signatures (EIP-3009).
7
7
 
8
8
  ## 📖 Read the Docs
9
9
 
@@ -33,7 +33,7 @@ async function main() {
33
33
  main();
34
34
  ```
35
35
 
36
- ### Key Features (v2.2.0)
36
+ ### Key Features (v2.2.1)
37
37
  - **Zero-Wait Checkout**: API response speed drops from 5 seconds to **under 50ms** by using local signatures instead of waiting for on-chain inclusion.
38
38
  - **Double-Spend Protection**:
39
39
  - **L1 (Memory)**: High-speed local replay protection via `IdempotencyStore`.
@@ -104,4 +104,18 @@ To publish a new version of the SDK:
104
104
 
105
105
  ---
106
106
 
107
+ ## Versioning Guide
108
+
109
+ PayNode uses two distinct versioning schemes:
110
+
111
+ | Version Type | Description | Current Value |
112
+ | :--- | :--- | :--- |
113
+ | **Protocol Version** | On-chain contracts & core x402 data schema. | `1.4.0` |
114
+ | **SDK/Product Version** | Software package version (npm/SemVer). | `2.2.2` |
115
+
116
+ > [!NOTE]
117
+ > Protocol Version changes imply breaking changes in verification or contract interfaces. SDK Version changes may include features, fixes, or performance improvements without altering protocol logic.
118
+
119
+ ---
120
+
107
121
  _Built for the Autonomous AI Economy by PayNodeLabs._
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,eAAe,EAEhB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAID,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAoC;IAErD,OAAO,CAAC,SAAS,CAMf;IAEF,OAAO,CAAC,UAAU,CAAsB;gBAE5B,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,GAAG,MAAM,EAAkB,EAAE,UAAU,GAAE,MAAU;YAepF,eAAe;IAoCvB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;YAoDjE,aAAa;IAwJrB,6BAA6B,CACjC,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAC9B,OAAO,CAAC,eAAe,CAAC;IA6CrB,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBpH,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BrJ,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAE,MAAa,EAAE,OAAO,GAAE,MAAY;;;;;;YAyChH,UAAU;CAYzB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,eAAe,EAEhB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAID,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAoC;IAErD,OAAO,CAAC,SAAS,CAMf;IAEF,OAAO,CAAC,UAAU,CAAsB;gBAE5B,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,GAAG,MAAM,EAAkB,EAAE,UAAU,GAAE,MAAU;YAepF,eAAe;IAoCvB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;YAuEjE,aAAa;IAkKrB,6BAA6B,CACjC,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAC9B,OAAO,CAAC,eAAe,CAAC;IA+CrB,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBpH,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BrJ,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAE,MAAa,EAAE,OAAO,GAAE,MAAY;;;;;;YAyChH,UAAU;CAYzB"}
package/dist/client.js CHANGED
@@ -63,11 +63,17 @@ class PayNodeAgentClient {
63
63
  }
64
64
  async requestGate(url, options = {}) {
65
65
  const fetchOptions = { ...options };
66
+ const network = await this.provider.getNetwork();
67
+ const paynodeNetwork = Number(network.chainId) === 8453 ? 'mainnet' : 'testnet';
68
+ fetchOptions.headers = {
69
+ 'X-PayNode-Network': paynodeNetwork,
70
+ ...fetchOptions.headers
71
+ };
66
72
  if (options.json && !fetchOptions.body) {
67
73
  fetchOptions.body = JSON.stringify(options.json);
68
74
  fetchOptions.headers = {
69
- 'Content-Type': 'application/json',
70
- ...fetchOptions.headers
75
+ ...fetchOptions.headers,
76
+ 'Content-Type': 'application/json'
71
77
  };
72
78
  }
73
79
  try {
@@ -78,20 +84,28 @@ class PayNodeAgentClient {
78
84
  const b64Required = response.headers.get('PAYMENT-REQUIRED') || response.headers.get('X-402-Required');
79
85
  const orderId = response.headers.get('X-402-Order-Id');
80
86
  let body = null;
81
- if (contentType && contentType.includes('application/json')) {
82
- body = await response.clone().json();
83
- }
84
- else if (b64Required) {
87
+ let headerBody = null;
88
+ if (b64Required) {
85
89
  try {
86
90
  const decoded = typeof globalThis.Buffer !== 'undefined'
87
91
  ? globalThis.Buffer.from(b64Required, 'base64').toString()
88
92
  : atob(b64Required);
89
- body = JSON.parse(decoded);
93
+ headerBody = JSON.parse(decoded);
90
94
  }
91
95
  catch (e) {
92
96
  console.debug('⚠️ [PayNode-JS] Failed to parse PAYMENT-REQUIRED header:', e);
93
97
  }
94
98
  }
99
+ if (contentType && contentType.includes('application/json')) {
100
+ try {
101
+ body = await response.clone().json();
102
+ }
103
+ catch (e) { /* ignore */ }
104
+ }
105
+ // Robustness: Merge header info into body if body is missing critical bits
106
+ if (headerBody && (!body || !body.x402Version)) {
107
+ body = { ...body, ...headerBody };
108
+ }
95
109
  if (body && body.x402Version === 2) {
96
110
  console.log(`🚀 [PayNode-JS] x402 v2 detected. Handling autonomous payment...`);
97
111
  if (orderId && !body.orderId)
@@ -118,6 +132,7 @@ class PayNodeAgentClient {
118
132
  if (!requirement) {
119
133
  throw new errors_1.PayNodeException(errors_1.ErrorCode.TransactionFailed, `No compatible payment requirement found for network ${caip2ChainId}`);
120
134
  }
135
+ console.log(`💡 [PayNode-JS] Selected payment method: ${requirement.type || 'onchain'} on ${requirement.network}`);
121
136
  // 🛡️ Token Whitelist Check (Case-insensitive)
122
137
  const chainTokens = constants_1.ACCEPTED_TOKENS[chainId]?.map(t => t.toLowerCase());
123
138
  if (chainTokens && !chainTokens.includes(requirement.asset.toLowerCase())) {
@@ -148,7 +163,7 @@ class PayNodeAgentClient {
148
163
  },
149
164
  payload: authorization,
150
165
  _paynode: {
151
- version: "2.2.0",
166
+ version: constants_1.SDK_VERSION,
152
167
  type: 'eip3009',
153
168
  orderId: orderId
154
169
  }
@@ -192,7 +207,7 @@ class PayNodeAgentClient {
192
207
  },
193
208
  payload: { txHash },
194
209
  _paynode: {
195
- version: "2.2.0",
210
+ version: constants_1.SDK_VERSION,
196
211
  type: 'onchain',
197
212
  orderId: orderId
198
213
  }
@@ -202,6 +217,7 @@ class PayNodeAgentClient {
202
217
  const b64Payload = typeof globalThis.Buffer !== 'undefined'
203
218
  ? globalThis.Buffer.from(payloadJson).toString('base64')
204
219
  : btoa(payloadJson);
220
+ const paynodeNetwork = chainId === 8453 ? 'mainnet' : 'testnet';
205
221
  const retryOptions = {
206
222
  ...options,
207
223
  headers: {
@@ -209,7 +225,8 @@ class PayNodeAgentClient {
209
225
  'Content-Type': 'application/json',
210
226
  'PAYMENT-SIGNATURE': b64Payload,
211
227
  'X-402-Payload': b64Payload, // Keep for backward compatibility
212
- 'X-402-Order-Id': orderId
228
+ 'X-402-Order-Id': orderId,
229
+ 'X-PayNode-Network': paynodeNetwork
213
230
  }
214
231
  };
215
232
  const retryResponse = await this._fetchWithRetry(url, retryOptions);
@@ -220,9 +237,15 @@ class PayNodeAgentClient {
220
237
  const settleHeader = retryResponse.headers.get('PAYMENT-RESPONSE') || retryResponse.headers.get('X-PAYMENT-RESPONSE');
221
238
  if (settleHeader) {
222
239
  try {
223
- const decoded = typeof globalThis.Buffer !== 'undefined'
224
- ? globalThis.Buffer.from(settleHeader, 'base64').toString()
225
- : atob(settleHeader);
240
+ let decoded;
241
+ if (settleHeader.trim().startsWith('{')) {
242
+ decoded = settleHeader;
243
+ }
244
+ else {
245
+ decoded = typeof globalThis.Buffer !== 'undefined'
246
+ ? globalThis.Buffer.from(settleHeader, 'base64').toString()
247
+ : atob(settleHeader);
248
+ }
226
249
  const settleData = JSON.parse(decoded);
227
250
  if (settleData.success) {
228
251
  console.log(`✅ [PayNode-JS] Settlement confirmed: ${settleData.transaction}`);
@@ -239,10 +262,12 @@ class PayNodeAgentClient {
239
262
  }
240
263
  async signTransferWithAuthorization(tokenAddr, to, amount, validAfter, validBefore, nonce, extra = {}) {
241
264
  const network = await this.provider.getNetwork();
265
+ const chainId = Number(network.chainId);
266
+ const defaultName = chainId === 8453 ? "USDC" : "USD Coin";
242
267
  const domain = {
243
- name: extra.name || "USD Coin",
268
+ name: extra.name || defaultName,
244
269
  version: extra.version || "2",
245
- chainId: Number(network.chainId),
270
+ chainId: chainId,
246
271
  verifyingContract: tokenAddr
247
272
  };
248
273
  const types = {
@@ -1,4 +1,4 @@
1
- /** Generated by scripts/sync-config.py */
1
+ /** Generated by meta/scripts/sync-config.py */
2
2
  export declare const PAYNODE_ROUTER_ADDRESS = "0x4A73696ccF76E7381b044cB95127B3784369Ed63";
3
3
  export declare const PAYNODE_ROUTER_ADDRESS_SANDBOX = "0x24cD8b68aaC209217ff5a6ef1Bf55a59f2c8Ca6F";
4
4
  export declare const BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
@@ -6,6 +6,7 @@ export declare const BASE_USDC_ADDRESS_SANDBOX = "0x65c088EfBDB0E03185Dbe8e258Ad
6
6
  export declare const PROTOCOL_TREASURY = "0x598bF63F5449876efafa7b36b77Deb2070621C0E";
7
7
  export declare const PROTOCOL_FEE_BPS = 100;
8
8
  export declare const MIN_PAYMENT_AMOUNT: bigint;
9
+ export declare const SDK_VERSION = "2.2.2";
9
10
  export declare const BASE_RPC_URLS: string[];
10
11
  export declare const BASE_RPC_URLS_SANDBOX: string[];
11
12
  export declare const ACCEPTED_TOKENS: Record<number, string[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,+CAA+C,CAAC;AACnF,eAAO,MAAM,8BAA8B,+CAA+C,CAAC;AAC3F,eAAO,MAAM,iBAAiB,+CAA+C,CAAC;AAC9E,eAAO,MAAM,yBAAyB,+CAA+C,CAAC;AACtF,eAAO,MAAM,iBAAiB,+CAA+C,CAAC;AAC9E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,kBAAkB,QAAe,CAAC;AAE/C,eAAO,MAAM,aAAa,UAAmF,CAAC;AAC9G,eAAO,MAAM,qBAAqB,UAA0E,CAAC;AAE7G,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAGpD,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAA25K,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,+CAA+C,CAAC;AACnF,eAAO,MAAM,8BAA8B,+CAA+C,CAAC;AAC3F,eAAO,MAAM,iBAAiB,+CAA+C,CAAC;AAC9E,eAAO,MAAM,yBAAyB,+CAA+C,CAAC;AACtF,eAAO,MAAM,iBAAiB,+CAA+C,CAAC;AAC9E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,kBAAkB,QAAe,CAAC;AAC/C,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,eAAO,MAAM,aAAa,UAAmF,CAAC;AAC9G,eAAO,MAAM,qBAAqB,UAA0E,CAAC;AAE7G,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAGpD,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAA25K,CAAC"}
package/dist/constants.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PAYNODE_ROUTER_ABI = exports.ACCEPTED_TOKENS = exports.BASE_RPC_URLS_SANDBOX = exports.BASE_RPC_URLS = exports.MIN_PAYMENT_AMOUNT = exports.PROTOCOL_FEE_BPS = exports.PROTOCOL_TREASURY = exports.BASE_USDC_ADDRESS_SANDBOX = exports.BASE_USDC_ADDRESS = exports.PAYNODE_ROUTER_ADDRESS_SANDBOX = exports.PAYNODE_ROUTER_ADDRESS = void 0;
4
- /** Generated by scripts/sync-config.py */
3
+ exports.PAYNODE_ROUTER_ABI = exports.ACCEPTED_TOKENS = exports.BASE_RPC_URLS_SANDBOX = exports.BASE_RPC_URLS = exports.SDK_VERSION = exports.MIN_PAYMENT_AMOUNT = exports.PROTOCOL_FEE_BPS = exports.PROTOCOL_TREASURY = exports.BASE_USDC_ADDRESS_SANDBOX = exports.BASE_USDC_ADDRESS = exports.PAYNODE_ROUTER_ADDRESS_SANDBOX = exports.PAYNODE_ROUTER_ADDRESS = void 0;
4
+ /** Generated by meta/scripts/sync-config.py */
5
5
  exports.PAYNODE_ROUTER_ADDRESS = "0x4A73696ccF76E7381b044cB95127B3784369Ed63";
6
6
  exports.PAYNODE_ROUTER_ADDRESS_SANDBOX = "0x24cD8b68aaC209217ff5a6ef1Bf55a59f2c8Ca6F";
7
7
  exports.BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
@@ -9,6 +9,7 @@ exports.BASE_USDC_ADDRESS_SANDBOX = "0x65c088EfBDB0E03185Dbe8e258Ad0cf4Ab7946b0"
9
9
  exports.PROTOCOL_TREASURY = "0x598bF63F5449876efafa7b36b77Deb2070621C0E";
10
10
  exports.PROTOCOL_FEE_BPS = 100;
11
11
  exports.MIN_PAYMENT_AMOUNT = BigInt(1000);
12
+ exports.SDK_VERSION = "2.2.2";
12
13
  exports.BASE_RPC_URLS = ["https://mainnet.base.org", "https://base.meowrpc.com", "https://1rpc.io/base"];
13
14
  exports.BASE_RPC_URLS_SANDBOX = ["https://sepolia.base.org", "https://base-sepolia-rpc.publicnode.com"];
14
15
  exports.ACCEPTED_TOKENS = {
@@ -1,4 +1,4 @@
1
- /** Generated by scripts/sync-config.py */
1
+ /** Generated by meta/scripts/sync-config.py */
2
2
  export declare enum ErrorCode {
3
3
  RpcError = "rpc_error",
4
4
  InsufficientFunds = "insufficient_funds",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,oBAAY,SAAS;IACnB,QAAQ,cAAc;IACtB,iBAAiB,uBAAuB;IACxC,YAAY,mBAAmB;IAC/B,gBAAgB,uBAAuB;IACvC,iBAAiB,uBAAuB;IACxC,oBAAoB,0BAA0B;IAC9C,cAAc,oBAAoB;IAClC,aAAa,mBAAmB;IAChC,mBAAmB,0BAA0B;IAC7C,aAAa,mBAAmB;IAChC,aAAa,mBAAmB;IAChC,cAAc,oBAAoB;CACnC;AAED,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAajD,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,KAAK;IACtB,IAAI,EAAE,SAAS;IAA2B,OAAO,CAAC,EAAE,GAAG;gBAAvD,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,EAAS,OAAO,CAAC,EAAE,GAAG,YAAA;CAM3E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,oBAAY,SAAS;IACnB,QAAQ,cAAc;IACtB,iBAAiB,uBAAuB;IACxC,YAAY,mBAAmB;IAC/B,gBAAgB,uBAAuB;IACvC,iBAAiB,uBAAuB;IACxC,oBAAoB,0BAA0B;IAC9C,cAAc,oBAAoB;IAClC,aAAa,mBAAmB;IAChC,mBAAmB,0BAA0B;IAC7C,aAAa,mBAAmB;IAChC,aAAa,mBAAmB;IAChC,cAAc,oBAAoB;CACnC;AAED,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAajD,CAAC;AAEF,qBAAa,gBAAiB,SAAQ,KAAK;IACtB,IAAI,EAAE,SAAS;IAA2B,OAAO,CAAC,EAAE,GAAG;gBAAvD,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,EAAS,OAAO,CAAC,EAAE,GAAG,YAAA;CAM3E"}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PayNodeException = exports.ERROR_MESSAGES = exports.ErrorCode = void 0;
4
- /** Generated by scripts/sync-config.py */
4
+ /** Generated by meta/scripts/sync-config.py */
5
5
  var ErrorCode;
6
6
  (function (ErrorCode) {
7
7
  ErrorCode["RpcError"] = "rpc_error";
package/dist/index.d.ts CHANGED
@@ -5,5 +5,7 @@ export * from './utils/webhook';
5
5
  export * from './client';
6
6
  export * from './errors';
7
7
  export * from './constants';
8
+ export * from './utils/payload';
8
9
  export * from './types/x402';
10
+ export { ethers } from 'ethers';
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC"}
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.ethers = void 0;
17
18
  __exportStar(require("./middleware/x402"), exports);
18
19
  __exportStar(require("./utils/verifier"), exports);
19
20
  __exportStar(require("./utils/idempotency"), exports);
@@ -21,4 +22,7 @@ __exportStar(require("./utils/webhook"), exports);
21
22
  __exportStar(require("./client"), exports);
22
23
  __exportStar(require("./errors"), exports);
23
24
  __exportStar(require("./constants"), exports);
25
+ __exportStar(require("./utils/payload"), exports);
24
26
  __exportStar(require("./types/x402"), exports);
27
+ var ethers_1 = require("ethers");
28
+ Object.defineProperty(exports, "ethers", { enumerable: true, get: function () { return ethers_1.ethers; } });
@@ -30,7 +30,7 @@ const x402Gate = (options) => {
30
30
  fractionPart = fractionPart.slice(0, decimals).padEnd(decimals, '0');
31
31
  rawAmount = BigInt(integerPart + fractionPart);
32
32
  }
33
- const defaultOrderIdGen = (req) => `agent_js_${Date.now()}`;
33
+ const defaultOrderIdGen = (req) => `pn_sdk_${Date.now()}`;
34
34
  return async (req, res, next) => {
35
35
  // ... rest of the logic
36
36
  const getHeader = (name) => {
@@ -63,7 +63,7 @@ const x402Gate = (options) => {
63
63
  inferredType = "onchain";
64
64
  }
65
65
  unifiedPayload = {
66
- version: "2.2.0",
66
+ version: "2.2.2",
67
67
  type: parsed._paynode?.type || inferredType,
68
68
  orderId: internalOrderId,
69
69
  router: parsed.accepted?.router,
@@ -71,7 +71,7 @@ const x402Gate = (options) => {
71
71
  };
72
72
  orderId = internalOrderId;
73
73
  }
74
- else if (parsed.version === "2.2.0") {
74
+ else if (typeof parsed.version === 'string' && (parsed.version.startsWith("2.3") || parsed.version.startsWith("2.2"))) {
75
75
  // Legacy PayNode format
76
76
  unifiedPayload = parsed;
77
77
  if (unifiedPayload?.orderId) {
@@ -67,7 +67,7 @@ export interface VerifyResponse {
67
67
  payer?: string;
68
68
  }
69
69
  export interface UnifiedPaymentPayload {
70
- version: "2.2.0";
70
+ version: "2.2.2";
71
71
  type: "onchain" | "eip3009";
72
72
  orderId: string;
73
73
  router?: string;
@@ -0,0 +1,17 @@
1
+ import { UnifiedPaymentPayload } from '../types/x402';
2
+ export declare class X402PayloadHelper {
3
+ /**
4
+ * Normalizes a raw payment payload (usually from PAYMENT-SIGNATURE or X-402-Payload headers)
5
+ * into the UnifiedPaymentPayload format used internally by PayNode.
6
+ *
7
+ * Supports:
8
+ * - standard X402 V2 format
9
+ * - legacy PayNode internal format (base64 encoded JSON)
10
+ *
11
+ * @param authHeader The base64 encoded payload header
12
+ * @param fallbackOrderId Optional orderId to use if missing from payload
13
+ * @returns UnifiedPaymentPayload
14
+ */
15
+ static normalize(authHeader: string, fallbackOrderId?: string): UnifiedPaymentPayload;
16
+ }
17
+ //# sourceMappingURL=payload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/utils/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,qBAAa,iBAAiB;IAC5B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,qBAAqB;CAuCtF"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.X402PayloadHelper = void 0;
4
+ class X402PayloadHelper {
5
+ /**
6
+ * Normalizes a raw payment payload (usually from PAYMENT-SIGNATURE or X-402-Payload headers)
7
+ * into the UnifiedPaymentPayload format used internally by PayNode.
8
+ *
9
+ * Supports:
10
+ * - standard X402 V2 format
11
+ * - legacy PayNode internal format (base64 encoded JSON)
12
+ *
13
+ * @param authHeader The base64 encoded payload header
14
+ * @param fallbackOrderId Optional orderId to use if missing from payload
15
+ * @returns UnifiedPaymentPayload
16
+ */
17
+ static normalize(authHeader, fallbackOrderId) {
18
+ try {
19
+ const decoded = Buffer.from(authHeader, 'base64').toString('utf-8');
20
+ const parsed = JSON.parse(decoded);
21
+ // 1. Handle Official X402 V2 Standard Format
22
+ if (parsed.x402Version === 2 && parsed.accepted) {
23
+ let inferredType = "onchain";
24
+ // Inference logic: signature/authorization presence implies EIP-3009 (USDC Permit/TransferWithAuth)
25
+ if (parsed.payload?.signature || parsed.payload?.authorization) {
26
+ inferredType = "eip3009";
27
+ }
28
+ else if (parsed.payload?.txHash) {
29
+ inferredType = "onchain";
30
+ }
31
+ return {
32
+ version: "2.2.2",
33
+ type: parsed._paynode?.type || inferredType,
34
+ orderId: parsed._paynode?.orderId || fallbackOrderId || "",
35
+ router: parsed.accepted?.router || parsed.router,
36
+ payload: parsed.payload
37
+ };
38
+ }
39
+ // 2. Handle Legacy or already Unified Format
40
+ if (typeof parsed.version === 'string' && (parsed.version.startsWith("2.2") || parsed.version.startsWith("2.3"))) {
41
+ return {
42
+ ...parsed,
43
+ orderId: parsed.orderId || parsed.order_id || fallbackOrderId || ""
44
+ };
45
+ }
46
+ // 3. Fallback for raw internal format
47
+ return parsed;
48
+ }
49
+ catch (e) {
50
+ throw new Error(`Failed to normalize PayNode payload: ${e instanceof Error ? e.message : String(e)}`);
51
+ }
52
+ }
53
+ }
54
+ exports.X402PayloadHelper = X402PayloadHelper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paynodelabs/sdk-js",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "description": "The official JavaScript/TypeScript SDK for PayNode x402 protocol on Base L2.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  "author": "PayNodeLabs",
26
26
  "license": "MIT",
27
27
  "dependencies": {
28
- "ethers": "^6.13.0",
28
+ "ethers": "^6.16.0",
29
29
  "ioredis": "^5.10.1"
30
30
  },
31
31
  "peerDependencies": {