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