@armory-sh/client-web3 0.2.9 → 0.2.11

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +13 -156
  2. package/dist/index.js +79 -365
  3. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Web3BaseWalletAccount, Web3BaseWallet } from 'web3-types';
2
- import { PaymentPayloadV1, PaymentPayloadV2, CustomToken, NetworkConfig, PaymentRequirementsV1, PaymentRequirementsV2, SettlementResponseV1, SettlementResponseV2, X402PaymentRequiredV1, PaymentRequiredV2, X402PaymentPayloadV1 } from '@armory-sh/base';
3
- export { EIP712_TYPES as CORE_EIP712_TYPES, USDC_DOMAIN as CORE_USDC_DOMAIN, NETWORKS, NetworkConfig, PaymentPayload, PaymentPayloadV1, PaymentPayloadV2, PaymentRequirements, PaymentRequirementsV1, PaymentRequirementsV2, SettlementResponse, SettlementResponseV1, SettlementResponseV2, V1_HEADERS, V2_HEADERS, combineSignatureV2, createEIP712Domain as createCoreEIP712Domain, createTransferWithAuthorization as createCoreTransferWithAuthorization, createNonce, decodePaymentV1, decodePaymentV2, decodeSettlementV1, decodeSettlementV2, encodePaymentV1, encodePaymentV2, encodeSettlementV1, encodeSettlementV2, getMainnets, getNetworkByChainId, getNetworkConfig, getPaymentHeaderName, getPaymentRequiredHeaderName, getPaymentResponseHeaderName, getPaymentVersion, getRequirementsVersion, getSettlementVersion, getTestnets, getTxHash, isSettlementSuccessful, isV1, isV2, isX402V1Payload, isX402V1Requirements, isX402V1Settlement, isX402V2Payload, isX402V2Requirements, isX402V2Settlement, parseSignatureV2, validateTransferWithAuthorization as validateCoreTransferWithAuthorization } from '@armory-sh/base';
2
+ import { NetworkConfig, CustomToken, PaymentPayloadV2, PaymentRequirementsV2, SettlementResponseV2 } from '@armory-sh/base';
3
+ export { EIP3009Authorization, PaymentPayloadV2, PaymentRequirementsV2, SchemePayloadV2, SettlementResponseV2 } from '@armory-sh/base';
4
4
 
5
5
  type Web3Account = Web3BaseWalletAccount | Web3BaseWallet<Web3BaseWalletAccount>;
6
6
  /** Token configuration - can use pre-configured tokens from @armory-sh/tokens */
@@ -8,7 +8,7 @@ type Token = CustomToken;
8
8
  interface Web3ClientConfig {
9
9
  account: Web3Account;
10
10
  network: NetworkConfig | string;
11
- version?: 1 | 2;
11
+ version?: 2;
12
12
  rpcUrl?: string;
13
13
  /** Pre-configured token object (overrides individual fields below) */
14
14
  token?: Token;
@@ -18,15 +18,12 @@ interface Web3ClientConfig {
18
18
  domainVersion?: string;
19
19
  }
20
20
  interface PaymentSignatureResult {
21
- v?: number;
22
- r?: string;
23
- s?: string;
24
21
  signature?: {
25
22
  v: number;
26
23
  r: string;
27
24
  s: string;
28
25
  };
29
- payload: PaymentPayloadV1 | PaymentPayloadV2;
26
+ payload: PaymentPayloadV2;
30
27
  }
31
28
  interface PaymentSignOptions {
32
29
  amount: string | bigint;
@@ -35,30 +32,24 @@ interface PaymentSignOptions {
35
32
  expiry?: number;
36
33
  validAfter?: number;
37
34
  }
38
- interface X402RequestContext {
39
- url: string;
40
- method: string;
41
- headers: Record<string, string> | Headers;
42
- body?: string | Record<string, unknown> | null;
43
- version: 1 | 2;
44
- }
45
35
  interface X402TransportOptions {
46
36
  client: Web3X402Client;
47
37
  autoSign?: boolean;
48
38
  maxRetries?: number;
49
39
  }
40
+ interface X402Transport {
41
+ fetch(url: string | Request, init?: RequestInit): Promise<Response>;
42
+ getClient(): Web3X402Client;
43
+ }
50
44
  interface Web3X402Client {
45
+ fetch(url: string | Request, init?: RequestInit): Promise<Response>;
51
46
  getAccount(): Web3Account;
52
47
  getNetwork(): NetworkConfig;
53
- getVersion(): 1 | 2;
48
+ getVersion(): 2;
54
49
  signPayment(options: PaymentSignOptions): Promise<PaymentSignatureResult>;
55
50
  createPaymentHeaders(options: PaymentSignOptions): Promise<Headers>;
56
- handlePaymentRequired(requirements: PaymentRequirementsV1 | PaymentRequirementsV2): Promise<PaymentSignatureResult>;
57
- verifySettlement(response: SettlementResponseV1 | SettlementResponseV2): boolean;
58
- }
59
- interface X402Transport {
60
- fetch(url: string | Request, init?: RequestInit): Promise<Response>;
61
- getClient(): Web3X402Client;
51
+ handlePaymentRequired(requirements: PaymentRequirementsV2): Promise<PaymentSignatureResult>;
52
+ verifySettlement(response: SettlementResponseV2): boolean;
62
53
  }
63
54
  interface Web3TransferWithAuthorization {
64
55
  from: string;
@@ -75,10 +66,6 @@ interface Web3EIP712Domain {
75
66
  verifyingContract: string;
76
67
  [key: string]: string | number;
77
68
  }
78
- declare const isV1Requirements: (requirements: PaymentRequirementsV1 | PaymentRequirementsV2) => requirements is PaymentRequirementsV1;
79
- declare const isV2Requirements: (requirements: PaymentRequirementsV1 | PaymentRequirementsV2) => requirements is PaymentRequirementsV2;
80
- declare const isV1Settlement: (response: SettlementResponseV1 | SettlementResponseV2) => response is SettlementResponseV1;
81
- declare const isV2Settlement: (response: SettlementResponseV1 | SettlementResponseV2) => response is SettlementResponseV2;
82
69
 
83
70
  declare const createX402Client: (config: Web3ClientConfig) => Web3X402Client;
84
71
 
@@ -86,137 +73,7 @@ declare const createX402Client: (config: Web3ClientConfig) => Web3X402Client;
86
73
  * Create an x402 transport layer for handling payment-required responses
87
74
  */
88
75
  declare const createX402Transport: (options: X402TransportOptions) => X402Transport;
89
- /**
90
- * Create a fetch function bound to an x402 transport
91
- */
92
- declare const createFetchWithX402: (transport: X402Transport) => (url: string | Request, init?: RequestInit) => Promise<Response>;
93
-
94
- /**
95
- * X402 Protocol Detection and Parsing Functions
96
- *
97
- * Handles both x402 V1 and V2 protocol detection and parsing from HTTP responses.
98
- */
99
-
100
- type X402Version = 1 | 2;
101
- interface ParsedPaymentRequired {
102
- version: X402Version;
103
- requirements: PaymentRequirementsV1[] | PaymentRequirementsV2[];
104
- raw: X402PaymentRequiredV1 | PaymentRequiredV2;
105
- }
106
- /**
107
- * Detect x402 protocol version from response headers
108
- * Returns V2 if PAYMENT-REQUIRED header exists, V1 for X-PAYMENT-REQUIRED
109
- * Falls back to body detection if no headers present
110
- */
111
- declare const detectX402Version: (response: Response, fallbackVersion?: X402Version) => X402Version;
112
- /**
113
- * Detect version from a parsed payment required object
114
- */
115
- declare const detectVersionFromObject: (obj: unknown) => X402Version | null;
116
- /**
117
- * Parse PAYMENT-REQUIRED header or response body
118
- * Handles both V1 (base64 encoded) and V2 (JSON) formats
119
- */
120
- declare const parsePaymentRequired: (response: Response, version?: X402Version) => Promise<ParsedPaymentRequired>;
121
- /**
122
- * Parse payment required from header value
123
- */
124
- declare const parsePaymentRequiredFromHeader: (header: string, version: X402Version) => ParsedPaymentRequired;
125
- /**
126
- * Parse payment required from response body
127
- */
128
- declare const parsePaymentRequiredFromBody: (body: string, version: X402Version) => ParsedPaymentRequired;
129
- /**
130
- * Create x402 V1 payment payload
131
- */
132
- declare const createX402V1Payment: (params: {
133
- from: string;
134
- to: string;
135
- value: string;
136
- nonce: `0x${string}`;
137
- validAfter: string;
138
- validBefore: string;
139
- signature: `0x${string}`;
140
- network: string;
141
- }) => X402PaymentPayloadV1;
142
- /**
143
- * Create x402 V2 payment payload
144
- */
145
- declare const createX402V2Payment: (params: {
146
- from: string;
147
- to: string;
148
- value: string;
149
- nonce: `0x${string}`;
150
- validAfter: string;
151
- validBefore: string;
152
- signature: `0x${string}`;
153
- accepted: PaymentRequirementsV2;
154
- resource?: {
155
- url: string;
156
- description?: string;
157
- mimeType?: string;
158
- };
159
- }) => PaymentPayloadV2;
160
- /**
161
- * Create payment header for request
162
- */
163
- declare const createPaymentHeader: (payload: X402PaymentPayloadV1 | PaymentPayloadV2, version: X402Version) => string;
164
- /**
165
- * Get the payment header name for a version
166
- */
167
- declare const getPaymentHeader: (version: X402Version) => string;
168
- /**
169
- * Get the payment required header name for a version
170
- */
171
- declare const getPaymentRequiredHeader: (version: X402Version) => string;
172
- /**
173
- * Check if response indicates payment is required
174
- */
175
- declare const isPaymentRequiredResponse: (response: Response) => boolean;
176
- /**
177
- * Extract requirements for a specific scheme from accepts array
178
- * Uses type assertion to handle union types
179
- */
180
- declare const selectSchemeRequirements: (requirements: PaymentRequirementsV1[] | PaymentRequirementsV2[], scheme?: string) => PaymentRequirementsV1 | PaymentRequirementsV2 | undefined;
181
76
 
182
- declare const EIP712_TYPES: {
183
- readonly EIP712Domain: readonly [{
184
- readonly name: "name";
185
- readonly type: "string";
186
- }, {
187
- readonly name: "version";
188
- readonly type: "string";
189
- }, {
190
- readonly name: "chainId";
191
- readonly type: "uint256";
192
- }, {
193
- readonly name: "verifyingContract";
194
- readonly type: "address";
195
- }];
196
- readonly TransferWithAuthorization: readonly [{
197
- readonly name: "from";
198
- readonly type: "address";
199
- }, {
200
- readonly name: "to";
201
- readonly type: "address";
202
- }, {
203
- readonly name: "value";
204
- readonly type: "uint256";
205
- }, {
206
- readonly name: "validAfter";
207
- readonly type: "uint256";
208
- }, {
209
- readonly name: "validBefore";
210
- readonly type: "uint256";
211
- }, {
212
- readonly name: "nonce";
213
- readonly type: "uint256";
214
- }];
215
- };
216
- declare const USDC_DOMAIN: {
217
- readonly NAME: "USD Coin";
218
- readonly VERSION: "2";
219
- };
220
77
  declare const createEIP712Domain: (chainId: number | string, contractAddress: string, domainName?: string, domainVersion?: string) => Web3EIP712Domain;
221
78
  declare const createTransferWithAuthorization: (params: Web3TransferWithAuthorization) => Record<string, string>;
222
79
  declare const validateTransferWithAuthorization: (message: Web3TransferWithAuthorization) => boolean;
@@ -238,4 +95,4 @@ declare const signWithPrivateKey: (_privateKey: string, _domain: Web3EIP712Domai
238
95
  s: string;
239
96
  }>;
240
97
 
241
- export { EIP712_TYPES, type ParsedPaymentRequired, type PaymentSignOptions, type PaymentSignatureResult, type Token, USDC_DOMAIN, type Web3Account, type Web3ClientConfig, type Web3EIP712Domain, type Web3TransferWithAuthorization, type Web3X402Client, type X402RequestContext, type X402Transport, type X402TransportOptions, type X402Version, adjustVForChainId, concatenateSignature, createEIP712Domain, createFetchWithX402, createPaymentHeader, createTransferWithAuthorization, createX402Client, createX402Transport, createX402V1Payment, createX402V2Payment, detectVersionFromObject, detectX402Version, getPaymentHeader, getPaymentRequiredHeader, isPaymentRequiredResponse, isV1Requirements, isV1Settlement, isV2Requirements, isV2Settlement, parsePaymentRequired, parsePaymentRequiredFromBody, parsePaymentRequiredFromHeader, parseSignature, selectSchemeRequirements, signTypedData, signWithPrivateKey, validateTransferWithAuthorization };
98
+ export { adjustVForChainId, concatenateSignature, createEIP712Domain, createTransferWithAuthorization, createX402Client, createX402Transport, parseSignature, signTypedData, signWithPrivateKey, validateTransferWithAuthorization };
package/dist/index.js CHANGED
@@ -2,30 +2,13 @@
2
2
  import { Web3 } from "web3";
3
3
  import {
4
4
  getNetworkConfig,
5
- encodePaymentV1,
6
5
  encodePaymentV2,
7
- isX402V1Requirements,
8
- isX402V2Requirements,
9
- combineSignatureV2
6
+ networkToCaip2,
7
+ combineSignatureV2,
8
+ V2_HEADERS as V2_HEADERS2
10
9
  } from "@armory-sh/base";
11
10
 
12
11
  // src/eip3009.ts
13
- var EIP712_TYPES = {
14
- EIP712Domain: [
15
- { name: "name", type: "string" },
16
- { name: "version", type: "string" },
17
- { name: "chainId", type: "uint256" },
18
- { name: "verifyingContract", type: "address" }
19
- ],
20
- TransferWithAuthorization: [
21
- { name: "from", type: "address" },
22
- { name: "to", type: "address" },
23
- { name: "value", type: "uint256" },
24
- { name: "validAfter", type: "uint256" },
25
- { name: "validBefore", type: "uint256" },
26
- { name: "nonce", type: "uint256" }
27
- ]
28
- };
29
12
  var USDC_DOMAIN = {
30
13
  NAME: "USD Coin",
31
14
  VERSION: "2"
@@ -123,107 +106,40 @@ var signWithPrivateKey = async (_privateKey, _domain, _message) => {
123
106
 
124
107
  // src/protocol.ts
125
108
  import {
126
- V1_HEADERS,
127
109
  V2_HEADERS,
128
- decodeX402PaymentRequiredV1,
129
- isX402V1PaymentRequired,
130
- isX402V2PaymentRequired,
131
- getPaymentRequiredHeaderName,
132
- getPaymentHeaderName
110
+ isX402V2PaymentRequired
133
111
  } from "@armory-sh/base";
134
- var detectX402Version = (response, fallbackVersion = 2) => {
135
- if (response.headers.has(V2_HEADERS.PAYMENT_REQUIRED)) {
136
- return 2;
137
- }
138
- if (response.headers.has(V1_HEADERS.PAYMENT_REQUIRED)) {
139
- return 1;
140
- }
141
- if (response.headers.has("Payment-Required")) {
142
- return 2;
143
- }
144
- return fallbackVersion;
145
- };
146
- var detectVersionFromObject = (obj) => {
147
- if (isX402V2PaymentRequired(obj)) return 2;
148
- if (isX402V1PaymentRequired(obj)) return 1;
149
- return null;
150
- };
151
- var parsePaymentRequired = async (response, version) => {
152
- const detectedVersion = version ?? detectX402Version(response);
153
- const headerName = getPaymentRequiredHeaderName(detectedVersion);
154
- const header = response.headers.get(headerName);
155
- if (header) {
156
- return parsePaymentRequiredFromHeader(header, detectedVersion);
157
- }
158
- const body = await response.clone().text();
159
- return parsePaymentRequiredFromBody(body, detectedVersion);
112
+ var detectX402Version = (_response, _fallbackVersion = 2) => {
113
+ return 2;
160
114
  };
161
- var parsePaymentRequiredFromHeader = (header, version) => {
162
- if (version === 1) {
163
- const decoded = decodeX402PaymentRequiredV1(header);
164
- return {
165
- version: 1,
166
- requirements: decoded.accepts,
167
- raw: decoded
168
- };
115
+ var parsePaymentRequired = async (response, _version) => {
116
+ const v2Header = response.headers.get(V2_HEADERS.PAYMENT_REQUIRED);
117
+ if (!v2Header) {
118
+ throw new Error("No PAYMENT-REQUIRED header found in V2 response");
169
119
  }
170
- let parsed;
171
120
  try {
172
- parsed = JSON.parse(header);
173
- } catch {
174
- const decoded = Buffer.from(header, "base64").toString("utf-8");
175
- parsed = JSON.parse(decoded);
176
- }
177
- return {
178
- version: 2,
179
- requirements: parsed.accepts,
180
- raw: parsed
181
- };
182
- };
183
- var parsePaymentRequiredFromBody = (body, version) => {
184
- let parsed;
185
- try {
186
- parsed = JSON.parse(body);
187
- } catch {
188
- const decoded = Buffer.from(body, "base64").toString("utf-8");
189
- parsed = JSON.parse(decoded);
190
- }
191
- const detectedVersion = detectVersionFromObject(parsed) ?? version;
192
- if (detectedVersion === 1 && isX402V1PaymentRequired(parsed)) {
121
+ let parsed;
122
+ try {
123
+ parsed = JSON.parse(v2Header);
124
+ } catch {
125
+ const decoded = Buffer.from(v2Header, "base64").toString("utf-8");
126
+ parsed = JSON.parse(decoded);
127
+ }
128
+ if (!isX402V2PaymentRequired(parsed)) {
129
+ throw new Error("Invalid x402 V2 payment required format");
130
+ }
131
+ if (!parsed.accepts || parsed.accepts.length === 0) {
132
+ throw new Error("No payment requirements found in accepts array");
133
+ }
193
134
  return {
194
- version: 1,
135
+ version: 2,
195
136
  requirements: parsed.accepts,
196
137
  raw: parsed
197
138
  };
139
+ } catch (error) {
140
+ if (error instanceof Error) throw error;
141
+ throw new Error(`Failed to parse V2 PAYMENT-REQUIRED header: ${error}`);
198
142
  }
199
- if (detectedVersion === 2 && isX402V2PaymentRequired(parsed)) {
200
- const v2Parsed = parsed;
201
- return {
202
- version: 2,
203
- requirements: v2Parsed.accepts,
204
- raw: v2Parsed
205
- };
206
- }
207
- throw new Error("Unable to parse payment required response");
208
- };
209
- var createX402V1Payment = (params) => {
210
- const authorization = {
211
- from: params.from,
212
- to: params.to,
213
- value: params.value,
214
- validAfter: params.validAfter,
215
- validBefore: params.validBefore,
216
- nonce: params.nonce
217
- };
218
- return {
219
- x402Version: 1,
220
- scheme: "exact",
221
- network: params.network,
222
- payload: {
223
- signature: params.signature,
224
- authorization
225
- }
226
- };
227
143
  };
228
144
  var createX402V2Payment = (params) => {
229
145
  const authorization = {
@@ -236,38 +152,22 @@ var createX402V2Payment = (params) => {
236
152
  };
237
153
  return {
238
154
  x402Version: 2,
239
- resource: params.resource,
240
- accepted: params.accepted,
155
+ scheme: params.accepted.scheme,
156
+ network: params.accepted.network,
241
157
  payload: {
242
158
  signature: params.signature,
243
159
  authorization
244
- }
160
+ },
161
+ resource: params.resource
245
162
  };
246
163
  };
247
- var createPaymentHeader = (payload, version) => {
248
- const headerName = getPaymentHeaderName(version);
249
- const encoded = Buffer.from(JSON.stringify(payload)).toString("base64");
250
- return encoded;
251
- };
252
- var getPaymentHeader = (version) => {
253
- return getPaymentHeaderName(version);
254
- };
255
- var getPaymentRequiredHeader = (version) => {
256
- return getPaymentRequiredHeaderName(version);
257
- };
258
164
  var isPaymentRequiredResponse = (response) => {
259
165
  if (response.status === 402) return true;
260
- return response.headers.has(V1_HEADERS.PAYMENT_REQUIRED) || response.headers.has(V2_HEADERS.PAYMENT_REQUIRED) || response.headers.has("Payment-Required");
261
- };
262
- var selectSchemeRequirements = (requirements, scheme = "exact") => {
263
- return requirements.find(
264
- (r) => "scheme" in r && r.scheme === scheme
265
- );
166
+ return response.headers.has(V2_HEADERS.PAYMENT_REQUIRED);
266
167
  };
267
168
 
268
169
  // src/client.ts
269
170
  var DEFAULT_EXPIRY_SECONDS = 3600;
270
- var DEFAULT_VALID_AFTER = 0;
271
171
  var extractDomainConfig = (config) => {
272
172
  if (config.token) {
273
173
  return {
@@ -331,34 +231,6 @@ var signTypedDataWrapper = async (account, domain, message) => {
331
231
  }
332
232
  throw new Error("Account does not support EIP-712 signing.");
333
233
  };
334
- var signPaymentV1 = async (state, params) => {
335
- const { from, to, amount, nonce, expiry, validAfter } = params;
336
- const { network, domainName, domainVersion } = state;
337
- const domain = createEIP712Domain(network.chainId, network.usdcAddress, domainName, domainVersion);
338
- const message = createTransferWithAuthorization({
339
- from,
340
- to,
341
- value: amount,
342
- validAfter: `0x${validAfter.toString(16)}`,
343
- validBefore: `0x${expiry.toString(16)}`,
344
- nonce: `0x${nonce}`
345
- });
346
- const signature = await signTypedDataWrapper(state.account, domain, message);
347
- const legacyPayload = {
348
- from,
349
- to,
350
- amount,
351
- nonce,
352
- expiry,
353
- v: signature.v,
354
- r: signature.r,
355
- s: signature.s,
356
- chainId: network.chainId,
357
- contractAddress: network.usdcAddress,
358
- network: network.name.toLowerCase().replace(" ", "-")
359
- };
360
- return { v: signature.v, r: signature.r, s: signature.s, payload: legacyPayload };
361
- };
362
234
  var signPaymentV2 = async (state, params) => {
363
235
  const { from, to, amount, nonce, expiry, accepted } = params;
364
236
  const { network, domainName, domainVersion } = state;
@@ -375,7 +247,7 @@ var signPaymentV2 = async (state, params) => {
375
247
  const combinedSig = combineSignatureV2(signature.v, signature.r, signature.s);
376
248
  const defaultAccepted = accepted ?? {
377
249
  scheme: "exact",
378
- network: network.caip2Id,
250
+ network: networkToCaip2(network.name),
379
251
  amount,
380
252
  asset: network.usdcAddress,
381
253
  payTo: to,
@@ -389,6 +261,7 @@ var signPaymentV2 = async (state, params) => {
389
261
  validAfter: "0x0",
390
262
  validBefore: `0x${expiry.toString(16)}`,
391
263
  signature: combinedSig,
264
+ network: defaultAccepted.network,
392
265
  accepted: defaultAccepted
393
266
  });
394
267
  return {
@@ -402,7 +275,34 @@ var signPaymentV2 = async (state, params) => {
402
275
  };
403
276
  var createX402Client = (config) => {
404
277
  const state = createClientState(config);
278
+ const fetch2 = async (url, init) => {
279
+ let response = await fetch2(url, init);
280
+ if (response.status === 402) {
281
+ const version = detectX402Version(response, state.version);
282
+ const parsed = await parsePaymentRequired(response, version);
283
+ const selectedRequirements = parsed.requirements[0];
284
+ if (!selectedRequirements) {
285
+ throw new Error("No supported payment scheme found in requirements");
286
+ }
287
+ const from = getAddress(state.account);
288
+ const req = selectedRequirements;
289
+ const to = typeof req.payTo === "string" ? req.payTo : "0x0000000000000000000000000000000000000000";
290
+ const result = await signPaymentV2(state, {
291
+ from,
292
+ to,
293
+ amount: req.amount,
294
+ nonce: crypto.randomUUID(),
295
+ expiry: Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_SECONDS,
296
+ accepted: req
297
+ });
298
+ const paymentHeaders = new Headers(init?.headers);
299
+ paymentHeaders.set(V2_HEADERS2.PAYMENT_SIGNATURE, encodePaymentV2(result.payload));
300
+ response = await fetch2(url, { ...init, headers: paymentHeaders });
301
+ }
302
+ return response;
303
+ };
405
304
  return {
305
+ fetch: fetch2,
406
306
  getAccount: () => state.account,
407
307
  getNetwork: () => state.network,
408
308
  getVersion: () => state.version,
@@ -412,116 +312,46 @@ var createX402Client = (config) => {
412
312
  const amount = options.amount.toString();
413
313
  const nonce = options.nonce ?? crypto.randomUUID();
414
314
  const expiry = options.expiry ?? Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_SECONDS;
415
- if (state.version === 1) {
416
- return signPaymentV1(state, {
417
- from,
418
- to,
419
- amount,
420
- nonce,
421
- expiry,
422
- validAfter: options.validAfter ?? DEFAULT_VALID_AFTER
423
- });
424
- }
425
315
  return signPaymentV2(state, { from, to, amount, nonce, expiry });
426
316
  },
427
317
  createPaymentHeaders: async (options) => {
428
- const result = await signPayment(options, state);
318
+ const from = getAddress(state.account);
319
+ const to = options.to;
320
+ const amount = options.amount.toString();
321
+ const nonce = options.nonce ?? crypto.randomUUID();
322
+ const expiry = options.expiry ?? Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_SECONDS;
323
+ const result = await signPaymentV2(state, { from, to, amount, nonce, expiry });
429
324
  const headers = new Headers();
430
- if (state.version === 1) {
431
- headers.set("X-PAYMENT", encodePaymentV1(result.payload));
432
- } else {
433
- headers.set("PAYMENT-SIGNATURE", encodePaymentV2(result.payload));
434
- }
325
+ headers.set("PAYMENT-SIGNATURE", encodePaymentV2(result.payload));
435
326
  return headers;
436
327
  },
437
328
  handlePaymentRequired: async (requirements) => {
438
- const version = detectVersionFromRequirements(requirements);
439
- if (version === 1) {
440
- const req2 = requirements;
441
- if (isX402V1Requirements(req2)) {
442
- const x402Req = req2;
443
- return signPayment({
444
- amount: x402Req.maxAmountRequired,
445
- to: x402Req.payTo
446
- }, state);
447
- }
448
- const legacyReq = req2;
449
- return signPayment({
450
- amount: legacyReq.amount,
451
- to: legacyReq.payTo,
452
- expiry: legacyReq.expiry
453
- }, state);
454
- }
455
- const req = requirements;
456
- const to = typeof req.payTo === "string" ? req.payTo : "0x0000000000000000000000000000000000000000";
457
329
  const from = getAddress(state.account);
330
+ const to = typeof requirements.payTo === "string" ? requirements.payTo : "0x0000000000000000000000000000000000000000";
458
331
  return signPaymentV2(state, {
459
332
  from,
460
333
  to,
461
- amount: req.amount,
334
+ amount: requirements.amount,
462
335
  nonce: crypto.randomUUID(),
463
336
  expiry: Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_SECONDS,
464
- accepted: req
337
+ accepted: requirements
465
338
  });
466
339
  },
467
340
  verifySettlement: (response) => {
468
- if ("success" in response) {
469
- return response.success;
470
- }
471
- return false;
341
+ return response.success === true;
472
342
  }
473
343
  };
474
344
  };
475
- var detectVersionFromRequirements = (requirements) => {
476
- if (isX402V2Requirements(requirements)) {
477
- return 2;
478
- }
479
- if (isX402V1Requirements(requirements)) {
480
- return 1;
481
- }
482
- if ("contractAddress" in requirements) {
483
- return 1;
484
- }
485
- return 2;
486
- };
487
- var signPayment = async (options, state) => {
488
- const from = getAddress(state.account);
489
- if (state.version === 1) {
490
- return signPaymentV1(state, {
491
- from,
492
- to: options.to,
493
- amount: options.amount.toString(),
494
- nonce: options.nonce ?? crypto.randomUUID(),
495
- expiry: options.expiry ?? Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_SECONDS,
496
- validAfter: options.validAfter ?? DEFAULT_VALID_AFTER
497
- });
498
- }
499
- return signPaymentV2(state, {
500
- from,
501
- to: options.to,
502
- amount: options.amount.toString(),
503
- nonce: options.nonce ?? crypto.randomUUID(),
504
- expiry: options.expiry ?? Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_SECONDS
505
- });
506
- };
507
345
 
508
346
  // src/transport.ts
509
347
  import {
510
- V1_HEADERS as V1_HEADERS2,
511
- V2_HEADERS as V2_HEADERS2,
512
- encodePaymentV1 as encodePaymentV12,
513
- encodePaymentV2 as encodePaymentV22,
514
- isX402V1Requirements as isX402V1Requirements2,
515
- isX402V2Requirements as isX402V2Requirements2
348
+ V2_HEADERS as V2_HEADERS3,
349
+ encodePaymentV2 as encodePaymentV22
516
350
  } from "@armory-sh/base";
517
351
  var DEFAULT_MAX_RETRIES = 3;
518
- var createPaymentHeaders = (payload, version) => {
352
+ var createPaymentHeaders = (payload, _version) => {
519
353
  const headers = new Headers();
520
- if (version === 1) {
521
- headers.set(V1_HEADERS2.PAYMENT, encodePaymentV12(payload));
522
- } else {
523
- headers.set(V2_HEADERS2.PAYMENT_SIGNATURE, encodePaymentV22(payload));
524
- }
354
+ headers.set(V2_HEADERS3.PAYMENT_SIGNATURE, encodePaymentV22(payload));
525
355
  return headers;
526
356
  };
527
357
  var isPaymentRelatedError = (error) => error.message.includes("402") || error.message.includes("payment") || error.message.includes("signature") || error.message.includes("Payment");
@@ -533,20 +363,12 @@ var backoff = (attempt) => {
533
363
  var handlePaymentRequired = async (response, client) => {
534
364
  const version = detectX402Version(response, client.getVersion());
535
365
  const parsed = await parsePaymentRequired(response, version);
536
- const selectedRequirements = selectSchemeRequirements(parsed.requirements, "exact");
366
+ const selectedRequirements = parsed.requirements[0];
537
367
  if (!selectedRequirements) {
538
368
  throw new Error("No supported payment scheme found in requirements");
539
369
  }
540
- let result;
541
- if (version === 1 && isX402V1Requirements2(selectedRequirements)) {
542
- const req = selectedRequirements;
543
- result = await client.handlePaymentRequired(req);
544
- } else if (version === 2 && isX402V2Requirements2(selectedRequirements)) {
545
- const req = selectedRequirements;
546
- result = await client.handlePaymentRequired(req);
547
- } else {
548
- result = await client.handlePaymentRequired(selectedRequirements);
549
- }
370
+ const req = selectedRequirements;
371
+ const result = await client.handlePaymentRequired(req);
550
372
  return createPaymentHeaders(result.payload, version);
551
373
  };
552
374
  var mergePaymentHeaders = (init = {}, paymentHeaders) => {
@@ -589,123 +411,15 @@ var createX402Transport = (options) => {
589
411
  }
590
412
  };
591
413
  };
592
- var createFetchWithX402 = (transport) => (url, init) => transport.fetch(url, init);
593
-
594
- // src/types.ts
595
- var isV1Requirements = (requirements) => "contractAddress" in requirements;
596
- var isV2Requirements = (requirements) => "chainId" in requirements && "assetId" in requirements;
597
- var isV1Settlement = (response) => "success" in response;
598
- var isV2Settlement = (response) => "status" in response;
599
-
600
- // src/index.ts
601
- import {
602
- V1_HEADERS as V1_HEADERS3,
603
- V2_HEADERS as V2_HEADERS3,
604
- encodePaymentV1 as encodePaymentV13,
605
- decodePaymentV1,
606
- encodeSettlementV1,
607
- decodeSettlementV1,
608
- encodePaymentV2 as encodePaymentV23,
609
- decodePaymentV2,
610
- encodeSettlementV2,
611
- decodeSettlementV2,
612
- isV1,
613
- isV2,
614
- getPaymentVersion,
615
- getRequirementsVersion,
616
- getSettlementVersion,
617
- getPaymentHeaderName as getPaymentHeaderName2,
618
- getPaymentResponseHeaderName,
619
- getPaymentRequiredHeaderName as getPaymentRequiredHeaderName2,
620
- isSettlementSuccessful,
621
- getTxHash,
622
- NETWORKS,
623
- getNetworkConfig as getNetworkConfig2,
624
- getNetworkByChainId,
625
- getMainnets,
626
- getTestnets,
627
- isX402V1Payload,
628
- isX402V2Payload,
629
- isX402V1Requirements as isX402V1Requirements3,
630
- isX402V2Requirements as isX402V2Requirements3,
631
- isX402V1Settlement,
632
- isX402V2Settlement,
633
- combineSignatureV2 as combineSignatureV22,
634
- parseSignatureV2,
635
- createNonce as createNonce2,
636
- EIP712_TYPES as EIP712_TYPES2,
637
- USDC_DOMAIN as USDC_DOMAIN2,
638
- createEIP712Domain as createEIP712Domain2,
639
- createTransferWithAuthorization as createTransferWithAuthorization2,
640
- validateTransferWithAuthorization as validateTransferWithAuthorization2
641
- } from "@armory-sh/base";
642
414
  export {
643
- EIP712_TYPES2 as CORE_EIP712_TYPES,
644
- USDC_DOMAIN2 as CORE_USDC_DOMAIN,
645
- EIP712_TYPES,
646
- NETWORKS,
647
- USDC_DOMAIN,
648
- V1_HEADERS3 as V1_HEADERS,
649
- V2_HEADERS3 as V2_HEADERS,
650
415
  adjustVForChainId,
651
- combineSignatureV22 as combineSignatureV2,
652
416
  concatenateSignature,
653
- createEIP712Domain2 as createCoreEIP712Domain,
654
- createTransferWithAuthorization2 as createCoreTransferWithAuthorization,
655
417
  createEIP712Domain,
656
- createFetchWithX402,
657
- createNonce2 as createNonce,
658
- createPaymentHeader,
659
418
  createTransferWithAuthorization,
660
419
  createX402Client,
661
420
  createX402Transport,
662
- createX402V1Payment,
663
- createX402V2Payment,
664
- decodePaymentV1,
665
- decodePaymentV2,
666
- decodeSettlementV1,
667
- decodeSettlementV2,
668
- detectVersionFromObject,
669
- detectX402Version,
670
- encodePaymentV13 as encodePaymentV1,
671
- encodePaymentV23 as encodePaymentV2,
672
- encodeSettlementV1,
673
- encodeSettlementV2,
674
- getMainnets,
675
- getNetworkByChainId,
676
- getNetworkConfig2 as getNetworkConfig,
677
- getPaymentHeader,
678
- getPaymentHeaderName2 as getPaymentHeaderName,
679
- getPaymentRequiredHeader,
680
- getPaymentRequiredHeaderName2 as getPaymentRequiredHeaderName,
681
- getPaymentResponseHeaderName,
682
- getPaymentVersion,
683
- getRequirementsVersion,
684
- getSettlementVersion,
685
- getTestnets,
686
- getTxHash,
687
- isPaymentRequiredResponse,
688
- isSettlementSuccessful,
689
- isV1,
690
- isV1Requirements,
691
- isV1Settlement,
692
- isV2,
693
- isV2Requirements,
694
- isV2Settlement,
695
- isX402V1Payload,
696
- isX402V1Requirements3 as isX402V1Requirements,
697
- isX402V1Settlement,
698
- isX402V2Payload,
699
- isX402V2Requirements3 as isX402V2Requirements,
700
- isX402V2Settlement,
701
- parsePaymentRequired,
702
- parsePaymentRequiredFromBody,
703
- parsePaymentRequiredFromHeader,
704
421
  parseSignature,
705
- parseSignatureV2,
706
- selectSchemeRequirements,
707
422
  signTypedData,
708
423
  signWithPrivateKey,
709
- validateTransferWithAuthorization2 as validateCoreTransferWithAuthorization,
710
424
  validateTransferWithAuthorization
711
425
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armory-sh/client-web3",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "license": "MIT",
5
5
  "author": "Sawyer Cutler <sawyer@dirtroad.dev>",
6
6
  "type": "module",
@@ -27,7 +27,7 @@
27
27
  "directory": "packages/client-web3"
28
28
  },
29
29
  "dependencies": {
30
- "@armory-sh/base": "^0.2.12",
30
+ "@armory-sh/base": "^0.2.14",
31
31
  "web3": "4.16.0",
32
32
  "web3-types": "1.10.0"
33
33
  },
@@ -36,7 +36,7 @@
36
36
  "bun-types": "latest"
37
37
  },
38
38
  "scripts": {
39
- "build": "tsup",
39
+ "build": "rm -rf dist && tsup",
40
40
  "test": "bun test",
41
41
  "example": "bun run examples/"
42
42
  }