@armory-sh/client-web3 0.2.23-alpha.23.76 → 0.2.23-alpha.23.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +31 -29
- package/dist/index.js +164 -82
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Web3BaseWalletAccount, Web3BaseWallet } from 'web3-types';
|
|
2
1
|
import { NetworkConfig, CustomToken, PaymentPayloadV2, PaymentRequirementsV2, SettlementResponseV2, NetworkId, TokenId, ArmoryPaymentResult, ValidationError } from '@armory-sh/base';
|
|
2
|
+
import { ClientHook } from '@armory-sh/base/types/hooks';
|
|
3
|
+
import { Web3BaseWalletAccount, Web3BaseWallet } from 'web3-types';
|
|
3
4
|
|
|
4
5
|
type Web3Account = Web3BaseWalletAccount | Web3BaseWallet<Web3BaseWalletAccount>;
|
|
5
6
|
/** Token configuration - can use pre-configured tokens from @armory-sh/tokens */
|
|
@@ -15,6 +16,7 @@ interface Web3ClientConfig {
|
|
|
15
16
|
domainName?: string;
|
|
16
17
|
/** Override EIP-712 domain version for custom tokens */
|
|
17
18
|
domainVersion?: string;
|
|
19
|
+
hooks?: ClientHook<Web3Account>[];
|
|
18
20
|
}
|
|
19
21
|
interface PaymentSignatureResult {
|
|
20
22
|
signature?: {
|
|
@@ -66,34 +68,6 @@ interface Web3EIP712Domain {
|
|
|
66
68
|
[key: string]: string | number;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
declare const createX402Client: (config: Web3ClientConfig) => Web3X402Client;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Create an x402 transport layer for handling payment-required responses
|
|
73
|
-
*/
|
|
74
|
-
declare const createX402Transport: (options: X402TransportOptions) => X402Transport;
|
|
75
|
-
|
|
76
|
-
declare const createEIP712Domain: (chainId: number | string, contractAddress: string, domainName?: string, domainVersion?: string) => Web3EIP712Domain;
|
|
77
|
-
declare const createTransferWithAuthorization: (params: Web3TransferWithAuthorization) => Record<string, string>;
|
|
78
|
-
declare const validateTransferWithAuthorization: (message: Web3TransferWithAuthorization) => boolean;
|
|
79
|
-
declare const parseSignature: (signature: string) => {
|
|
80
|
-
v: number;
|
|
81
|
-
r: string;
|
|
82
|
-
s: string;
|
|
83
|
-
};
|
|
84
|
-
declare const concatenateSignature: (v: number, r: string, s: string) => string;
|
|
85
|
-
declare const adjustVForChainId: (v: number, chainId: number) => number;
|
|
86
|
-
declare const signTypedData: (_account: Web3BaseWalletAccount | Web3BaseWallet<Web3BaseWalletAccount>, _domain: Web3EIP712Domain, _message: Record<string, string>) => Promise<{
|
|
87
|
-
v: number;
|
|
88
|
-
r: string;
|
|
89
|
-
s: string;
|
|
90
|
-
}>;
|
|
91
|
-
declare const signWithPrivateKey: (_privateKey: string, _domain: Web3EIP712Domain, _message: Record<string, string>) => Promise<{
|
|
92
|
-
v: number;
|
|
93
|
-
r: string;
|
|
94
|
-
s: string;
|
|
95
|
-
}>;
|
|
96
|
-
|
|
97
71
|
/**
|
|
98
72
|
* Simple one-line payment API for Armory (Web3)
|
|
99
73
|
* Focus on DX/UX - "everything just magically works"
|
|
@@ -204,4 +178,32 @@ interface ArmoryInstance {
|
|
|
204
178
|
}
|
|
205
179
|
declare const createArmory: (config: ArmoryConfig) => ArmoryInstance;
|
|
206
180
|
|
|
181
|
+
declare const createX402Client: (config: Web3ClientConfig) => Web3X402Client;
|
|
182
|
+
|
|
183
|
+
declare const createEIP712Domain: (chainId: number | string, contractAddress: string, domainName?: string, domainVersion?: string) => Web3EIP712Domain;
|
|
184
|
+
declare const createTransferWithAuthorization: (params: Web3TransferWithAuthorization) => Record<string, string>;
|
|
185
|
+
declare const validateTransferWithAuthorization: (message: Web3TransferWithAuthorization) => boolean;
|
|
186
|
+
declare const parseSignature: (signature: string) => {
|
|
187
|
+
v: number;
|
|
188
|
+
r: string;
|
|
189
|
+
s: string;
|
|
190
|
+
};
|
|
191
|
+
declare const concatenateSignature: (v: number, r: string, s: string) => string;
|
|
192
|
+
declare const adjustVForChainId: (v: number, chainId: number) => number;
|
|
193
|
+
declare const signTypedData: (_account: Web3BaseWalletAccount | Web3BaseWallet<Web3BaseWalletAccount>, _domain: Web3EIP712Domain, _message: Record<string, string>) => Promise<{
|
|
194
|
+
v: number;
|
|
195
|
+
r: string;
|
|
196
|
+
s: string;
|
|
197
|
+
}>;
|
|
198
|
+
declare const signWithPrivateKey: (_privateKey: string, _domain: Web3EIP712Domain, _message: Record<string, string>) => Promise<{
|
|
199
|
+
v: number;
|
|
200
|
+
r: string;
|
|
201
|
+
s: string;
|
|
202
|
+
}>;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Create an x402 transport layer for handling payment-required responses
|
|
206
|
+
*/
|
|
207
|
+
declare const createX402Transport: (options: X402TransportOptions) => X402Transport;
|
|
208
|
+
|
|
207
209
|
export { type ArmoryConfig, type ArmoryInstance, type HttpMethod, type NormalizedWallet, type PaymentOptions, type SimpleWalletInput, adjustVForChainId, armoryDelete, armoryGet, armoryPatch, armoryPay, armoryPost, armoryPut, concatenateSignature, createArmory, createEIP712Domain, createTransferWithAuthorization, createX402Client, createX402Transport, getNetworks, getTokens, getWalletAddress, normalizeWallet, parseSignature, signTypedData, signWithPrivateKey, validateNetwork, validateToken, validateTransferWithAuthorization };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Web3 } from 'web3';
|
|
2
1
|
import { encodePaymentV2, validatePaymentConfig, isValidationError, resolveNetwork, resolveToken, V2_HEADERS, getNetworkConfig, getNetworkByChainId, networkToCaip2, combineSignatureV2, normalizeBase64Url, decodeBase64ToUtf8, isX402V2PaymentRequired } from '@armory-sh/base';
|
|
2
|
+
import { runOnPaymentRequiredHooks, selectRequirementWithHooks, runBeforeSignPaymentHooks, runAfterPaymentResponseHooks } from '@armory-sh/base/client-hooks-runtime';
|
|
3
|
+
import { Web3 } from 'web3';
|
|
3
4
|
|
|
4
5
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
6
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -74,7 +75,9 @@ var validateTransferWithAuthorization = (message) => {
|
|
|
74
75
|
var parseSignature = (signature) => {
|
|
75
76
|
const hexSig = signature.startsWith("0x") ? signature.slice(2) : signature;
|
|
76
77
|
if (hexSig.length !== 130) {
|
|
77
|
-
throw new Error(
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Invalid signature length: ${hexSig.length} (expected 130)`
|
|
80
|
+
);
|
|
78
81
|
}
|
|
79
82
|
return {
|
|
80
83
|
r: `0x${hexSig.slice(0, 64)}`,
|
|
@@ -196,7 +199,8 @@ var getAddress = (account) => {
|
|
|
196
199
|
};
|
|
197
200
|
var parseSignature2 = (signature) => {
|
|
198
201
|
const hexSig = signature.startsWith("0x") ? signature.slice(2) : signature;
|
|
199
|
-
if (hexSig.length !== 130)
|
|
202
|
+
if (hexSig.length !== 130)
|
|
203
|
+
throw new Error(`Invalid signature length: ${hexSig.length}`);
|
|
200
204
|
return {
|
|
201
205
|
r: `0x${hexSig.slice(0, 64)}`,
|
|
202
206
|
s: `0x${hexSig.slice(64, 128)}`,
|
|
@@ -222,7 +226,9 @@ var signTypedDataWrapper = async (account, domain, message) => {
|
|
|
222
226
|
return parseSignature2(sig);
|
|
223
227
|
}
|
|
224
228
|
if ("privateKey" in account && typeof account.privateKey === "string") {
|
|
225
|
-
throw new Error(
|
|
229
|
+
throw new Error(
|
|
230
|
+
"Direct private key signing not implemented. Use wallet provider with signTypedData."
|
|
231
|
+
);
|
|
226
232
|
}
|
|
227
233
|
throw new Error("Account does not support EIP-712 signing.");
|
|
228
234
|
};
|
|
@@ -237,12 +243,17 @@ var signPaymentV2 = async (state, network, params) => {
|
|
|
237
243
|
maxTimeoutSeconds: expiry - Math.floor(Date.now() / 1e3)
|
|
238
244
|
};
|
|
239
245
|
const domainExtra = defaultAccepted.extra;
|
|
240
|
-
const requirementDomainName = defaultAccepted.name ?? (domainExtra && typeof domainExtra === "object" && typeof domainExtra
|
|
241
|
-
const requirementDomainVersion = defaultAccepted.version ?? (domainExtra && typeof domainExtra === "object" && typeof domainExtra
|
|
246
|
+
const requirementDomainName = defaultAccepted.name ?? (domainExtra && typeof domainExtra === "object" && typeof domainExtra.name === "string" ? domainExtra.name : void 0);
|
|
247
|
+
const requirementDomainVersion = defaultAccepted.version ?? (domainExtra && typeof domainExtra === "object" && typeof domainExtra.version === "string" ? domainExtra.version : void 0);
|
|
242
248
|
const effectiveDomainName = state.domainName ?? requirementDomainName;
|
|
243
249
|
const effectiveDomainVersion = state.domainVersion ?? requirementDomainVersion;
|
|
244
250
|
const chainId = parseInt(defaultAccepted.network.split(":")[1], 10);
|
|
245
|
-
const domain = createEIP712Domain(
|
|
251
|
+
const domain = createEIP712Domain(
|
|
252
|
+
chainId,
|
|
253
|
+
defaultAccepted.asset,
|
|
254
|
+
effectiveDomainName,
|
|
255
|
+
effectiveDomainVersion
|
|
256
|
+
);
|
|
246
257
|
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
247
258
|
const validAfterHex = `0x${(nowSeconds - 600).toString(16)}`;
|
|
248
259
|
const message = createTransferWithAuthorization({
|
|
@@ -290,6 +301,7 @@ var extractNetworkFromRequirements = (requirements) => {
|
|
|
290
301
|
};
|
|
291
302
|
var createX402Client = (config) => {
|
|
292
303
|
const state = createClientState(config);
|
|
304
|
+
const hooks = config.hooks;
|
|
293
305
|
const fetch2 = async (url, init) => {
|
|
294
306
|
let response = await fetch2(url, init);
|
|
295
307
|
if (response.status === 402) {
|
|
@@ -299,7 +311,22 @@ var createX402Client = (config) => {
|
|
|
299
311
|
throw new Error("No supported payment scheme found in requirements");
|
|
300
312
|
}
|
|
301
313
|
const from = getAddress(state.account);
|
|
302
|
-
const
|
|
314
|
+
const paymentRequiredContext = {
|
|
315
|
+
url,
|
|
316
|
+
requestInit: init,
|
|
317
|
+
accepts: parsed.requirements,
|
|
318
|
+
requirements: selectedRequirements,
|
|
319
|
+
selectedRequirement: selectedRequirements,
|
|
320
|
+
serverExtensions: void 0,
|
|
321
|
+
fromAddress: from,
|
|
322
|
+
nonce: `0x${Date.now().toString(16).padStart(64, "0")}`,
|
|
323
|
+
validBefore: Math.floor(Date.now() / 1e3) + selectedRequirements.maxTimeoutSeconds
|
|
324
|
+
};
|
|
325
|
+
await runOnPaymentRequiredHooks(hooks, paymentRequiredContext);
|
|
326
|
+
const req = await selectRequirementWithHooks(
|
|
327
|
+
hooks,
|
|
328
|
+
paymentRequiredContext
|
|
329
|
+
);
|
|
303
330
|
const to = typeof req.payTo === "string" ? req.payTo : "0x0000000000000000000000000000000000000000";
|
|
304
331
|
const network = extractNetworkFromRequirements(req);
|
|
305
332
|
const result = await signPaymentV2(state, network, {
|
|
@@ -310,9 +337,25 @@ var createX402Client = (config) => {
|
|
|
310
337
|
expiry: Math.floor(Date.now() / 1e3) + req.maxTimeoutSeconds,
|
|
311
338
|
accepted: req
|
|
312
339
|
});
|
|
340
|
+
await runBeforeSignPaymentHooks(hooks, {
|
|
341
|
+
payload: result.payload,
|
|
342
|
+
requirements: req,
|
|
343
|
+
wallet: state.account,
|
|
344
|
+
paymentContext: paymentRequiredContext
|
|
345
|
+
});
|
|
313
346
|
const paymentHeaders = new Headers(init?.headers);
|
|
314
|
-
paymentHeaders.set(
|
|
347
|
+
paymentHeaders.set(
|
|
348
|
+
V2_HEADERS.PAYMENT_SIGNATURE,
|
|
349
|
+
encodePaymentV2(result.payload)
|
|
350
|
+
);
|
|
315
351
|
response = await fetch2(url, { ...init, headers: paymentHeaders });
|
|
352
|
+
await runAfterPaymentResponseHooks(hooks, {
|
|
353
|
+
payload: result.payload,
|
|
354
|
+
requirements: req,
|
|
355
|
+
wallet: state.account,
|
|
356
|
+
paymentContext: paymentRequiredContext,
|
|
357
|
+
response
|
|
358
|
+
});
|
|
316
359
|
}
|
|
317
360
|
return response;
|
|
318
361
|
};
|
|
@@ -323,7 +366,9 @@ var createX402Client = (config) => {
|
|
|
323
366
|
getVersion: () => state.version,
|
|
324
367
|
signPayment: async (options) => {
|
|
325
368
|
const network = state.network ?? (() => {
|
|
326
|
-
throw new Error(
|
|
369
|
+
throw new Error(
|
|
370
|
+
"Network must be configured for manual payment signing"
|
|
371
|
+
);
|
|
327
372
|
})();
|
|
328
373
|
const from = getAddress(state.account);
|
|
329
374
|
const to = options.to;
|
|
@@ -334,14 +379,22 @@ var createX402Client = (config) => {
|
|
|
334
379
|
},
|
|
335
380
|
createPaymentHeaders: async (options) => {
|
|
336
381
|
const network = state.network ?? (() => {
|
|
337
|
-
throw new Error(
|
|
382
|
+
throw new Error(
|
|
383
|
+
"Network must be configured for manual payment signing"
|
|
384
|
+
);
|
|
338
385
|
})();
|
|
339
386
|
const from = getAddress(state.account);
|
|
340
387
|
const to = options.to;
|
|
341
388
|
const amount = options.amount.toString();
|
|
342
389
|
const nonce = options.nonce ?? crypto.randomUUID();
|
|
343
390
|
const expiry = options.expiry ?? Math.floor(Date.now() / 1e3) + DEFAULT_EXPIRY_SECONDS;
|
|
344
|
-
const result = await signPaymentV2(state, network, {
|
|
391
|
+
const result = await signPaymentV2(state, network, {
|
|
392
|
+
from,
|
|
393
|
+
to,
|
|
394
|
+
amount,
|
|
395
|
+
nonce,
|
|
396
|
+
expiry
|
|
397
|
+
});
|
|
345
398
|
const headers = new Headers();
|
|
346
399
|
headers.set("PAYMENT-SIGNATURE", encodePaymentV2(result.payload));
|
|
347
400
|
return headers;
|
|
@@ -364,69 +417,8 @@ var createX402Client = (config) => {
|
|
|
364
417
|
}
|
|
365
418
|
};
|
|
366
419
|
};
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const headers = new Headers();
|
|
370
|
-
headers.set(V2_HEADERS.PAYMENT_SIGNATURE, encodePaymentV2(payload));
|
|
371
|
-
return headers;
|
|
372
|
-
};
|
|
373
|
-
var isPaymentRelatedError = (error) => error.message.includes("402") || error.message.includes("payment") || error.message.includes("signature") || error.message.includes("Payment");
|
|
374
|
-
var backoff = (attempt) => {
|
|
375
|
-
const baseDelay = Math.min(1e3 * Math.pow(2, attempt - 1), 1e4);
|
|
376
|
-
const jitter = Math.random() * 100;
|
|
377
|
-
return new Promise((resolve) => setTimeout(resolve, baseDelay + jitter));
|
|
378
|
-
};
|
|
379
|
-
var handlePaymentRequired = async (response, client) => {
|
|
380
|
-
detectX402Version(response, client.getVersion());
|
|
381
|
-
const parsed = await parsePaymentRequired(response);
|
|
382
|
-
const selectedRequirements = parsed.requirements[0];
|
|
383
|
-
if (!selectedRequirements) {
|
|
384
|
-
throw new Error("No supported payment scheme found in requirements");
|
|
385
|
-
}
|
|
386
|
-
const req = selectedRequirements;
|
|
387
|
-
const result = await client.handlePaymentRequired(req);
|
|
388
|
-
return createPaymentHeaders(result.payload);
|
|
389
|
-
};
|
|
390
|
-
var mergePaymentHeaders = (init = {}, paymentHeaders) => {
|
|
391
|
-
const existingHeaders = new Headers(init.headers);
|
|
392
|
-
for (const [key, value] of paymentHeaders.entries()) {
|
|
393
|
-
existingHeaders.set(key, value);
|
|
394
|
-
}
|
|
395
|
-
return { ...init, headers: existingHeaders };
|
|
396
|
-
};
|
|
397
|
-
var createX402Transport = (options) => {
|
|
398
|
-
const client = options.client;
|
|
399
|
-
const autoSign = options.autoSign ?? true;
|
|
400
|
-
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
401
|
-
return {
|
|
402
|
-
getClient: () => client,
|
|
403
|
-
fetch: async (url, init) => {
|
|
404
|
-
let attempt = 0;
|
|
405
|
-
let lastError;
|
|
406
|
-
while (attempt < maxRetries) {
|
|
407
|
-
attempt++;
|
|
408
|
-
try {
|
|
409
|
-
const response = await fetch(url, init);
|
|
410
|
-
if (isPaymentRequiredResponse(response) && autoSign) {
|
|
411
|
-
const paymentHeaders = await handlePaymentRequired(response, client);
|
|
412
|
-
const newInit = mergePaymentHeaders(init, paymentHeaders);
|
|
413
|
-
return await fetch(url, newInit);
|
|
414
|
-
}
|
|
415
|
-
return response;
|
|
416
|
-
} catch (error) {
|
|
417
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
418
|
-
if (!isPaymentRelatedError(lastError)) {
|
|
419
|
-
throw lastError;
|
|
420
|
-
}
|
|
421
|
-
if (attempt < maxRetries) {
|
|
422
|
-
await backoff(attempt);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
throw lastError ?? new Error("Max retries exceeded");
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
};
|
|
420
|
+
|
|
421
|
+
// src/payment-api.ts
|
|
430
422
|
var normalizeWallet = (wallet) => {
|
|
431
423
|
if (typeof wallet === "object" && wallet !== null && "account" in wallet) {
|
|
432
424
|
return wallet.account;
|
|
@@ -495,19 +487,37 @@ var armoryPay = async (wallet, url, network, token, options) => {
|
|
|
495
487
|
}
|
|
496
488
|
};
|
|
497
489
|
var armoryGet = (wallet, url, network, token, options) => {
|
|
498
|
-
return armoryPay(wallet, url, network, token, {
|
|
490
|
+
return armoryPay(wallet, url, network, token, {
|
|
491
|
+
...options,
|
|
492
|
+
method: "GET"
|
|
493
|
+
});
|
|
499
494
|
};
|
|
500
495
|
var armoryPost = (wallet, url, network, token, body, options) => {
|
|
501
|
-
return armoryPay(wallet, url, network, token, {
|
|
496
|
+
return armoryPay(wallet, url, network, token, {
|
|
497
|
+
...options,
|
|
498
|
+
method: "POST",
|
|
499
|
+
body
|
|
500
|
+
});
|
|
502
501
|
};
|
|
503
502
|
var armoryPut = (wallet, url, network, token, body, options) => {
|
|
504
|
-
return armoryPay(wallet, url, network, token, {
|
|
503
|
+
return armoryPay(wallet, url, network, token, {
|
|
504
|
+
...options,
|
|
505
|
+
method: "PUT",
|
|
506
|
+
body
|
|
507
|
+
});
|
|
505
508
|
};
|
|
506
509
|
var armoryDelete = (wallet, url, network, token, options) => {
|
|
507
|
-
return armoryPay(wallet, url, network, token, {
|
|
510
|
+
return armoryPay(wallet, url, network, token, {
|
|
511
|
+
...options,
|
|
512
|
+
method: "DELETE"
|
|
513
|
+
});
|
|
508
514
|
};
|
|
509
515
|
var armoryPatch = (wallet, url, network, token, body, options) => {
|
|
510
|
-
return armoryPay(wallet, url, network, token, {
|
|
516
|
+
return armoryPay(wallet, url, network, token, {
|
|
517
|
+
...options,
|
|
518
|
+
method: "PATCH",
|
|
519
|
+
body
|
|
520
|
+
});
|
|
511
521
|
};
|
|
512
522
|
var getWalletAddress = (wallet) => {
|
|
513
523
|
const account = normalizeWallet(wallet);
|
|
@@ -523,7 +533,7 @@ var validateNetwork = (network) => {
|
|
|
523
533
|
return { success: true, network: resolved.config.name };
|
|
524
534
|
};
|
|
525
535
|
var validateToken = (token, network) => {
|
|
526
|
-
let resolvedNetwork
|
|
536
|
+
let resolvedNetwork;
|
|
527
537
|
if (network) {
|
|
528
538
|
const networkResult = resolveNetwork(network);
|
|
529
539
|
if (isValidationError(networkResult)) {
|
|
@@ -551,7 +561,13 @@ var getTokens = () => {
|
|
|
551
561
|
};
|
|
552
562
|
|
|
553
563
|
// src/armory-api.ts
|
|
554
|
-
var ALL_METHODS = /* @__PURE__ */ new Set([
|
|
564
|
+
var ALL_METHODS = /* @__PURE__ */ new Set([
|
|
565
|
+
"GET",
|
|
566
|
+
"POST",
|
|
567
|
+
"PUT",
|
|
568
|
+
"DELETE",
|
|
569
|
+
"PATCH"
|
|
570
|
+
]);
|
|
555
571
|
var arrayify = (value) => {
|
|
556
572
|
if (value === void 0) return void 0;
|
|
557
573
|
return Array.isArray(value) ? value : [value];
|
|
@@ -607,5 +623,71 @@ var createArmory = (config) => {
|
|
|
607
623
|
call: (url) => makeRequest(url, "GET")
|
|
608
624
|
};
|
|
609
625
|
};
|
|
626
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
627
|
+
var createPaymentHeaders = (payload, _version) => {
|
|
628
|
+
const headers = new Headers();
|
|
629
|
+
headers.set(V2_HEADERS.PAYMENT_SIGNATURE, encodePaymentV2(payload));
|
|
630
|
+
return headers;
|
|
631
|
+
};
|
|
632
|
+
var isPaymentRelatedError = (error) => error.message.includes("402") || error.message.includes("payment") || error.message.includes("signature") || error.message.includes("Payment");
|
|
633
|
+
var backoff = (attempt) => {
|
|
634
|
+
const baseDelay = Math.min(1e3 * 2 ** (attempt - 1), 1e4);
|
|
635
|
+
const jitter = Math.random() * 100;
|
|
636
|
+
return new Promise((resolve) => setTimeout(resolve, baseDelay + jitter));
|
|
637
|
+
};
|
|
638
|
+
var handlePaymentRequired = async (response, client) => {
|
|
639
|
+
detectX402Version(response, client.getVersion());
|
|
640
|
+
const parsed = await parsePaymentRequired(response);
|
|
641
|
+
const selectedRequirements = parsed.requirements[0];
|
|
642
|
+
if (!selectedRequirements) {
|
|
643
|
+
throw new Error("No supported payment scheme found in requirements");
|
|
644
|
+
}
|
|
645
|
+
const req = selectedRequirements;
|
|
646
|
+
const result = await client.handlePaymentRequired(req);
|
|
647
|
+
return createPaymentHeaders(result.payload);
|
|
648
|
+
};
|
|
649
|
+
var mergePaymentHeaders = (init = {}, paymentHeaders) => {
|
|
650
|
+
const existingHeaders = new Headers(init.headers);
|
|
651
|
+
for (const [key, value] of paymentHeaders.entries()) {
|
|
652
|
+
existingHeaders.set(key, value);
|
|
653
|
+
}
|
|
654
|
+
return { ...init, headers: existingHeaders };
|
|
655
|
+
};
|
|
656
|
+
var createX402Transport = (options) => {
|
|
657
|
+
const client = options.client;
|
|
658
|
+
const autoSign = options.autoSign ?? true;
|
|
659
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
660
|
+
return {
|
|
661
|
+
getClient: () => client,
|
|
662
|
+
fetch: async (url, init) => {
|
|
663
|
+
let attempt = 0;
|
|
664
|
+
let lastError;
|
|
665
|
+
while (attempt < maxRetries) {
|
|
666
|
+
attempt++;
|
|
667
|
+
try {
|
|
668
|
+
const response = await fetch(url, init);
|
|
669
|
+
if (isPaymentRequiredResponse(response) && autoSign) {
|
|
670
|
+
const paymentHeaders = await handlePaymentRequired(
|
|
671
|
+
response,
|
|
672
|
+
client
|
|
673
|
+
);
|
|
674
|
+
const newInit = mergePaymentHeaders(init, paymentHeaders);
|
|
675
|
+
return await fetch(url, newInit);
|
|
676
|
+
}
|
|
677
|
+
return response;
|
|
678
|
+
} catch (error) {
|
|
679
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
680
|
+
if (!isPaymentRelatedError(lastError)) {
|
|
681
|
+
throw lastError;
|
|
682
|
+
}
|
|
683
|
+
if (attempt < maxRetries) {
|
|
684
|
+
await backoff(attempt);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
throw lastError ?? new Error("Max retries exceeded");
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
};
|
|
610
692
|
|
|
611
693
|
export { adjustVForChainId, armoryDelete, armoryGet, armoryPatch, armoryPay, armoryPost, armoryPut, concatenateSignature, createArmory, createEIP712Domain, createTransferWithAuthorization, createX402Client, createX402Transport, getNetworks, getTokens, getWalletAddress, normalizeWallet, parseSignature, signTypedData, signWithPrivateKey, validateNetwork, validateToken, validateTransferWithAuthorization };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@armory-sh/client-web3",
|
|
3
|
-
"version": "0.2.23-alpha.23.
|
|
3
|
+
"version": "0.2.23-alpha.23.78",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Sawyer Cutler <sawyer@dirtroad.dev>",
|
|
6
6
|
"keywords": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"directory": "packages/client-web3"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@armory-sh/base": "0.2.27-alpha.23.
|
|
49
|
+
"@armory-sh/base": "0.2.27-alpha.23.78",
|
|
50
50
|
"web3": "4.16.0",
|
|
51
51
|
"web3-types": "1.10.0"
|
|
52
52
|
},
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "rm -rf dist && tsup",
|
|
59
|
+
"lint": "bun run build",
|
|
60
|
+
"format": "bun run lint",
|
|
59
61
|
"test": "bun test",
|
|
60
62
|
"example": "bun run examples/"
|
|
61
63
|
}
|