@armory-sh/client-ethers 0.2.26-alpha.23.76 → 0.2.26-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 +155 -152
- package/dist/index.js +172 -65
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,37 +1,120 @@
|
|
|
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';
|
|
1
3
|
import { Signer, Provider } from 'ethers';
|
|
2
4
|
export { Provider, Signer } from 'ethers';
|
|
3
|
-
import {
|
|
4
|
-
export { PaymentException as PaymentError, SigningError, X402ClientError } from '@armory-sh/base';
|
|
5
|
+
import { ClientHook } from '@armory-sh/base/types/hooks';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* Handles parsing x402 V2 PAYMENT-REQUIRED headers
|
|
10
|
-
* and generating x402 V2 PAYMENT-SIGNATURE payloads
|
|
8
|
+
* Simple one-line payment API for Armory (Ethers)
|
|
9
|
+
* Focus on DX/UX - "everything just magically works"
|
|
11
10
|
*/
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
|
-
*
|
|
15
|
-
* V2-only: Always returns 2
|
|
13
|
+
* Simple wallet input - accepts wallet directly or wrapped for backward compatibility
|
|
16
14
|
*/
|
|
17
|
-
|
|
15
|
+
type SimpleWalletInput = Signer | {
|
|
16
|
+
signer: Signer;
|
|
17
|
+
};
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Normalized wallet (internal use)
|
|
20
20
|
*/
|
|
21
|
-
|
|
22
|
-
interface ParsedPaymentRequirements {
|
|
23
|
-
version: 2;
|
|
24
|
-
requirements: PaymentRequirementsV2;
|
|
25
|
-
}
|
|
21
|
+
type NormalizedWallet = Signer;
|
|
26
22
|
/**
|
|
27
|
-
*
|
|
28
|
-
* V2 only
|
|
23
|
+
* Normalize wallet input to internal format
|
|
29
24
|
*/
|
|
30
|
-
declare
|
|
25
|
+
declare const normalizeWallet: (wallet: SimpleWalletInput) => NormalizedWallet;
|
|
31
26
|
/**
|
|
32
|
-
*
|
|
27
|
+
* Make a payment-protected API request with one line of code
|
|
33
28
|
*/
|
|
34
|
-
declare
|
|
29
|
+
declare const armoryPay: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: {
|
|
30
|
+
/** Request method (default: GET) */
|
|
31
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
32
|
+
/** Request body (for POST/PUT/PATCH) */
|
|
33
|
+
body?: unknown;
|
|
34
|
+
/** Request headers */
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
/** Protocol version (V2 only) */
|
|
37
|
+
version?: 2;
|
|
38
|
+
/** Payment amount in token units (default: from 402 header) */
|
|
39
|
+
amount?: string;
|
|
40
|
+
/** Enable debug logging */
|
|
41
|
+
debug?: boolean;
|
|
42
|
+
}) => Promise<ArmoryPaymentResult<T>>;
|
|
43
|
+
/**
|
|
44
|
+
* Make a GET request with payment
|
|
45
|
+
*/
|
|
46
|
+
declare const armoryGet: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
47
|
+
/**
|
|
48
|
+
* Make a POST request with payment
|
|
49
|
+
*/
|
|
50
|
+
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>>;
|
|
51
|
+
/**
|
|
52
|
+
* Make a PUT request with payment
|
|
53
|
+
*/
|
|
54
|
+
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>>;
|
|
55
|
+
/**
|
|
56
|
+
* Make a DELETE request with payment
|
|
57
|
+
*/
|
|
58
|
+
declare const armoryDelete: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
59
|
+
/**
|
|
60
|
+
* Make a PATCH request with payment
|
|
61
|
+
*/
|
|
62
|
+
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>>;
|
|
63
|
+
/**
|
|
64
|
+
* Get the wallet address from a SimpleWalletInput
|
|
65
|
+
*/
|
|
66
|
+
declare const getWalletAddress: (wallet: SimpleWalletInput) => Promise<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Validate a network identifier without making a request
|
|
69
|
+
*/
|
|
70
|
+
declare const validateNetwork: (network: NetworkId) => ValidationError | {
|
|
71
|
+
success: true;
|
|
72
|
+
network: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Validate a token identifier without making a request
|
|
76
|
+
*/
|
|
77
|
+
declare const validateToken: (token: TokenId, network?: NetworkId) => ValidationError | {
|
|
78
|
+
success: true;
|
|
79
|
+
token: string;
|
|
80
|
+
network: string;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Get list of available networks
|
|
84
|
+
*/
|
|
85
|
+
declare const getNetworks: () => string[];
|
|
86
|
+
/**
|
|
87
|
+
* Get list of available tokens
|
|
88
|
+
*/
|
|
89
|
+
declare const getTokens: () => string[];
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Armory API - Simplified payment interface (Ethers)
|
|
93
|
+
* Provides a configurable object with method-based payment functions
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
97
|
+
interface ArmoryConfig {
|
|
98
|
+
wallet: SimpleWalletInput;
|
|
99
|
+
methods?: HttpMethod[] | HttpMethod;
|
|
100
|
+
tokens?: TokenId[] | TokenId;
|
|
101
|
+
chains?: NetworkId[] | NetworkId;
|
|
102
|
+
debug?: boolean;
|
|
103
|
+
}
|
|
104
|
+
interface PaymentOptions {
|
|
105
|
+
method?: HttpMethod;
|
|
106
|
+
body?: unknown;
|
|
107
|
+
}
|
|
108
|
+
interface ArmoryInstance {
|
|
109
|
+
get<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
110
|
+
post<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
111
|
+
put<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
112
|
+
delete<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
113
|
+
patch<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
114
|
+
pay<T>(url: string, options?: PaymentOptions): Promise<ArmoryPaymentResult<T>>;
|
|
115
|
+
call<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
116
|
+
}
|
|
117
|
+
declare const createArmory: (config: ArmoryConfig) => ArmoryInstance;
|
|
35
118
|
|
|
36
119
|
declare class SignerRequiredError extends X402ClientError {
|
|
37
120
|
constructor(message?: string);
|
|
@@ -58,6 +141,7 @@ interface X402ClientConfig {
|
|
|
58
141
|
domainName?: string;
|
|
59
142
|
/** Override EIP-712 domain version for custom tokens */
|
|
60
143
|
domainVersion?: string;
|
|
144
|
+
hooks?: ClientHook<Signer>[];
|
|
61
145
|
}
|
|
62
146
|
interface SignerClientConfig extends X402ClientConfig {
|
|
63
147
|
signer: Signer;
|
|
@@ -77,6 +161,7 @@ interface X402TransportConfig {
|
|
|
77
161
|
onPaymentRequired?: (requirements: unknown) => boolean | Promise<boolean>;
|
|
78
162
|
onPaymentSuccess?: (settlement: unknown) => void;
|
|
79
163
|
onPaymentError?: (error: Error) => void;
|
|
164
|
+
hooks?: ClientHook<Signer>[];
|
|
80
165
|
}
|
|
81
166
|
interface X402RequestInit extends Omit<RequestInit, "headers"> {
|
|
82
167
|
headers?: Record<string, string> | Headers;
|
|
@@ -98,40 +183,6 @@ interface EIP712Domain {
|
|
|
98
183
|
verifyingContract: `0x${string}`;
|
|
99
184
|
}
|
|
100
185
|
|
|
101
|
-
interface X402Transport {
|
|
102
|
-
fetch(url: string, init?: X402RequestInit): Promise<Response>;
|
|
103
|
-
get(url: string, init?: X402RequestInit): Promise<Response>;
|
|
104
|
-
post(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
105
|
-
put(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
106
|
-
del(url: string, init?: X402RequestInit): Promise<Response>;
|
|
107
|
-
patch(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
108
|
-
setSigner(signer: Signer): void;
|
|
109
|
-
getSigner(): Signer | undefined;
|
|
110
|
-
}
|
|
111
|
-
declare const createX402Transport: (config?: X402TransportConfig) => X402Transport;
|
|
112
|
-
|
|
113
|
-
declare function signEIP3009(signer: Signer, params: TransferWithAuthorizationParams, domain: EIP712Domain): Promise<{
|
|
114
|
-
v: number;
|
|
115
|
-
r: string;
|
|
116
|
-
s: string;
|
|
117
|
-
}>;
|
|
118
|
-
declare function signEIP3009WithDomain(signer: Signer, params: TransferWithAuthorizationParams, chainId: number, verifyingContract: `0x${string}`, domainName?: string, domainVersion?: string): Promise<{
|
|
119
|
-
v: number;
|
|
120
|
-
r: string;
|
|
121
|
-
s: string;
|
|
122
|
-
}>;
|
|
123
|
-
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<{
|
|
124
|
-
v: number;
|
|
125
|
-
r: string;
|
|
126
|
-
s: string;
|
|
127
|
-
nonce: `0x${string}`;
|
|
128
|
-
}>;
|
|
129
|
-
declare function recoverEIP3009Signer(params: TransferWithAuthorizationParams, signature: {
|
|
130
|
-
v: number;
|
|
131
|
-
r: string;
|
|
132
|
-
s: string;
|
|
133
|
-
}, domain: EIP712Domain): Promise<`0x${string}`>;
|
|
134
|
-
|
|
135
186
|
/**
|
|
136
187
|
* X402 Client Factory for Ethers
|
|
137
188
|
*
|
|
@@ -184,116 +235,68 @@ declare function createX402Client(config: X402ClientConfig & SignerClientConfig
|
|
|
184
235
|
}): X402Client;
|
|
185
236
|
declare function createX402Client(config: X402ClientConfig & ProviderClientConfig): X402Client;
|
|
186
237
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
238
|
+
declare function signEIP3009(signer: Signer, params: TransferWithAuthorizationParams, domain: EIP712Domain): Promise<{
|
|
239
|
+
v: number;
|
|
240
|
+
r: string;
|
|
241
|
+
s: string;
|
|
242
|
+
}>;
|
|
243
|
+
declare function signEIP3009WithDomain(signer: Signer, params: TransferWithAuthorizationParams, chainId: number, verifyingContract: `0x${string}`, domainName?: string, domainVersion?: string): Promise<{
|
|
244
|
+
v: number;
|
|
245
|
+
r: string;
|
|
246
|
+
s: string;
|
|
247
|
+
}>;
|
|
248
|
+
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<{
|
|
249
|
+
v: number;
|
|
250
|
+
r: string;
|
|
251
|
+
s: string;
|
|
252
|
+
nonce: `0x${string}`;
|
|
253
|
+
}>;
|
|
254
|
+
declare function recoverEIP3009Signer(params: TransferWithAuthorizationParams, signature: {
|
|
255
|
+
v: number;
|
|
256
|
+
r: string;
|
|
257
|
+
s: string;
|
|
258
|
+
}, domain: EIP712Domain): Promise<`0x${string}`>;
|
|
191
259
|
|
|
192
260
|
/**
|
|
193
|
-
*
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
};
|
|
198
|
-
/**
|
|
199
|
-
* Normalized wallet (internal use)
|
|
200
|
-
*/
|
|
201
|
-
type NormalizedWallet = Signer;
|
|
202
|
-
/**
|
|
203
|
-
* Normalize wallet input to internal format
|
|
204
|
-
*/
|
|
205
|
-
declare const normalizeWallet: (wallet: SimpleWalletInput) => NormalizedWallet;
|
|
206
|
-
/**
|
|
207
|
-
* Make a payment-protected API request with one line of code
|
|
208
|
-
*/
|
|
209
|
-
declare const armoryPay: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: {
|
|
210
|
-
/** Request method (default: GET) */
|
|
211
|
-
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
212
|
-
/** Request body (for POST/PUT/PATCH) */
|
|
213
|
-
body?: unknown;
|
|
214
|
-
/** Request headers */
|
|
215
|
-
headers?: Record<string, string>;
|
|
216
|
-
/** Protocol version (V2 only) */
|
|
217
|
-
version?: 2;
|
|
218
|
-
/** Payment amount in token units (default: from 402 header) */
|
|
219
|
-
amount?: string;
|
|
220
|
-
/** Enable debug logging */
|
|
221
|
-
debug?: boolean;
|
|
222
|
-
}) => Promise<ArmoryPaymentResult<T>>;
|
|
223
|
-
/**
|
|
224
|
-
* Make a GET request with payment
|
|
225
|
-
*/
|
|
226
|
-
declare const armoryGet: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
227
|
-
/**
|
|
228
|
-
* Make a POST request with payment
|
|
229
|
-
*/
|
|
230
|
-
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>>;
|
|
231
|
-
/**
|
|
232
|
-
* Make a PUT request with payment
|
|
233
|
-
*/
|
|
234
|
-
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>>;
|
|
235
|
-
/**
|
|
236
|
-
* Make a DELETE request with payment
|
|
237
|
-
*/
|
|
238
|
-
declare const armoryDelete: <T = unknown>(wallet: SimpleWalletInput, url: string, network: NetworkId, token: TokenId, options?: Omit<Parameters<typeof armoryPay>[4], "method">) => Promise<ArmoryPaymentResult<T>>;
|
|
239
|
-
/**
|
|
240
|
-
* Make a PATCH request with payment
|
|
241
|
-
*/
|
|
242
|
-
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>>;
|
|
243
|
-
/**
|
|
244
|
-
* Get the wallet address from a SimpleWalletInput
|
|
245
|
-
*/
|
|
246
|
-
declare const getWalletAddress: (wallet: SimpleWalletInput) => Promise<string>;
|
|
247
|
-
/**
|
|
248
|
-
* Validate a network identifier without making a request
|
|
261
|
+
* X402 Protocol Implementation for Ethers Client (V2 Only)
|
|
262
|
+
*
|
|
263
|
+
* Handles parsing x402 V2 PAYMENT-REQUIRED headers
|
|
264
|
+
* and generating x402 V2 PAYMENT-SIGNATURE payloads
|
|
249
265
|
*/
|
|
250
|
-
|
|
251
|
-
success: true;
|
|
252
|
-
network: string;
|
|
253
|
-
};
|
|
266
|
+
|
|
254
267
|
/**
|
|
255
|
-
*
|
|
268
|
+
* Detect x402 protocol version from response headers
|
|
269
|
+
* V2-only: Always returns 2
|
|
256
270
|
*/
|
|
257
|
-
declare
|
|
258
|
-
success: true;
|
|
259
|
-
token: string;
|
|
260
|
-
network: string;
|
|
261
|
-
};
|
|
271
|
+
declare function detectX402Version(_response: Response): 2;
|
|
262
272
|
/**
|
|
263
|
-
* Get
|
|
273
|
+
* Get payment header name for protocol version
|
|
264
274
|
*/
|
|
265
|
-
declare
|
|
275
|
+
declare function getPaymentHeaderName(_version: 2): string;
|
|
276
|
+
interface ParsedPaymentRequirements {
|
|
277
|
+
version: 2;
|
|
278
|
+
accepts: PaymentRequirementsV2[];
|
|
279
|
+
}
|
|
266
280
|
/**
|
|
267
|
-
*
|
|
281
|
+
* Parse x402 PAYMENT-REQUIRED header from response
|
|
282
|
+
* V2 only
|
|
268
283
|
*/
|
|
269
|
-
declare
|
|
270
|
-
|
|
284
|
+
declare function parsePaymentRequired(response: Response): ParsedPaymentRequirements;
|
|
271
285
|
/**
|
|
272
|
-
*
|
|
273
|
-
* Provides a configurable object with method-based payment functions
|
|
286
|
+
* Create x402 payment payload (V2-only wrapper)
|
|
274
287
|
*/
|
|
288
|
+
declare function createX402Payment(signer: Signer, requirement: PaymentRequirementsV2, fromAddress: Address, nonce?: `0x${string}`, validBefore?: number, domainName?: string, domainVersion?: string): Promise<PaymentPayloadV2>;
|
|
275
289
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
method?: HttpMethod;
|
|
286
|
-
body?: unknown;
|
|
287
|
-
}
|
|
288
|
-
interface ArmoryInstance {
|
|
289
|
-
get<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
290
|
-
post<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
291
|
-
put<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
292
|
-
delete<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
293
|
-
patch<T>(url: string, body?: unknown): Promise<ArmoryPaymentResult<T>>;
|
|
294
|
-
pay<T>(url: string, options?: PaymentOptions): Promise<ArmoryPaymentResult<T>>;
|
|
295
|
-
call<T>(url: string): Promise<ArmoryPaymentResult<T>>;
|
|
290
|
+
interface X402Transport {
|
|
291
|
+
fetch(url: string, init?: X402RequestInit): Promise<Response>;
|
|
292
|
+
get(url: string, init?: X402RequestInit): Promise<Response>;
|
|
293
|
+
post(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
294
|
+
put(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
295
|
+
del(url: string, init?: X402RequestInit): Promise<Response>;
|
|
296
|
+
patch(url: string, body?: unknown, init?: X402RequestInit): Promise<Response>;
|
|
297
|
+
setSigner(signer: Signer): void;
|
|
298
|
+
getSigner(): Signer | undefined;
|
|
296
299
|
}
|
|
297
|
-
declare const
|
|
300
|
+
declare const createX402Transport: (config?: X402TransportConfig) => X402Transport;
|
|
298
301
|
|
|
299
302
|
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,6 @@
|
|
|
1
1
|
import { X402ClientError, createEIP712Domain, V2_HEADERS, PaymentException, isX402V2PaymentRequired, validatePaymentConfig, isValidationError, resolveNetwork, resolveToken, normalizeBase64Url, decodeBase64ToUtf8, getNetworkConfig, normalizeNetworkName, encodePaymentV2, decodeSettlementV2 } from '@armory-sh/base';
|
|
2
2
|
export { PaymentException as PaymentError, SigningError, X402ClientError } from '@armory-sh/base';
|
|
3
|
+
import { runOnPaymentRequiredHooks, selectRequirementWithHooks, runBeforeSignPaymentHooks, runAfterPaymentResponseHooks } from '@armory-sh/base/client-hooks-runtime';
|
|
3
4
|
import { ethers } from 'ethers';
|
|
4
5
|
|
|
5
6
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
@@ -26,8 +27,6 @@ var ProviderRequiredError = class extends X402ClientError {
|
|
|
26
27
|
this.name = "ProviderRequiredError";
|
|
27
28
|
}
|
|
28
29
|
};
|
|
29
|
-
|
|
30
|
-
// src/eip3009.ts
|
|
31
30
|
var EIP712_TYPES_ETHERS = {
|
|
32
31
|
TransferWithAuthorization: [
|
|
33
32
|
{ name: "from", type: "address" },
|
|
@@ -48,7 +47,11 @@ async function signEIP3009(signer, params, domain) {
|
|
|
48
47
|
validBefore: BigInt(params.validBefore),
|
|
49
48
|
nonce: params.nonce
|
|
50
49
|
};
|
|
51
|
-
const signature = await signer.signTypedData(
|
|
50
|
+
const signature = await signer.signTypedData(
|
|
51
|
+
domain,
|
|
52
|
+
EIP712_TYPES_ETHERS,
|
|
53
|
+
message
|
|
54
|
+
);
|
|
52
55
|
const { v, r, s } = ethers.Signature.from(signature);
|
|
53
56
|
return { v: Number(v), r, s };
|
|
54
57
|
} catch (error) {
|
|
@@ -60,7 +63,11 @@ async function signEIP3009(signer, params, domain) {
|
|
|
60
63
|
}
|
|
61
64
|
async function signEIP3009WithDomain(signer, params, chainId, verifyingContract, domainName, domainVersion) {
|
|
62
65
|
const domain = createEIP712Domain(chainId, verifyingContract);
|
|
63
|
-
const customDomain = domainName || domainVersion ? {
|
|
66
|
+
const customDomain = domainName || domainVersion ? {
|
|
67
|
+
...domain,
|
|
68
|
+
name: domainName ?? domain.name,
|
|
69
|
+
version: domainVersion ?? domain.version
|
|
70
|
+
} : domain;
|
|
64
71
|
return signEIP3009(signer, params, customDomain);
|
|
65
72
|
}
|
|
66
73
|
async function signPayment(signer, from, to, value, chainId, verifyingContract, expirySeconds = 3600, domainName, domainVersion) {
|
|
@@ -68,7 +75,14 @@ async function signPayment(signer, from, to, value, chainId, verifyingContract,
|
|
|
68
75
|
const nonce = `0x${(now * 1e3).toString(16).padStart(64, "0")}`;
|
|
69
76
|
const signature = await signEIP3009WithDomain(
|
|
70
77
|
signer,
|
|
71
|
-
{
|
|
78
|
+
{
|
|
79
|
+
from,
|
|
80
|
+
to,
|
|
81
|
+
value,
|
|
82
|
+
validAfter: 0n,
|
|
83
|
+
validBefore: BigInt(now + expirySeconds),
|
|
84
|
+
nonce
|
|
85
|
+
},
|
|
72
86
|
chainId,
|
|
73
87
|
verifyingContract,
|
|
74
88
|
domainName,
|
|
@@ -90,7 +104,12 @@ async function recoverEIP3009Signer(params, signature, domain) {
|
|
|
90
104
|
r: signature.r,
|
|
91
105
|
s: signature.s
|
|
92
106
|
});
|
|
93
|
-
const address = ethers.verifyTypedData(
|
|
107
|
+
const address = ethers.verifyTypedData(
|
|
108
|
+
domain,
|
|
109
|
+
EIP712_TYPES_ETHERS,
|
|
110
|
+
message,
|
|
111
|
+
sig
|
|
112
|
+
);
|
|
94
113
|
return address;
|
|
95
114
|
}
|
|
96
115
|
|
|
@@ -124,11 +143,13 @@ function parsePaymentRequired(response) {
|
|
|
124
143
|
}
|
|
125
144
|
return {
|
|
126
145
|
version: 2,
|
|
127
|
-
|
|
146
|
+
accepts: parsed.accepts
|
|
128
147
|
};
|
|
129
148
|
} catch (error) {
|
|
130
149
|
if (error instanceof PaymentException) throw error;
|
|
131
|
-
throw new PaymentException(
|
|
150
|
+
throw new PaymentException(
|
|
151
|
+
`Failed to parse V2 PAYMENT-REQUIRED header: ${error}`
|
|
152
|
+
);
|
|
132
153
|
}
|
|
133
154
|
}
|
|
134
155
|
function extractChainId(network) {
|
|
@@ -150,7 +171,11 @@ async function createX402V2Payment(signer, requirements, fromAddress, nonce, val
|
|
|
150
171
|
const chainId = extractChainId(requirements.network);
|
|
151
172
|
const now = Math.floor(Date.now() / 1e3);
|
|
152
173
|
const domain = createEIP712Domain(chainId, contractAddress);
|
|
153
|
-
const customDomain = domainName || domainVersion ? {
|
|
174
|
+
const customDomain = domainName || domainVersion ? {
|
|
175
|
+
...domain,
|
|
176
|
+
name: domainName ?? domain.name,
|
|
177
|
+
version: domainVersion ?? domain.version
|
|
178
|
+
} : domain;
|
|
154
179
|
const authorization = {
|
|
155
180
|
from: fromAddress,
|
|
156
181
|
to: requirements.payTo,
|
|
@@ -179,12 +204,12 @@ async function createX402V2Payment(signer, requirements, fromAddress, nonce, val
|
|
|
179
204
|
payload
|
|
180
205
|
};
|
|
181
206
|
}
|
|
182
|
-
async function createX402Payment(signer,
|
|
207
|
+
async function createX402Payment(signer, requirement, fromAddress, nonce, validBefore, domainName, domainVersion) {
|
|
183
208
|
const effectiveNonce = nonce ?? createNonce();
|
|
184
209
|
const effectiveValidBefore = validBefore ?? Math.floor(Date.now() / 1e3) + 3600;
|
|
185
210
|
return createX402V2Payment(
|
|
186
211
|
signer,
|
|
187
|
-
|
|
212
|
+
requirement,
|
|
188
213
|
fromAddress,
|
|
189
214
|
effectiveNonce,
|
|
190
215
|
effectiveValidBefore,
|
|
@@ -192,6 +217,8 @@ async function createX402Payment(signer, parsed, fromAddress, nonce, validBefore
|
|
|
192
217
|
domainVersion
|
|
193
218
|
);
|
|
194
219
|
}
|
|
220
|
+
|
|
221
|
+
// src/transport.ts
|
|
195
222
|
var defaultConfig = {
|
|
196
223
|
baseURL: "",
|
|
197
224
|
headers: {},
|
|
@@ -203,7 +230,8 @@ var defaultConfig = {
|
|
|
203
230
|
onPaymentSuccess: () => {
|
|
204
231
|
},
|
|
205
232
|
onPaymentError: () => {
|
|
206
|
-
}
|
|
233
|
+
},
|
|
234
|
+
hooks: []
|
|
207
235
|
};
|
|
208
236
|
var createState = (config) => ({
|
|
209
237
|
config: { ...defaultConfig, ...config }
|
|
@@ -224,11 +252,11 @@ var fetchWithTimeout = async (url, init, timeout) => {
|
|
|
224
252
|
}
|
|
225
253
|
};
|
|
226
254
|
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
227
|
-
var getRequirementDomainOverrides = (
|
|
228
|
-
const requirement = parsed.requirements;
|
|
255
|
+
var getRequirementDomainOverrides = (_parsed, requirement) => {
|
|
229
256
|
const extra = requirement.extra;
|
|
230
|
-
const
|
|
231
|
-
const
|
|
257
|
+
const extraRecord = extra && typeof extra === "object" ? extra : void 0;
|
|
258
|
+
const extraName = extraRecord && typeof extraRecord.name === "string" ? extraRecord.name : void 0;
|
|
259
|
+
const extraVersion = extraRecord && typeof extraRecord.version === "string" ? extraRecord.version : void 0;
|
|
232
260
|
return {
|
|
233
261
|
domainName: requirement.name ?? extraName,
|
|
234
262
|
domainVersion: requirement.version ?? extraVersion
|
|
@@ -236,21 +264,52 @@ var getRequirementDomainOverrides = (parsed) => {
|
|
|
236
264
|
};
|
|
237
265
|
var handlePaymentRequired = async (state, response) => {
|
|
238
266
|
if (!state.signer) {
|
|
239
|
-
throw new SignerRequiredError(
|
|
267
|
+
throw new SignerRequiredError(
|
|
268
|
+
"Cannot handle payment: no signer configured."
|
|
269
|
+
);
|
|
240
270
|
}
|
|
241
271
|
try {
|
|
242
272
|
const parsed = parsePaymentRequired(response);
|
|
273
|
+
const initialRequirement = parsed.accepts[0];
|
|
274
|
+
if (!initialRequirement) {
|
|
275
|
+
throw new Error("No payment requirements found in accepts array");
|
|
276
|
+
}
|
|
243
277
|
const from = await state.signer.getAddress();
|
|
244
|
-
const
|
|
278
|
+
const paymentRequiredContext = {
|
|
279
|
+
url: response.url,
|
|
280
|
+
requestInit: void 0,
|
|
281
|
+
accepts: parsed.accepts,
|
|
282
|
+
requirements: initialRequirement,
|
|
283
|
+
selectedRequirement: initialRequirement,
|
|
284
|
+
serverExtensions: void 0,
|
|
285
|
+
fromAddress: from,
|
|
286
|
+
nonce: `0x${Date.now().toString(16).padStart(64, "0")}`,
|
|
287
|
+
validBefore: Math.floor(Date.now() / 1e3) + initialRequirement.maxTimeoutSeconds
|
|
288
|
+
};
|
|
289
|
+
await runOnPaymentRequiredHooks(state.config.hooks, paymentRequiredContext);
|
|
290
|
+
const selectedRequirement = await selectRequirementWithHooks(
|
|
291
|
+
state.config.hooks,
|
|
292
|
+
paymentRequiredContext
|
|
293
|
+
);
|
|
294
|
+
const requirementDomain = getRequirementDomainOverrides(
|
|
295
|
+
parsed,
|
|
296
|
+
selectedRequirement
|
|
297
|
+
);
|
|
245
298
|
const payload = await createX402Payment(
|
|
246
299
|
state.signer,
|
|
247
|
-
|
|
300
|
+
selectedRequirement,
|
|
248
301
|
from,
|
|
249
|
-
|
|
250
|
-
|
|
302
|
+
paymentRequiredContext.nonce,
|
|
303
|
+
paymentRequiredContext.validBefore,
|
|
251
304
|
requirementDomain.domainName,
|
|
252
305
|
requirementDomain.domainVersion
|
|
253
306
|
);
|
|
307
|
+
await runBeforeSignPaymentHooks(state.config.hooks, {
|
|
308
|
+
payload,
|
|
309
|
+
requirements: selectedRequirement,
|
|
310
|
+
wallet: state.signer,
|
|
311
|
+
paymentContext: paymentRequiredContext
|
|
312
|
+
});
|
|
254
313
|
const encoded = encodePaymentV2(payload);
|
|
255
314
|
const headerName = getPaymentHeaderName(parsed.version);
|
|
256
315
|
const paymentResponse = await fetchWithTimeout(
|
|
@@ -261,30 +320,48 @@ var handlePaymentRequired = async (state, response) => {
|
|
|
261
320
|
},
|
|
262
321
|
state.config.timeout
|
|
263
322
|
);
|
|
264
|
-
const settlement = decodeSettlementV2(
|
|
323
|
+
const settlement = decodeSettlementV2(
|
|
324
|
+
paymentResponse.headers.get(V2_HEADERS.PAYMENT_RESPONSE) || ""
|
|
325
|
+
);
|
|
326
|
+
await runAfterPaymentResponseHooks(state.config.hooks, {
|
|
327
|
+
payload,
|
|
328
|
+
requirements: selectedRequirement,
|
|
329
|
+
wallet: state.signer,
|
|
330
|
+
paymentContext: paymentRequiredContext,
|
|
331
|
+
response: paymentResponse
|
|
332
|
+
});
|
|
265
333
|
return { success: true, settlement };
|
|
266
334
|
} catch (error) {
|
|
267
|
-
return {
|
|
335
|
+
return {
|
|
336
|
+
success: false,
|
|
337
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
338
|
+
};
|
|
268
339
|
}
|
|
269
340
|
};
|
|
270
341
|
var shouldRetryPayment = async (state, response) => {
|
|
271
342
|
if (!state.config.autoPay) return false;
|
|
272
343
|
const parsed = parsePaymentRequired(response);
|
|
273
|
-
return await state.config.onPaymentRequired(parsed.
|
|
344
|
+
return await state.config.onPaymentRequired(parsed.accepts[0]);
|
|
274
345
|
};
|
|
275
346
|
var x402Fetch = async (state, url, init = {}) => {
|
|
276
347
|
const fullUrl = state.config.baseURL ? new URL(url, state.config.baseURL).toString() : url;
|
|
277
348
|
const headers = new Headers({ ...state.config.headers, ...init.headers });
|
|
278
349
|
for (let attempt = 1; attempt <= state.config.maxRetries; attempt++) {
|
|
279
350
|
try {
|
|
280
|
-
const response = await fetchWithTimeout(
|
|
351
|
+
const response = await fetchWithTimeout(
|
|
352
|
+
fullUrl,
|
|
353
|
+
{ ...init, headers },
|
|
354
|
+
state.config.timeout
|
|
355
|
+
);
|
|
281
356
|
if (response.status === 402 && !init.skipAutoPay && await shouldRetryPayment(state, response)) {
|
|
282
357
|
const paymentResult = await handlePaymentRequired(state, response);
|
|
283
358
|
if (paymentResult.success) {
|
|
284
359
|
state.config.onPaymentSuccess(paymentResult.settlement);
|
|
285
360
|
continue;
|
|
286
361
|
}
|
|
287
|
-
state.config.onPaymentError(
|
|
362
|
+
state.config.onPaymentError(
|
|
363
|
+
paymentResult.error ?? new Error("Payment failed")
|
|
364
|
+
);
|
|
288
365
|
}
|
|
289
366
|
return response;
|
|
290
367
|
} catch (error) {
|
|
@@ -307,7 +384,7 @@ var createMethod = (state, method) => async (url, bodyOrInit, init) => {
|
|
|
307
384
|
});
|
|
308
385
|
};
|
|
309
386
|
var createX402Transport = (config) => {
|
|
310
|
-
|
|
387
|
+
const state = createState(config);
|
|
311
388
|
return {
|
|
312
389
|
fetch: (url, init) => x402Fetch(state, url, init),
|
|
313
390
|
get: createMethod(state, "GET"),
|
|
@@ -322,37 +399,7 @@ var createX402Transport = (config) => {
|
|
|
322
399
|
};
|
|
323
400
|
};
|
|
324
401
|
|
|
325
|
-
// src/
|
|
326
|
-
function createX402Client(config) {
|
|
327
|
-
const transport = createX402Transport(void 0);
|
|
328
|
-
if ("signer" in config && config.signer) {
|
|
329
|
-
transport.setSigner(config.signer);
|
|
330
|
-
} else if ("provider" in config && config.provider) {
|
|
331
|
-
const provider = config.provider;
|
|
332
|
-
if (provider.getSigner) {
|
|
333
|
-
try {
|
|
334
|
-
const signer = provider.getSigner();
|
|
335
|
-
if (signer) {
|
|
336
|
-
transport.setSigner(signer);
|
|
337
|
-
}
|
|
338
|
-
} catch {
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
} else {
|
|
342
|
-
throw new SignerRequiredError(
|
|
343
|
-
"Either 'signer' or 'provider' with getSigner() must be provided"
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
return {
|
|
347
|
-
get: (url, init) => transport.get(url, init),
|
|
348
|
-
post: (url, body, init) => transport.post(url, body, init),
|
|
349
|
-
put: (url, body, init) => transport.put(url, body, init),
|
|
350
|
-
del: (url, init) => transport.del(url, init),
|
|
351
|
-
patch: (url, body, init) => transport.patch(url, body, init),
|
|
352
|
-
setSigner: (signer) => transport.setSigner(signer),
|
|
353
|
-
getSigner: () => transport.getSigner()
|
|
354
|
-
};
|
|
355
|
-
}
|
|
402
|
+
// src/payment-api.ts
|
|
356
403
|
var normalizeWallet = (wallet) => {
|
|
357
404
|
if (typeof wallet === "object" && wallet !== null && "signer" in wallet) {
|
|
358
405
|
return wallet.signer;
|
|
@@ -414,19 +461,37 @@ var armoryPay = async (wallet, url, network, token, options) => {
|
|
|
414
461
|
}
|
|
415
462
|
};
|
|
416
463
|
var armoryGet = (wallet, url, network, token, options) => {
|
|
417
|
-
return armoryPay(wallet, url, network, token, {
|
|
464
|
+
return armoryPay(wallet, url, network, token, {
|
|
465
|
+
...options,
|
|
466
|
+
method: "GET"
|
|
467
|
+
});
|
|
418
468
|
};
|
|
419
469
|
var armoryPost = (wallet, url, network, token, body, options) => {
|
|
420
|
-
return armoryPay(wallet, url, network, token, {
|
|
470
|
+
return armoryPay(wallet, url, network, token, {
|
|
471
|
+
...options,
|
|
472
|
+
method: "POST",
|
|
473
|
+
body
|
|
474
|
+
});
|
|
421
475
|
};
|
|
422
476
|
var armoryPut = (wallet, url, network, token, body, options) => {
|
|
423
|
-
return armoryPay(wallet, url, network, token, {
|
|
477
|
+
return armoryPay(wallet, url, network, token, {
|
|
478
|
+
...options,
|
|
479
|
+
method: "PUT",
|
|
480
|
+
body
|
|
481
|
+
});
|
|
424
482
|
};
|
|
425
483
|
var armoryDelete = (wallet, url, network, token, options) => {
|
|
426
|
-
return armoryPay(wallet, url, network, token, {
|
|
484
|
+
return armoryPay(wallet, url, network, token, {
|
|
485
|
+
...options,
|
|
486
|
+
method: "DELETE"
|
|
487
|
+
});
|
|
427
488
|
};
|
|
428
489
|
var armoryPatch = (wallet, url, network, token, body, options) => {
|
|
429
|
-
return armoryPay(wallet, url, network, token, {
|
|
490
|
+
return armoryPay(wallet, url, network, token, {
|
|
491
|
+
...options,
|
|
492
|
+
method: "PATCH",
|
|
493
|
+
body
|
|
494
|
+
});
|
|
430
495
|
};
|
|
431
496
|
var getWalletAddress = async (wallet) => {
|
|
432
497
|
const signer = normalizeWallet(wallet);
|
|
@@ -440,7 +505,7 @@ var validateNetwork = (network) => {
|
|
|
440
505
|
return { success: true, network: resolved.config.name };
|
|
441
506
|
};
|
|
442
507
|
var validateToken = (token, network) => {
|
|
443
|
-
let resolvedNetwork
|
|
508
|
+
let resolvedNetwork;
|
|
444
509
|
if (network) {
|
|
445
510
|
const networkResult = resolveNetwork(network);
|
|
446
511
|
if (isValidationError(networkResult)) {
|
|
@@ -466,7 +531,15 @@ var getTokens = () => {
|
|
|
466
531
|
const { getAvailableTokens } = __require("@armory-sh/base");
|
|
467
532
|
return getAvailableTokens();
|
|
468
533
|
};
|
|
469
|
-
|
|
534
|
+
|
|
535
|
+
// src/armory-api.ts
|
|
536
|
+
var ALL_METHODS = /* @__PURE__ */ new Set([
|
|
537
|
+
"GET",
|
|
538
|
+
"POST",
|
|
539
|
+
"PUT",
|
|
540
|
+
"DELETE",
|
|
541
|
+
"PATCH"
|
|
542
|
+
]);
|
|
470
543
|
var arrayify = (value) => {
|
|
471
544
|
if (value === void 0) return void 0;
|
|
472
545
|
return Array.isArray(value) ? value : [value];
|
|
@@ -534,4 +607,38 @@ var createArmory = (config) => {
|
|
|
534
607
|
};
|
|
535
608
|
};
|
|
536
609
|
|
|
610
|
+
// src/client.ts
|
|
611
|
+
function createX402Client(config) {
|
|
612
|
+
const transport = createX402Transport({
|
|
613
|
+
hooks: config.hooks
|
|
614
|
+
});
|
|
615
|
+
if ("signer" in config && config.signer) {
|
|
616
|
+
transport.setSigner(config.signer);
|
|
617
|
+
} else if ("provider" in config && config.provider) {
|
|
618
|
+
const provider = config.provider;
|
|
619
|
+
if (provider.getSigner) {
|
|
620
|
+
try {
|
|
621
|
+
const signer = provider.getSigner();
|
|
622
|
+
if (signer) {
|
|
623
|
+
transport.setSigner(signer);
|
|
624
|
+
}
|
|
625
|
+
} catch {
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
} else {
|
|
629
|
+
throw new SignerRequiredError(
|
|
630
|
+
"Either 'signer' or 'provider' with getSigner() must be provided"
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
return {
|
|
634
|
+
get: (url, init) => transport.get(url, init),
|
|
635
|
+
post: (url, body, init) => transport.post(url, body, init),
|
|
636
|
+
put: (url, body, init) => transport.put(url, body, init),
|
|
637
|
+
del: (url, init) => transport.del(url, init),
|
|
638
|
+
patch: (url, body, init) => transport.patch(url, body, init),
|
|
639
|
+
setSigner: (signer) => transport.setSigner(signer),
|
|
640
|
+
getSigner: () => transport.getSigner()
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
|
|
537
644
|
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.78",
|
|
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.78",
|
|
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
|
}
|