@armory-sh/client-ethers 0.2.26-alpha.23.74 → 0.2.26-alpha.23.77
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 +150 -160
- package/dist/index.js +129 -116
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,48 +1,120 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { NetworkId, TokenId, ArmoryPaymentResult, ValidationError, X402ClientError, CustomToken, PaymentRequirementsV2, Address, PaymentPayloadV2 } from '@armory-sh/base';
|
|
2
|
+
export { PaymentException as PaymentError, SigningError, X402ClientError } from '@armory-sh/base';
|
|
3
3
|
import { Signer, Provider } from 'ethers';
|
|
4
4
|
export { Provider, Signer } from 'ethers';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* Handles parsing x402 V2 PAYMENT-REQUIRED headers
|
|
10
|
-
* and generating x402 V2 PAYMENT-SIGNATURE payloads
|
|
7
|
+
* Simple one-line payment API for Armory (Ethers)
|
|
8
|
+
* Focus on DX/UX - "everything just magically works"
|
|
11
9
|
*/
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
|
-
*
|
|
15
|
-
* V2-only: Always returns 2
|
|
12
|
+
* Simple wallet input - accepts wallet directly or wrapped for backward compatibility
|
|
16
13
|
*/
|
|
17
|
-
|
|
14
|
+
type SimpleWalletInput = Signer | {
|
|
15
|
+
signer: Signer;
|
|
16
|
+
};
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
18
|
+
* Normalized wallet (internal use)
|
|
20
19
|
*/
|
|
21
|
-
|
|
22
|
-
interface ParsedPaymentRequirements {
|
|
23
|
-
version: 2;
|
|
24
|
-
requirements: PaymentRequirementsV2;
|
|
25
|
-
}
|
|
20
|
+
type NormalizedWallet = Signer;
|
|
26
21
|
/**
|
|
27
|
-
*
|
|
28
|
-
* V2 only
|
|
22
|
+
* Normalize wallet input to internal format
|
|
29
23
|
*/
|
|
30
|
-
declare
|
|
24
|
+
declare const normalizeWallet: (wallet: SimpleWalletInput) => NormalizedWallet;
|
|
31
25
|
/**
|
|
32
|
-
*
|
|
26
|
+
* Make a payment-protected API request with one line of code
|
|
33
27
|
*/
|
|
34
|
-
declare
|
|
28
|
+
declare const armoryPay: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: {
|
|
29
|
+
/** Request method (default: GET) */
|
|
30
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
31
|
+
/** Request body (for POST/PUT/PATCH) */
|
|
32
|
+
body?: unknown;
|
|
33
|
+
/** Request headers */
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
/** Protocol version (V2 only) */
|
|
36
|
+
version?: 2;
|
|
37
|
+
/** Payment amount in token units (default: from 402 header) */
|
|
38
|
+
amount?: string;
|
|
39
|
+
/** Enable debug logging */
|
|
40
|
+
debug?: boolean;
|
|
41
|
+
}) => Promise<ArmoryPaymentResult<T>>;
|
|
42
|
+
/**
|
|
43
|
+
* Make a GET request with payment
|
|
44
|
+
*/
|
|
45
|
+
declare const armoryGet: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
46
|
+
/**
|
|
47
|
+
* Make a POST request with payment
|
|
48
|
+
*/
|
|
49
|
+
declare const armoryPost: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, body?: unknown, options?: Omit<Parameters<typeof armoryPay>[4], "method" | "body">) => Promise<ArmoryPaymentResult<T>>;
|
|
50
|
+
/**
|
|
51
|
+
* Make a PUT request with payment
|
|
52
|
+
*/
|
|
53
|
+
declare const armoryPut: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, body?: unknown, options?: Omit<Parameters<typeof armoryPay>[4], "method" | "body">) => Promise<ArmoryPaymentResult<T>>;
|
|
54
|
+
/**
|
|
55
|
+
* Make a DELETE request with payment
|
|
56
|
+
*/
|
|
57
|
+
declare const armoryDelete: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
58
|
+
/**
|
|
59
|
+
* Make a PATCH request with payment
|
|
60
|
+
*/
|
|
61
|
+
declare const armoryPatch: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, body?: unknown, options?: Omit<Parameters<typeof armoryPay>[4], "method" | "body">) => Promise<ArmoryPaymentResult<T>>;
|
|
62
|
+
/**
|
|
63
|
+
* Get the wallet address from a SimpleWalletInput
|
|
64
|
+
*/
|
|
65
|
+
declare const getWalletAddress: (wallet: SimpleWalletInput) => Promise<string>;
|
|
66
|
+
/**
|
|
67
|
+
* Validate a network identifier without making a request
|
|
68
|
+
*/
|
|
69
|
+
declare const validateNetwork: (network: NetworkId) => ValidationError | {
|
|
70
|
+
success: true;
|
|
71
|
+
network: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Validate a token identifier without making a request
|
|
75
|
+
*/
|
|
76
|
+
declare const validateToken: (token: TokenId, network?: NetworkId) => ValidationError | {
|
|
77
|
+
success: true;
|
|
78
|
+
token: string;
|
|
79
|
+
network: string;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Get list of available networks
|
|
83
|
+
*/
|
|
84
|
+
declare const getNetworks: () => string[];
|
|
85
|
+
/**
|
|
86
|
+
* Get list of available tokens
|
|
87
|
+
*/
|
|
88
|
+
declare const getTokens: () => string[];
|
|
35
89
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Armory API - Simplified payment interface (Ethers)
|
|
92
|
+
* Provides a configurable object with method-based payment functions
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
96
|
+
interface ArmoryConfig {
|
|
97
|
+
wallet: SimpleWalletInput;
|
|
98
|
+
methods?: HttpMethod[] | HttpMethod;
|
|
99
|
+
tokens?: TokenId[] | TokenId;
|
|
100
|
+
chains?: NetworkId[] | NetworkId;
|
|
101
|
+
debug?: boolean;
|
|
39
102
|
}
|
|
40
|
-
|
|
41
|
-
|
|
103
|
+
interface PaymentOptions {
|
|
104
|
+
method?: HttpMethod;
|
|
105
|
+
body?: unknown;
|
|
42
106
|
}
|
|
43
|
-
|
|
44
|
-
|
|
107
|
+
interface ArmoryInstance {
|
|
108
|
+
get<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
109
|
+
post<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
110
|
+
put<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
111
|
+
delete<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
112
|
+
patch<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
113
|
+
pay<T>(url: string, options?: PaymentOptions): Promise<ArmoryPaymentResult<T>>;
|
|
114
|
+
call<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
45
115
|
}
|
|
116
|
+
declare const createArmory: (config: ArmoryConfig) => ArmoryInstance;
|
|
117
|
+
|
|
46
118
|
declare class SignerRequiredError extends X402ClientError {
|
|
47
119
|
constructor(message?: string);
|
|
48
120
|
}
|
|
@@ -108,40 +180,6 @@ interface EIP712Domain {
|
|
|
108
180
|
verifyingContract: `0x${string}`;
|
|
109
181
|
}
|
|
110
182
|
|
|
111
|
-
interface X402Transport {
|
|
112
|
-
fetch(url: string, init?: X402RequestInit): Promise<Response>;
|
|
113
|
-
get(url: string, init?: X402RequestInit): Promise<Response>;
|
|
114
|
-
post(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
115
|
-
put(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
116
|
-
del(url: string, init?: X402RequestInit): Promise<Response>;
|
|
117
|
-
patch(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
118
|
-
setSigner(signer: Signer): void;
|
|
119
|
-
getSigner(): Signer | undefined;
|
|
120
|
-
}
|
|
121
|
-
declare const createX402Transport: (config?: X402TransportConfig) => X402Transport;
|
|
122
|
-
|
|
123
|
-
declare function signEIP3009(signer: Signer, params: TransferWithAuthorizationParams, domain: EIP712Domain): Promise<{
|
|
124
|
-
v: number;
|
|
125
|
-
r: string;
|
|
126
|
-
s: string;
|
|
127
|
-
}>;
|
|
128
|
-
declare function signEIP3009WithDomain(signer: Signer, params: TransferWithAuthorizationParams, chainId: number, verifyingContract: `0x${string}`, domainName?: string, domainVersion?: string): Promise<{
|
|
129
|
-
v: number;
|
|
130
|
-
r: string;
|
|
131
|
-
s: string;
|
|
132
|
-
}>;
|
|
133
|
-
declare function signPayment(signer: Signer, from: `0x${string}`, to: `0x${string}`, value: bigint, chainId: number, verifyingContract: `0x${string}`, expirySeconds?: number, domainName?: string, domainVersion?: string): Promise<{
|
|
134
|
-
v: number;
|
|
135
|
-
r: string;
|
|
136
|
-
s: string;
|
|
137
|
-
nonce: `0x${string}`;
|
|
138
|
-
}>;
|
|
139
|
-
declare function recoverEIP3009Signer(params: TransferWithAuthorizationParams, signature: {
|
|
140
|
-
v: number;
|
|
141
|
-
r: string;
|
|
142
|
-
s: string;
|
|
143
|
-
}, domain: EIP712Domain): Promise<`0x${string}`>;
|
|
144
|
-
|
|
145
183
|
/**
|
|
146
184
|
* X402 Client Factory for Ethers
|
|
147
185
|
*
|
|
@@ -194,116 +232,68 @@ declare function createX402Client(config: X402ClientConfig & SignerClientConfig
|
|
|
194
232
|
}): X402Client;
|
|
195
233
|
declare function createX402Client(config: X402ClientConfig & ProviderClientConfig): X402Client;
|
|
196
234
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
235
|
+
declare function signEIP3009(signer: Signer, params: TransferWithAuthorizationParams, domain: EIP712Domain): Promise<{
|
|
236
|
+
v: number;
|
|
237
|
+
r: string;
|
|
238
|
+
s: string;
|
|
239
|
+
}>;
|
|
240
|
+
declare function signEIP3009WithDomain(signer: Signer, params: TransferWithAuthorizationParams, chainId: number, verifyingContract: `0x${string}`, domainName?: string, domainVersion?: string): Promise<{
|
|
241
|
+
v: number;
|
|
242
|
+
r: string;
|
|
243
|
+
s: string;
|
|
244
|
+
}>;
|
|
245
|
+
declare function signPayment(signer: Signer, from: `0x${string}`, to: `0x${string}`, value: bigint, chainId: number, verifyingContract: `0x${string}`, expirySeconds?: number, domainName?: string, domainVersion?: string): Promise<{
|
|
246
|
+
v: number;
|
|
247
|
+
r: string;
|
|
248
|
+
s: string;
|
|
249
|
+
nonce: `0x${string}`;
|
|
250
|
+
}>;
|
|
251
|
+
declare function recoverEIP3009Signer(params: TransferWithAuthorizationParams, signature: {
|
|
252
|
+
v: number;
|
|
253
|
+
r: string;
|
|
254
|
+
s: string;
|
|
255
|
+
}, domain: EIP712Domain): Promise<`0x${string}`>;
|
|
201
256
|
|
|
202
257
|
/**
|
|
203
|
-
*
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
};
|
|
208
|
-
/**
|
|
209
|
-
* Normalized wallet (internal use)
|
|
210
|
-
*/
|
|
211
|
-
type NormalizedWallet = Signer;
|
|
212
|
-
/**
|
|
213
|
-
* Normalize wallet input to internal format
|
|
214
|
-
*/
|
|
215
|
-
declare const normalizeWallet: (wallet: SimpleWalletInput) => NormalizedWallet;
|
|
216
|
-
/**
|
|
217
|
-
* Make a payment-protected API request with one line of code
|
|
218
|
-
*/
|
|
219
|
-
declare const armoryPay: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: {
|
|
220
|
-
/** Request method (default: GET) */
|
|
221
|
-
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
222
|
-
/** Request body (for POST/PUT/PATCH) */
|
|
223
|
-
body?: unknown;
|
|
224
|
-
/** Request headers */
|
|
225
|
-
headers?: Record<string, string>;
|
|
226
|
-
/** Protocol version (V2 only) */
|
|
227
|
-
version?: 2;
|
|
228
|
-
/** Payment amount in token units (default: from 402 header) */
|
|
229
|
-
amount?: string;
|
|
230
|
-
/** Enable debug logging */
|
|
231
|
-
debug?: boolean;
|
|
232
|
-
}) => Promise<ArmoryPaymentResult<T>>;
|
|
233
|
-
/**
|
|
234
|
-
* Make a GET request with payment
|
|
235
|
-
*/
|
|
236
|
-
declare const armoryGet: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
237
|
-
/**
|
|
238
|
-
* Make a POST request with payment
|
|
239
|
-
*/
|
|
240
|
-
declare const armoryPost: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, body?: unknown, options?: Omit<Parameters<typeof armoryPay>[4], "method" | "body">) => Promise<ArmoryPaymentResult<T>>;
|
|
241
|
-
/**
|
|
242
|
-
* Make a PUT request with payment
|
|
243
|
-
*/
|
|
244
|
-
declare const armoryPut: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, body?: unknown, options?: Omit<Parameters<typeof armoryPay>[4], "method" | "body">) => Promise<ArmoryPaymentResult<T>>;
|
|
245
|
-
/**
|
|
246
|
-
* Make a DELETE request with payment
|
|
247
|
-
*/
|
|
248
|
-
declare const armoryDelete: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
249
|
-
/**
|
|
250
|
-
* Make a PATCH request with payment
|
|
251
|
-
*/
|
|
252
|
-
declare const armoryPatch: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, body?: unknown, options?: Omit<Parameters<typeof armoryPay>[4], "method" | "body">) => Promise<ArmoryPaymentResult<T>>;
|
|
253
|
-
/**
|
|
254
|
-
* Get the wallet address from a SimpleWalletInput
|
|
255
|
-
*/
|
|
256
|
-
declare const getWalletAddress: (wallet: SimpleWalletInput) => Promise<string>;
|
|
257
|
-
/**
|
|
258
|
-
* Validate a network identifier without making a request
|
|
258
|
+
* X402 Protocol Implementation for Ethers Client (V2 Only)
|
|
259
|
+
*
|
|
260
|
+
* Handles parsing x402 V2 PAYMENT-REQUIRED headers
|
|
261
|
+
* and generating x402 V2 PAYMENT-SIGNATURE payloads
|
|
259
262
|
*/
|
|
260
|
-
|
|
261
|
-
success: true;
|
|
262
|
-
network: string;
|
|
263
|
-
};
|
|
263
|
+
|
|
264
264
|
/**
|
|
265
|
-
*
|
|
265
|
+
* Detect x402 protocol version from response headers
|
|
266
|
+
* V2-only: Always returns 2
|
|
266
267
|
*/
|
|
267
|
-
declare
|
|
268
|
-
success: true;
|
|
269
|
-
token: string;
|
|
270
|
-
network: string;
|
|
271
|
-
};
|
|
268
|
+
declare function detectX402Version(_response: Response): 2;
|
|
272
269
|
/**
|
|
273
|
-
* Get
|
|
270
|
+
* Get payment header name for protocol version
|
|
274
271
|
*/
|
|
275
|
-
declare
|
|
272
|
+
declare function getPaymentHeaderName(_version: 2): string;
|
|
273
|
+
interface ParsedPaymentRequirements {
|
|
274
|
+
version: 2;
|
|
275
|
+
requirements: PaymentRequirementsV2;
|
|
276
|
+
}
|
|
276
277
|
/**
|
|
277
|
-
*
|
|
278
|
+
* Parse x402 PAYMENT-REQUIRED header from response
|
|
279
|
+
* V2 only
|
|
278
280
|
*/
|
|
279
|
-
declare
|
|
280
|
-
|
|
281
|
+
declare function parsePaymentRequired(response: Response): ParsedPaymentRequirements;
|
|
281
282
|
/**
|
|
282
|
-
*
|
|
283
|
-
* Provides a configurable object with method-based payment functions
|
|
283
|
+
* Create x402 payment payload (V2-only wrapper)
|
|
284
284
|
*/
|
|
285
|
+
declare function createX402Payment(signer: Signer, parsed: ParsedPaymentRequirements, fromAddress: Address, nonce?: `0x${string}`, validBefore?: number, domainName?: string, domainVersion?: string): Promise<PaymentPayloadV2>;
|
|
285
286
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
method?: HttpMethod;
|
|
296
|
-
body?: unknown;
|
|
297
|
-
}
|
|
298
|
-
interface ArmoryInstance {
|
|
299
|
-
get<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
300
|
-
post<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
301
|
-
put<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
302
|
-
delete<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
303
|
-
patch<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
304
|
-
pay<T>(url: string, options?: PaymentOptions): Promise<ArmoryPaymentResult<T>>;
|
|
305
|
-
call<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
287
|
+
interface X402Transport {
|
|
288
|
+
fetch(url: string, init?: X402RequestInit): Promise<Response>;
|
|
289
|
+
get(url: string, init?: X402RequestInit): Promise<Response>;
|
|
290
|
+
post(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
291
|
+
put(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
292
|
+
del(url: string, init?: X402RequestInit): Promise<Response>;
|
|
293
|
+
patch(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
294
|
+
setSigner(signer: Signer): void;
|
|
295
|
+
getSigner(): Signer | undefined;
|
|
306
296
|
}
|
|
307
|
-
declare const
|
|
297
|
+
declare const createX402Transport: (config?: X402TransportConfig) => X402Transport;
|
|
308
298
|
|
|
309
|
-
export { type ArmoryConfig, type ArmoryInstance, AuthorizationError, type ClientConfig, type HttpMethod, type NormalizedWallet, type ParsedPaymentRequirements,
|
|
299
|
+
export { type ArmoryConfig, type ArmoryInstance, AuthorizationError, type ClientConfig, type HttpMethod, type NormalizedWallet, type ParsedPaymentRequirements, type PaymentOptions, ProviderRequiredError, SignerRequiredError, type SimpleWalletInput, type X402Client, type X402ClientConfig, type X402RequestInit, type X402Transport, type X402TransportConfig, armoryDelete, armoryGet, armoryPatch, armoryPay, armoryPost, armoryPut, createArmory, createX402Client, createX402Payment, createX402Transport, detectX402Version, getNetworks, getPaymentHeaderName, getTokens, getWalletAddress, normalizeWallet, parsePaymentRequired, recoverEIP3009Signer, signEIP3009, signEIP3009WithDomain, signPayment, validateNetwork, validateToken };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createEIP712Domain, V2_HEADERS, isX402V2PaymentRequired, validatePaymentConfig, isValidationError, resolveNetwork, resolveToken, getNetworkConfig, normalizeNetworkName, encodePaymentV2, decodeSettlementV2 } from '@armory-sh/base';
|
|
2
|
-
export {
|
|
1
|
+
import { X402ClientError, createEIP712Domain, V2_HEADERS, PaymentException, isX402V2PaymentRequired, validatePaymentConfig, isValidationError, resolveNetwork, resolveToken, normalizeBase64Url, decodeBase64ToUtf8, getNetworkConfig, normalizeNetworkName, encodePaymentV2, decodeSettlementV2 } from '@armory-sh/base';
|
|
2
|
+
export { PaymentException as PaymentError, SigningError, X402ClientError } from '@armory-sh/base';
|
|
3
3
|
import { ethers } from 'ethers';
|
|
4
4
|
|
|
5
5
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
@@ -8,28 +8,6 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
8
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
9
9
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
10
10
|
});
|
|
11
|
-
|
|
12
|
-
// src/errors.ts
|
|
13
|
-
var X402ClientError = class extends Error {
|
|
14
|
-
cause;
|
|
15
|
-
constructor(message, cause) {
|
|
16
|
-
super(message);
|
|
17
|
-
this.name = "X402ClientError";
|
|
18
|
-
this.cause = cause;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
var SigningError = class extends X402ClientError {
|
|
22
|
-
constructor(message, cause) {
|
|
23
|
-
super(`Signing failed: ${message}`, cause);
|
|
24
|
-
this.name = "SigningError";
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
var PaymentError = class extends X402ClientError {
|
|
28
|
-
constructor(message, cause) {
|
|
29
|
-
super(`Payment failed: ${message}`, cause);
|
|
30
|
-
this.name = "PaymentError";
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
11
|
var SignerRequiredError = class extends X402ClientError {
|
|
34
12
|
constructor(message = "Signer is required for this operation") {
|
|
35
13
|
super(message);
|
|
@@ -48,8 +26,6 @@ var ProviderRequiredError = class extends X402ClientError {
|
|
|
48
26
|
this.name = "ProviderRequiredError";
|
|
49
27
|
}
|
|
50
28
|
};
|
|
51
|
-
|
|
52
|
-
// src/eip3009.ts
|
|
53
29
|
var EIP712_TYPES_ETHERS = {
|
|
54
30
|
TransferWithAuthorization: [
|
|
55
31
|
{ name: "from", type: "address" },
|
|
@@ -70,7 +46,11 @@ async function signEIP3009(signer, params, domain) {
|
|
|
70
46
|
validBefore: BigInt(params.validBefore),
|
|
71
47
|
nonce: params.nonce
|
|
72
48
|
};
|
|
73
|
-
const signature = await signer.signTypedData(
|
|
49
|
+
const signature = await signer.signTypedData(
|
|
50
|
+
domain,
|
|
51
|
+
EIP712_TYPES_ETHERS,
|
|
52
|
+
message
|
|
53
|
+
);
|
|
74
54
|
const { v, r, s } = ethers.Signature.from(signature);
|
|
75
55
|
return { v: Number(v), r, s };
|
|
76
56
|
} catch (error) {
|
|
@@ -82,7 +62,11 @@ async function signEIP3009(signer, params, domain) {
|
|
|
82
62
|
}
|
|
83
63
|
async function signEIP3009WithDomain(signer, params, chainId, verifyingContract, domainName, domainVersion) {
|
|
84
64
|
const domain = createEIP712Domain(chainId, verifyingContract);
|
|
85
|
-
const customDomain = domainName || domainVersion ? {
|
|
65
|
+
const customDomain = domainName || domainVersion ? {
|
|
66
|
+
...domain,
|
|
67
|
+
name: domainName ?? domain.name,
|
|
68
|
+
version: domainVersion ?? domain.version
|
|
69
|
+
} : domain;
|
|
86
70
|
return signEIP3009(signer, params, customDomain);
|
|
87
71
|
}
|
|
88
72
|
async function signPayment(signer, from, to, value, chainId, verifyingContract, expirySeconds = 3600, domainName, domainVersion) {
|
|
@@ -90,7 +74,14 @@ async function signPayment(signer, from, to, value, chainId, verifyingContract,
|
|
|
90
74
|
const nonce = `0x${(now * 1e3).toString(16).padStart(64, "0")}`;
|
|
91
75
|
const signature = await signEIP3009WithDomain(
|
|
92
76
|
signer,
|
|
93
|
-
{
|
|
77
|
+
{
|
|
78
|
+
from,
|
|
79
|
+
to,
|
|
80
|
+
value,
|
|
81
|
+
validAfter: 0n,
|
|
82
|
+
validBefore: BigInt(now + expirySeconds),
|
|
83
|
+
nonce
|
|
84
|
+
},
|
|
94
85
|
chainId,
|
|
95
86
|
verifyingContract,
|
|
96
87
|
domainName,
|
|
@@ -112,42 +103,15 @@ async function recoverEIP3009Signer(params, signature, domain) {
|
|
|
112
103
|
r: signature.r,
|
|
113
104
|
s: signature.s
|
|
114
105
|
});
|
|
115
|
-
const address = ethers.verifyTypedData(
|
|
106
|
+
const address = ethers.verifyTypedData(
|
|
107
|
+
domain,
|
|
108
|
+
EIP712_TYPES_ETHERS,
|
|
109
|
+
message,
|
|
110
|
+
sig
|
|
111
|
+
);
|
|
116
112
|
return address;
|
|
117
113
|
}
|
|
118
114
|
|
|
119
|
-
// src/bytes.ts
|
|
120
|
-
new TextEncoder();
|
|
121
|
-
var textDecoder = new TextDecoder();
|
|
122
|
-
function getNodeBuffer() {
|
|
123
|
-
if ("Buffer" in globalThis) {
|
|
124
|
-
return globalThis.Buffer;
|
|
125
|
-
}
|
|
126
|
-
return void 0;
|
|
127
|
-
}
|
|
128
|
-
function fromBase64(base64) {
|
|
129
|
-
if (typeof atob === "function") {
|
|
130
|
-
const binary = atob(base64);
|
|
131
|
-
const bytes = new Uint8Array(binary.length);
|
|
132
|
-
for (let index = 0; index < binary.length; index += 1) {
|
|
133
|
-
bytes[index] = binary.charCodeAt(index);
|
|
134
|
-
}
|
|
135
|
-
return bytes;
|
|
136
|
-
}
|
|
137
|
-
const nodeBuffer = getNodeBuffer();
|
|
138
|
-
if (nodeBuffer) {
|
|
139
|
-
return Uint8Array.from(nodeBuffer.from(base64, "base64"));
|
|
140
|
-
}
|
|
141
|
-
throw new Error("No base64 decoder available in this runtime");
|
|
142
|
-
}
|
|
143
|
-
function decodeBase64ToUtf8(value) {
|
|
144
|
-
const bytes = fromBase64(value);
|
|
145
|
-
return textDecoder.decode(bytes);
|
|
146
|
-
}
|
|
147
|
-
function normalizeBase64Url(value) {
|
|
148
|
-
return value.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(value.length / 4) * 4, "=");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
115
|
// src/protocol.ts
|
|
152
116
|
function detectX402Version(_response) {
|
|
153
117
|
return 2;
|
|
@@ -166,23 +130,25 @@ function parseJsonOrBase64(value) {
|
|
|
166
130
|
function parsePaymentRequired(response) {
|
|
167
131
|
const v2Header = response.headers.get(V2_HEADERS.PAYMENT_REQUIRED);
|
|
168
132
|
if (!v2Header) {
|
|
169
|
-
throw new
|
|
133
|
+
throw new PaymentException("No PAYMENT-REQUIRED header found in V2 response");
|
|
170
134
|
}
|
|
171
135
|
try {
|
|
172
136
|
const parsed = parseJsonOrBase64(v2Header);
|
|
173
137
|
if (!isX402V2PaymentRequired(parsed)) {
|
|
174
|
-
throw new
|
|
138
|
+
throw new PaymentException("Invalid x402 V2 payment required format");
|
|
175
139
|
}
|
|
176
140
|
if (!parsed.accepts || parsed.accepts.length === 0) {
|
|
177
|
-
throw new
|
|
141
|
+
throw new PaymentException("No payment requirements found in accepts array");
|
|
178
142
|
}
|
|
179
143
|
return {
|
|
180
144
|
version: 2,
|
|
181
145
|
requirements: parsed.accepts[0]
|
|
182
146
|
};
|
|
183
147
|
} catch (error) {
|
|
184
|
-
if (error instanceof
|
|
185
|
-
throw new
|
|
148
|
+
if (error instanceof PaymentException) throw error;
|
|
149
|
+
throw new PaymentException(
|
|
150
|
+
`Failed to parse V2 PAYMENT-REQUIRED header: ${error}`
|
|
151
|
+
);
|
|
186
152
|
}
|
|
187
153
|
}
|
|
188
154
|
function extractChainId(network) {
|
|
@@ -193,7 +159,7 @@ function extractChainId(network) {
|
|
|
193
159
|
if (net) {
|
|
194
160
|
return net.chainId;
|
|
195
161
|
}
|
|
196
|
-
throw new
|
|
162
|
+
throw new PaymentException(`Unsupported network: ${network}`);
|
|
197
163
|
}
|
|
198
164
|
function createNonce() {
|
|
199
165
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -204,7 +170,11 @@ async function createX402V2Payment(signer, requirements, fromAddress, nonce, val
|
|
|
204
170
|
const chainId = extractChainId(requirements.network);
|
|
205
171
|
const now = Math.floor(Date.now() / 1e3);
|
|
206
172
|
const domain = createEIP712Domain(chainId, contractAddress);
|
|
207
|
-
const customDomain = domainName || domainVersion ? {
|
|
173
|
+
const customDomain = domainName || domainVersion ? {
|
|
174
|
+
...domain,
|
|
175
|
+
name: domainName ?? domain.name,
|
|
176
|
+
version: domainVersion ?? domain.version
|
|
177
|
+
} : domain;
|
|
208
178
|
const authorization = {
|
|
209
179
|
from: fromAddress,
|
|
210
180
|
to: requirements.payTo,
|
|
@@ -246,6 +216,8 @@ async function createX402Payment(signer, parsed, fromAddress, nonce, validBefore
|
|
|
246
216
|
domainVersion
|
|
247
217
|
);
|
|
248
218
|
}
|
|
219
|
+
|
|
220
|
+
// src/transport.ts
|
|
249
221
|
var defaultConfig = {
|
|
250
222
|
baseURL: "",
|
|
251
223
|
headers: {},
|
|
@@ -281,8 +253,8 @@ var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
281
253
|
var getRequirementDomainOverrides = (parsed) => {
|
|
282
254
|
const requirement = parsed.requirements;
|
|
283
255
|
const extra = requirement.extra;
|
|
284
|
-
const extraName = extra && typeof extra === "object" && typeof extra
|
|
285
|
-
const extraVersion = extra && typeof extra === "object" && typeof extra
|
|
256
|
+
const extraName = extra && typeof extra === "object" && typeof extra.name === "string" ? extra.name : void 0;
|
|
257
|
+
const extraVersion = extra && typeof extra === "object" && typeof extra.version === "string" ? extra.version : void 0;
|
|
286
258
|
return {
|
|
287
259
|
domainName: requirement.name ?? extraName,
|
|
288
260
|
domainVersion: requirement.version ?? extraVersion
|
|
@@ -290,7 +262,9 @@ var getRequirementDomainOverrides = (parsed) => {
|
|
|
290
262
|
};
|
|
291
263
|
var handlePaymentRequired = async (state, response) => {
|
|
292
264
|
if (!state.signer) {
|
|
293
|
-
throw new SignerRequiredError(
|
|
265
|
+
throw new SignerRequiredError(
|
|
266
|
+
"Cannot handle payment: no signer configured."
|
|
267
|
+
);
|
|
294
268
|
}
|
|
295
269
|
try {
|
|
296
270
|
const parsed = parsePaymentRequired(response);
|
|
@@ -315,10 +289,15 @@ var handlePaymentRequired = async (state, response) => {
|
|
|
315
289
|
},
|
|
316
290
|
state.config.timeout
|
|
317
291
|
);
|
|
318
|
-
const settlement = decodeSettlementV2(
|
|
292
|
+
const settlement = decodeSettlementV2(
|
|
293
|
+
paymentResponse.headers.get(V2_HEADERS.PAYMENT_RESPONSE) || ""
|
|
294
|
+
);
|
|
319
295
|
return { success: true, settlement };
|
|
320
296
|
} catch (error) {
|
|
321
|
-
return {
|
|
297
|
+
return {
|
|
298
|
+
success: false,
|
|
299
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
300
|
+
};
|
|
322
301
|
}
|
|
323
302
|
};
|
|
324
303
|
var shouldRetryPayment = async (state, response) => {
|
|
@@ -331,14 +310,20 @@ var x402Fetch = async (state, url, init = {}) => {
|
|
|
331
310
|
const headers = new Headers({ ...state.config.headers, ...init.headers });
|
|
332
311
|
for (let attempt = 1; attempt <= state.config.maxRetries; attempt++) {
|
|
333
312
|
try {
|
|
334
|
-
const response = await fetchWithTimeout(
|
|
313
|
+
const response = await fetchWithTimeout(
|
|
314
|
+
fullUrl,
|
|
315
|
+
{ ...init, headers },
|
|
316
|
+
state.config.timeout
|
|
317
|
+
);
|
|
335
318
|
if (response.status === 402 && !init.skipAutoPay && await shouldRetryPayment(state, response)) {
|
|
336
319
|
const paymentResult = await handlePaymentRequired(state, response);
|
|
337
320
|
if (paymentResult.success) {
|
|
338
321
|
state.config.onPaymentSuccess(paymentResult.settlement);
|
|
339
322
|
continue;
|
|
340
323
|
}
|
|
341
|
-
state.config.onPaymentError(
|
|
324
|
+
state.config.onPaymentError(
|
|
325
|
+
paymentResult.error ?? new Error("Payment failed")
|
|
326
|
+
);
|
|
342
327
|
}
|
|
343
328
|
return response;
|
|
344
329
|
} catch (error) {
|
|
@@ -361,7 +346,7 @@ var createMethod = (state, method) => async (url, bodyOrInit, init) => {
|
|
|
361
346
|
});
|
|
362
347
|
};
|
|
363
348
|
var createX402Transport = (config) => {
|
|
364
|
-
|
|
349
|
+
const state = createState(config);
|
|
365
350
|
return {
|
|
366
351
|
fetch: (url, init) => x402Fetch(state, url, init),
|
|
367
352
|
get: createMethod(state, "GET"),
|
|
@@ -376,37 +361,7 @@ var createX402Transport = (config) => {
|
|
|
376
361
|
};
|
|
377
362
|
};
|
|
378
363
|
|
|
379
|
-
// src/
|
|
380
|
-
function createX402Client(config) {
|
|
381
|
-
const transport = createX402Transport(void 0);
|
|
382
|
-
if ("signer" in config && config.signer) {
|
|
383
|
-
transport.setSigner(config.signer);
|
|
384
|
-
} else if ("provider" in config && config.provider) {
|
|
385
|
-
const provider = config.provider;
|
|
386
|
-
if (provider.getSigner) {
|
|
387
|
-
try {
|
|
388
|
-
const signer = provider.getSigner();
|
|
389
|
-
if (signer) {
|
|
390
|
-
transport.setSigner(signer);
|
|
391
|
-
}
|
|
392
|
-
} catch {
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
} else {
|
|
396
|
-
throw new SignerRequiredError(
|
|
397
|
-
"Either 'signer' or 'provider' with getSigner() must be provided"
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
return {
|
|
401
|
-
get: (url, init) => transport.get(url, init),
|
|
402
|
-
post: (url, body, init) => transport.post(url, body, init),
|
|
403
|
-
put: (url, body, init) => transport.put(url, body, init),
|
|
404
|
-
del: (url, init) => transport.del(url, init),
|
|
405
|
-
patch: (url, body, init) => transport.patch(url, body, init),
|
|
406
|
-
setSigner: (signer) => transport.setSigner(signer),
|
|
407
|
-
getSigner: () => transport.getSigner()
|
|
408
|
-
};
|
|
409
|
-
}
|
|
364
|
+
// src/payment-api.ts
|
|
410
365
|
var normalizeWallet = (wallet) => {
|
|
411
366
|
if (typeof wallet === "object" && wallet !== null && "signer" in wallet) {
|
|
412
367
|
return wallet.signer;
|
|
@@ -468,19 +423,37 @@ var armoryPay = async (wallet, url, network, token, options) => {
|
|
|
468
423
|
}
|
|
469
424
|
};
|
|
470
425
|
var armoryGet = (wallet, url, network, token, options) => {
|
|
471
|
-
return armoryPay(wallet, url, network, token, {
|
|
426
|
+
return armoryPay(wallet, url, network, token, {
|
|
427
|
+
...options,
|
|
428
|
+
method: "GET"
|
|
429
|
+
});
|
|
472
430
|
};
|
|
473
431
|
var armoryPost = (wallet, url, network, token, body, options) => {
|
|
474
|
-
return armoryPay(wallet, url, network, token, {
|
|
432
|
+
return armoryPay(wallet, url, network, token, {
|
|
433
|
+
...options,
|
|
434
|
+
method: "POST",
|
|
435
|
+
body
|
|
436
|
+
});
|
|
475
437
|
};
|
|
476
438
|
var armoryPut = (wallet, url, network, token, body, options) => {
|
|
477
|
-
return armoryPay(wallet, url, network, token, {
|
|
439
|
+
return armoryPay(wallet, url, network, token, {
|
|
440
|
+
...options,
|
|
441
|
+
method: "PUT",
|
|
442
|
+
body
|
|
443
|
+
});
|
|
478
444
|
};
|
|
479
445
|
var armoryDelete = (wallet, url, network, token, options) => {
|
|
480
|
-
return armoryPay(wallet, url, network, token, {
|
|
446
|
+
return armoryPay(wallet, url, network, token, {
|
|
447
|
+
...options,
|
|
448
|
+
method: "DELETE"
|
|
449
|
+
});
|
|
481
450
|
};
|
|
482
451
|
var armoryPatch = (wallet, url, network, token, body, options) => {
|
|
483
|
-
return armoryPay(wallet, url, network, token, {
|
|
452
|
+
return armoryPay(wallet, url, network, token, {
|
|
453
|
+
...options,
|
|
454
|
+
method: "PATCH",
|
|
455
|
+
body
|
|
456
|
+
});
|
|
484
457
|
};
|
|
485
458
|
var getWalletAddress = async (wallet) => {
|
|
486
459
|
const signer = normalizeWallet(wallet);
|
|
@@ -494,7 +467,7 @@ var validateNetwork = (network) => {
|
|
|
494
467
|
return { success: true, network: resolved.config.name };
|
|
495
468
|
};
|
|
496
469
|
var validateToken = (token, network) => {
|
|
497
|
-
let resolvedNetwork
|
|
470
|
+
let resolvedNetwork;
|
|
498
471
|
if (network) {
|
|
499
472
|
const networkResult = resolveNetwork(network);
|
|
500
473
|
if (isValidationError(networkResult)) {
|
|
@@ -520,7 +493,15 @@ var getTokens = () => {
|
|
|
520
493
|
const { getAvailableTokens } = __require("@armory-sh/base");
|
|
521
494
|
return getAvailableTokens();
|
|
522
495
|
};
|
|
523
|
-
|
|
496
|
+
|
|
497
|
+
// src/armory-api.ts
|
|
498
|
+
var ALL_METHODS = /* @__PURE__ */ new Set([
|
|
499
|
+
"GET",
|
|
500
|
+
"POST",
|
|
501
|
+
"PUT",
|
|
502
|
+
"DELETE",
|
|
503
|
+
"PATCH"
|
|
504
|
+
]);
|
|
524
505
|
var arrayify = (value) => {
|
|
525
506
|
if (value === void 0) return void 0;
|
|
526
507
|
return Array.isArray(value) ? value : [value];
|
|
@@ -588,4 +569,36 @@ var createArmory = (config) => {
|
|
|
588
569
|
};
|
|
589
570
|
};
|
|
590
571
|
|
|
591
|
-
|
|
572
|
+
// src/client.ts
|
|
573
|
+
function createX402Client(config) {
|
|
574
|
+
const transport = createX402Transport(void 0);
|
|
575
|
+
if ("signer" in config && config.signer) {
|
|
576
|
+
transport.setSigner(config.signer);
|
|
577
|
+
} else if ("provider" in config && config.provider) {
|
|
578
|
+
const provider = config.provider;
|
|
579
|
+
if (provider.getSigner) {
|
|
580
|
+
try {
|
|
581
|
+
const signer = provider.getSigner();
|
|
582
|
+
if (signer) {
|
|
583
|
+
transport.setSigner(signer);
|
|
584
|
+
}
|
|
585
|
+
} catch {
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
} else {
|
|
589
|
+
throw new SignerRequiredError(
|
|
590
|
+
"Either 'signer' or 'provider' with getSigner() must be provided"
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
get: (url, init) => transport.get(url, init),
|
|
595
|
+
post: (url, body, init) => transport.post(url, body, init),
|
|
596
|
+
put: (url, body, init) => transport.put(url, body, init),
|
|
597
|
+
del: (url, init) => transport.del(url, init),
|
|
598
|
+
patch: (url, body, init) => transport.patch(url, body, init),
|
|
599
|
+
setSigner: (signer) => transport.setSigner(signer),
|
|
600
|
+
getSigner: () => transport.getSigner()
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export { AuthorizationError, ProviderRequiredError, SignerRequiredError, armoryDelete, armoryGet, armoryPatch, armoryPay, armoryPost, armoryPut, createArmory, createX402Client, createX402Payment, createX402Transport, detectX402Version, getNetworks, getPaymentHeaderName, getTokens, getWalletAddress, normalizeWallet, parsePaymentRequired, recoverEIP3009Signer, signEIP3009, signEIP3009WithDomain, signPayment, validateNetwork, validateToken };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@armory-sh/client-ethers",
|
|
3
|
-
"version": "0.2.26-alpha.23.
|
|
3
|
+
"version": "0.2.26-alpha.23.77",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Sawyer Cutler <sawyer@dirtroad.dev>",
|
|
6
6
|
"keywords": [
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"directory": "packages/client-ethers"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@armory-sh/base": "0.2.27-alpha.23.
|
|
50
|
+
"@armory-sh/base": "0.2.27-alpha.23.77",
|
|
51
51
|
"ethers": "6.16.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
@@ -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
|
}
|