@x402/evm 2.3.1 → 2.5.0
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/cjs/exact/client/index.d.ts +2 -2
- package/dist/cjs/exact/client/index.js +412 -169
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +18 -18
- package/dist/cjs/exact/facilitator/index.js +467 -157
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.d.ts +1 -1
- package/dist/cjs/exact/v1/client/index.js +17 -18
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.d.ts +1 -1
- package/dist/cjs/exact/v1/facilitator/index.js +7 -8
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -390
- package/dist/cjs/index.js +363 -110
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/permit2-CQbXqCMC.d.ts +517 -0
- package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
- package/dist/cjs/v1/index.d.ts +11 -2
- package/dist/cjs/v1/index.js +14 -11
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/{chunk-RPL6OFJL.mjs → chunk-7KHQD5KT.mjs} +92 -37
- package/dist/esm/chunk-7KHQD5KT.mjs.map +1 -0
- package/dist/esm/chunk-GY6X5A3G.mjs +425 -0
- package/dist/esm/chunk-GY6X5A3G.mjs.map +1 -0
- package/dist/esm/{chunk-PFULIQAE.mjs → chunk-TKN5V2BV.mjs} +1 -1
- package/dist/esm/chunk-TKN5V2BV.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +2 -2
- package/dist/esm/exact/client/index.mjs +4 -3
- package/dist/esm/exact/facilitator/index.d.mts +18 -18
- package/dist/esm/exact/facilitator/index.mjs +401 -99
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/v1/client/index.d.mts +1 -1
- package/dist/esm/exact/v1/client/index.mjs +2 -2
- package/dist/esm/exact/v1/facilitator/index.d.mts +1 -1
- package/dist/esm/exact/v1/facilitator/index.mjs +2 -2
- package/dist/esm/index.d.mts +3 -390
- package/dist/esm/index.mjs +29 -6
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/permit2-CGOcN7Et.d.mts +517 -0
- package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
- package/dist/esm/v1/index.d.mts +11 -2
- package/dist/esm/v1/index.mjs +6 -4
- package/package.json +3 -2
- package/dist/cjs/permit2-BYv82va2.d.ts +0 -103
- package/dist/cjs/signer-5OVDxViv.d.ts +0 -79
- package/dist/esm/chunk-E2YMUI3X.mjs +0 -229
- package/dist/esm/chunk-E2YMUI3X.mjs.map +0 -1
- package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
- package/dist/esm/chunk-RPL6OFJL.mjs.map +0 -1
- package/dist/esm/permit2-BsAoJiWD.d.mts +0 -103
- package/dist/esm/signer-5OVDxViv.d.mts +0 -79
|
@@ -28,8 +28,8 @@ __export(client_exports, {
|
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(client_exports);
|
|
30
30
|
|
|
31
|
-
// src/exact/client/
|
|
32
|
-
var
|
|
31
|
+
// src/exact/client/scheme.ts
|
|
32
|
+
var import_extensions2 = require("@x402/extensions");
|
|
33
33
|
|
|
34
34
|
// src/constants.ts
|
|
35
35
|
var authorizationTypes = {
|
|
@@ -56,131 +56,72 @@ var permit2WitnessTypes = {
|
|
|
56
56
|
],
|
|
57
57
|
Witness: [
|
|
58
58
|
{ name: "to", type: "address" },
|
|
59
|
-
{ name: "validAfter", type: "uint256" }
|
|
60
|
-
{ name: "extra", type: "bytes" }
|
|
59
|
+
{ name: "validAfter", type: "uint256" }
|
|
61
60
|
]
|
|
62
61
|
};
|
|
63
|
-
var
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this.scheme = "exact";
|
|
62
|
+
var eip2612PermitTypes = {
|
|
63
|
+
Permit: [
|
|
64
|
+
{ name: "owner", type: "address" },
|
|
65
|
+
{ name: "spender", type: "address" },
|
|
66
|
+
{ name: "value", type: "uint256" },
|
|
67
|
+
{ name: "nonce", type: "uint256" },
|
|
68
|
+
{ name: "deadline", type: "uint256" }
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
var eip2612NoncesAbi = [
|
|
72
|
+
{
|
|
73
|
+
type: "function",
|
|
74
|
+
name: "nonces",
|
|
75
|
+
inputs: [{ name: "owner", type: "address" }],
|
|
76
|
+
outputs: [{ type: "uint256" }],
|
|
77
|
+
stateMutability: "view"
|
|
80
78
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const authorization = {
|
|
93
|
-
from: this.signer.address,
|
|
94
|
-
to: (0, import_viem.getAddress)(selectedV1.payTo),
|
|
95
|
-
value: selectedV1.maxAmountRequired,
|
|
96
|
-
validAfter: (now - 600).toString(),
|
|
97
|
-
// 10 minutes before
|
|
98
|
-
validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),
|
|
99
|
-
nonce
|
|
100
|
-
};
|
|
101
|
-
const signature = await this.signAuthorization(authorization, selectedV1);
|
|
102
|
-
const payload = {
|
|
103
|
-
authorization,
|
|
104
|
-
signature
|
|
105
|
-
};
|
|
106
|
-
return {
|
|
107
|
-
x402Version,
|
|
108
|
-
scheme: selectedV1.scheme,
|
|
109
|
-
network: selectedV1.network,
|
|
110
|
-
payload
|
|
111
|
-
};
|
|
79
|
+
];
|
|
80
|
+
var erc20ApproveAbi = [
|
|
81
|
+
{
|
|
82
|
+
type: "function",
|
|
83
|
+
name: "approve",
|
|
84
|
+
inputs: [
|
|
85
|
+
{ name: "spender", type: "address" },
|
|
86
|
+
{ name: "amount", type: "uint256" }
|
|
87
|
+
],
|
|
88
|
+
outputs: [{ type: "bool" }],
|
|
89
|
+
stateMutability: "nonpayable"
|
|
112
90
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
const { name, version } = requirements.extra;
|
|
128
|
-
const domain = {
|
|
129
|
-
name,
|
|
130
|
-
version,
|
|
131
|
-
chainId,
|
|
132
|
-
verifyingContract: (0, import_viem.getAddress)(requirements.asset)
|
|
133
|
-
};
|
|
134
|
-
const message = {
|
|
135
|
-
from: (0, import_viem.getAddress)(authorization.from),
|
|
136
|
-
to: (0, import_viem.getAddress)(authorization.to),
|
|
137
|
-
value: BigInt(authorization.value),
|
|
138
|
-
validAfter: BigInt(authorization.validAfter),
|
|
139
|
-
validBefore: BigInt(authorization.validBefore),
|
|
140
|
-
nonce: authorization.nonce
|
|
141
|
-
};
|
|
142
|
-
return await this.signer.signTypedData({
|
|
143
|
-
domain,
|
|
144
|
-
types: authorizationTypes,
|
|
145
|
-
primaryType: "TransferWithAuthorization",
|
|
146
|
-
message
|
|
147
|
-
});
|
|
91
|
+
];
|
|
92
|
+
var erc20AllowanceAbi = [
|
|
93
|
+
{
|
|
94
|
+
type: "function",
|
|
95
|
+
name: "allowance",
|
|
96
|
+
inputs: [
|
|
97
|
+
{ name: "owner", type: "address" },
|
|
98
|
+
{ name: "spender", type: "address" }
|
|
99
|
+
],
|
|
100
|
+
outputs: [{ type: "uint256" }],
|
|
101
|
+
stateMutability: "view"
|
|
148
102
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
var
|
|
103
|
+
];
|
|
104
|
+
var ERC20_APPROVE_GAS_LIMIT = 70000n;
|
|
105
|
+
var DEFAULT_MAX_FEE_PER_GAS = 1000000000n;
|
|
106
|
+
var DEFAULT_MAX_PRIORITY_FEE_PER_GAS = 100000000n;
|
|
107
|
+
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
108
|
+
var x402ExactPermit2ProxyAddress = "0x402085c248EeA27D92E8b30b2C58ed07f9E20001";
|
|
153
109
|
|
|
154
|
-
// src/
|
|
155
|
-
var
|
|
156
|
-
ethereum: 1,
|
|
157
|
-
sepolia: 11155111,
|
|
158
|
-
abstract: 2741,
|
|
159
|
-
"abstract-testnet": 11124,
|
|
160
|
-
"base-sepolia": 84532,
|
|
161
|
-
base: 8453,
|
|
162
|
-
"avalanche-fuji": 43113,
|
|
163
|
-
avalanche: 43114,
|
|
164
|
-
iotex: 4689,
|
|
165
|
-
sei: 1329,
|
|
166
|
-
"sei-testnet": 1328,
|
|
167
|
-
polygon: 137,
|
|
168
|
-
"polygon-amoy": 80002,
|
|
169
|
-
peaq: 3338,
|
|
170
|
-
story: 1514,
|
|
171
|
-
educhain: 41923,
|
|
172
|
-
"skale-base-sepolia": 324705682,
|
|
173
|
-
megaeth: 4326
|
|
174
|
-
};
|
|
175
|
-
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
110
|
+
// src/exact/client/scheme.ts
|
|
111
|
+
var import_viem6 = require("viem");
|
|
176
112
|
|
|
177
113
|
// src/utils.ts
|
|
114
|
+
var import_viem = require("viem");
|
|
178
115
|
function getEvmChainId(network) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
116
|
+
if (network.startsWith("eip155:")) {
|
|
117
|
+
const idStr = network.split(":")[1];
|
|
118
|
+
const chainId = parseInt(idStr, 10);
|
|
119
|
+
if (isNaN(chainId)) {
|
|
120
|
+
throw new Error(`Invalid CAIP-2 chain ID: ${network}`);
|
|
121
|
+
}
|
|
122
|
+
return chainId;
|
|
182
123
|
}
|
|
183
|
-
|
|
124
|
+
throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);
|
|
184
125
|
}
|
|
185
126
|
function getCrypto() {
|
|
186
127
|
const cryptoObj = globalThis.crypto;
|
|
@@ -190,20 +131,21 @@ function getCrypto() {
|
|
|
190
131
|
return cryptoObj;
|
|
191
132
|
}
|
|
192
133
|
function createNonce() {
|
|
193
|
-
return (0,
|
|
134
|
+
return (0, import_viem.toHex)(getCrypto().getRandomValues(new Uint8Array(32)));
|
|
194
135
|
}
|
|
195
136
|
function createPermit2Nonce() {
|
|
196
137
|
const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));
|
|
197
|
-
return BigInt((0,
|
|
138
|
+
return BigInt((0, import_viem.toHex)(randomBytes)).toString();
|
|
198
139
|
}
|
|
199
140
|
|
|
200
141
|
// src/exact/client/eip3009.ts
|
|
142
|
+
var import_viem2 = require("viem");
|
|
201
143
|
async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
202
144
|
const nonce = createNonce();
|
|
203
145
|
const now = Math.floor(Date.now() / 1e3);
|
|
204
146
|
const authorization = {
|
|
205
147
|
from: signer.address,
|
|
206
|
-
to: (0,
|
|
148
|
+
to: (0, import_viem2.getAddress)(paymentRequirements.payTo),
|
|
207
149
|
value: paymentRequirements.amount,
|
|
208
150
|
validAfter: (now - 600).toString(),
|
|
209
151
|
validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
|
|
@@ -220,7 +162,7 @@ async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
|
220
162
|
};
|
|
221
163
|
}
|
|
222
164
|
async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
223
|
-
const chainId =
|
|
165
|
+
const chainId = getEvmChainId(requirements.network);
|
|
224
166
|
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
225
167
|
throw new Error(
|
|
226
168
|
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
@@ -231,11 +173,11 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
231
173
|
name,
|
|
232
174
|
version,
|
|
233
175
|
chainId,
|
|
234
|
-
verifyingContract: (0,
|
|
176
|
+
verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
|
|
235
177
|
};
|
|
236
178
|
const message = {
|
|
237
|
-
from: (0,
|
|
238
|
-
to: (0,
|
|
179
|
+
from: (0, import_viem2.getAddress)(authorization.from),
|
|
180
|
+
to: (0, import_viem2.getAddress)(authorization.to),
|
|
239
181
|
value: BigInt(authorization.value),
|
|
240
182
|
validAfter: BigInt(authorization.validAfter),
|
|
241
183
|
validBefore: BigInt(authorization.validBefore),
|
|
@@ -250,7 +192,7 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
250
192
|
}
|
|
251
193
|
|
|
252
194
|
// src/exact/client/permit2.ts
|
|
253
|
-
var
|
|
195
|
+
var import_viem3 = require("viem");
|
|
254
196
|
var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
255
197
|
async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
256
198
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -260,16 +202,15 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
260
202
|
const permit2Authorization = {
|
|
261
203
|
from: signer.address,
|
|
262
204
|
permitted: {
|
|
263
|
-
token: (0,
|
|
205
|
+
token: (0, import_viem3.getAddress)(paymentRequirements.asset),
|
|
264
206
|
amount: paymentRequirements.amount
|
|
265
207
|
},
|
|
266
208
|
spender: x402ExactPermit2ProxyAddress,
|
|
267
209
|
nonce,
|
|
268
210
|
deadline,
|
|
269
211
|
witness: {
|
|
270
|
-
to: (0,
|
|
271
|
-
validAfter
|
|
272
|
-
extra: "0x"
|
|
212
|
+
to: (0, import_viem3.getAddress)(paymentRequirements.payTo),
|
|
213
|
+
validAfter
|
|
273
214
|
}
|
|
274
215
|
};
|
|
275
216
|
const signature = await signPermit2Authorization(
|
|
@@ -287,7 +228,7 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
287
228
|
};
|
|
288
229
|
}
|
|
289
230
|
async function signPermit2Authorization(signer, permit2Authorization, requirements) {
|
|
290
|
-
const chainId =
|
|
231
|
+
const chainId = getEvmChainId(requirements.network);
|
|
291
232
|
const domain = {
|
|
292
233
|
name: "Permit2",
|
|
293
234
|
chainId,
|
|
@@ -295,16 +236,15 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
295
236
|
};
|
|
296
237
|
const message = {
|
|
297
238
|
permitted: {
|
|
298
|
-
token: (0,
|
|
239
|
+
token: (0, import_viem3.getAddress)(permit2Authorization.permitted.token),
|
|
299
240
|
amount: BigInt(permit2Authorization.permitted.amount)
|
|
300
241
|
},
|
|
301
|
-
spender: (0,
|
|
242
|
+
spender: (0, import_viem3.getAddress)(permit2Authorization.spender),
|
|
302
243
|
nonce: BigInt(permit2Authorization.nonce),
|
|
303
244
|
deadline: BigInt(permit2Authorization.deadline),
|
|
304
245
|
witness: {
|
|
305
|
-
to: (0,
|
|
306
|
-
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
307
|
-
extra: permit2Authorization.witness.extra
|
|
246
|
+
to: (0, import_viem3.getAddress)(permit2Authorization.witness.to),
|
|
247
|
+
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
308
248
|
}
|
|
309
249
|
};
|
|
310
250
|
return await signer.signTypedData({
|
|
@@ -314,47 +254,107 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
314
254
|
message
|
|
315
255
|
});
|
|
316
256
|
}
|
|
317
|
-
var erc20ApproveAbi = [
|
|
318
|
-
{
|
|
319
|
-
type: "function",
|
|
320
|
-
name: "approve",
|
|
321
|
-
inputs: [
|
|
322
|
-
{ name: "spender", type: "address" },
|
|
323
|
-
{ name: "amount", type: "uint256" }
|
|
324
|
-
],
|
|
325
|
-
outputs: [{ type: "bool" }],
|
|
326
|
-
stateMutability: "nonpayable"
|
|
327
|
-
}
|
|
328
|
-
];
|
|
329
|
-
var erc20AllowanceAbi = [
|
|
330
|
-
{
|
|
331
|
-
type: "function",
|
|
332
|
-
name: "allowance",
|
|
333
|
-
inputs: [
|
|
334
|
-
{ name: "owner", type: "address" },
|
|
335
|
-
{ name: "spender", type: "address" }
|
|
336
|
-
],
|
|
337
|
-
outputs: [{ type: "uint256" }],
|
|
338
|
-
stateMutability: "view"
|
|
339
|
-
}
|
|
340
|
-
];
|
|
341
257
|
function createPermit2ApprovalTx(tokenAddress) {
|
|
342
|
-
const data = (0,
|
|
258
|
+
const data = (0, import_viem3.encodeFunctionData)({
|
|
343
259
|
abi: erc20ApproveAbi,
|
|
344
260
|
functionName: "approve",
|
|
345
261
|
args: [PERMIT2_ADDRESS, MAX_UINT256]
|
|
346
262
|
});
|
|
347
263
|
return {
|
|
348
|
-
to: (0,
|
|
264
|
+
to: (0, import_viem3.getAddress)(tokenAddress),
|
|
349
265
|
data
|
|
350
266
|
};
|
|
351
267
|
}
|
|
352
268
|
function getPermit2AllowanceReadParams(params) {
|
|
353
269
|
return {
|
|
354
|
-
address: (0,
|
|
270
|
+
address: (0, import_viem3.getAddress)(params.tokenAddress),
|
|
355
271
|
abi: erc20AllowanceAbi,
|
|
356
272
|
functionName: "allowance",
|
|
357
|
-
args: [(0,
|
|
273
|
+
args: [(0, import_viem3.getAddress)(params.ownerAddress), PERMIT2_ADDRESS]
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/exact/client/eip2612.ts
|
|
278
|
+
var import_viem4 = require("viem");
|
|
279
|
+
async function signEip2612Permit(signer, tokenAddress, tokenName, tokenVersion, chainId, deadline, permittedAmount) {
|
|
280
|
+
const owner = signer.address;
|
|
281
|
+
const spender = (0, import_viem4.getAddress)(PERMIT2_ADDRESS);
|
|
282
|
+
const nonce = await signer.readContract({
|
|
283
|
+
address: tokenAddress,
|
|
284
|
+
abi: eip2612NoncesAbi,
|
|
285
|
+
functionName: "nonces",
|
|
286
|
+
args: [owner]
|
|
287
|
+
});
|
|
288
|
+
const domain = {
|
|
289
|
+
name: tokenName,
|
|
290
|
+
version: tokenVersion,
|
|
291
|
+
chainId,
|
|
292
|
+
verifyingContract: tokenAddress
|
|
293
|
+
};
|
|
294
|
+
const approvalAmount = BigInt(permittedAmount);
|
|
295
|
+
const message = {
|
|
296
|
+
owner,
|
|
297
|
+
spender,
|
|
298
|
+
value: approvalAmount,
|
|
299
|
+
nonce,
|
|
300
|
+
deadline: BigInt(deadline)
|
|
301
|
+
};
|
|
302
|
+
const signature = await signer.signTypedData({
|
|
303
|
+
domain,
|
|
304
|
+
types: eip2612PermitTypes,
|
|
305
|
+
primaryType: "Permit",
|
|
306
|
+
message
|
|
307
|
+
});
|
|
308
|
+
return {
|
|
309
|
+
from: owner,
|
|
310
|
+
asset: tokenAddress,
|
|
311
|
+
spender,
|
|
312
|
+
amount: approvalAmount.toString(),
|
|
313
|
+
nonce: nonce.toString(),
|
|
314
|
+
deadline,
|
|
315
|
+
signature,
|
|
316
|
+
version: "1"
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/exact/client/erc20approval.ts
|
|
321
|
+
var import_viem5 = require("viem");
|
|
322
|
+
var import_extensions = require("@x402/extensions");
|
|
323
|
+
async function signErc20ApprovalTransaction(signer, tokenAddress, chainId) {
|
|
324
|
+
const from = signer.address;
|
|
325
|
+
const spender = (0, import_viem5.getAddress)(PERMIT2_ADDRESS);
|
|
326
|
+
const data = (0, import_viem5.encodeFunctionData)({
|
|
327
|
+
abi: erc20ApproveAbi,
|
|
328
|
+
functionName: "approve",
|
|
329
|
+
args: [spender, import_viem5.maxUint256]
|
|
330
|
+
});
|
|
331
|
+
const nonce = await signer.getTransactionCount({ address: from });
|
|
332
|
+
let maxFeePerGas;
|
|
333
|
+
let maxPriorityFeePerGas;
|
|
334
|
+
try {
|
|
335
|
+
const fees = await signer.estimateFeesPerGas();
|
|
336
|
+
maxFeePerGas = fees.maxFeePerGas;
|
|
337
|
+
maxPriorityFeePerGas = fees.maxPriorityFeePerGas;
|
|
338
|
+
} catch {
|
|
339
|
+
maxFeePerGas = DEFAULT_MAX_FEE_PER_GAS;
|
|
340
|
+
maxPriorityFeePerGas = DEFAULT_MAX_PRIORITY_FEE_PER_GAS;
|
|
341
|
+
}
|
|
342
|
+
const signedTransaction = await signer.signTransaction({
|
|
343
|
+
to: tokenAddress,
|
|
344
|
+
data,
|
|
345
|
+
nonce,
|
|
346
|
+
gas: ERC20_APPROVE_GAS_LIMIT,
|
|
347
|
+
maxFeePerGas,
|
|
348
|
+
maxPriorityFeePerGas,
|
|
349
|
+
chainId
|
|
350
|
+
});
|
|
351
|
+
return {
|
|
352
|
+
from,
|
|
353
|
+
asset: tokenAddress,
|
|
354
|
+
spender,
|
|
355
|
+
amount: import_viem5.maxUint256.toString(),
|
|
356
|
+
signedTransaction,
|
|
357
|
+
version: import_extensions.ERC20_APPROVAL_GAS_SPONSORING_VERSION
|
|
358
358
|
};
|
|
359
359
|
}
|
|
360
360
|
|
|
@@ -363,7 +363,9 @@ var ExactEvmScheme = class {
|
|
|
363
363
|
/**
|
|
364
364
|
* Creates a new ExactEvmClient instance.
|
|
365
365
|
*
|
|
366
|
-
* @param signer - The EVM signer for client operations
|
|
366
|
+
* @param signer - The EVM signer for client operations.
|
|
367
|
+
* Must support `readContract` for EIP-2612 gas sponsoring.
|
|
368
|
+
* Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`.
|
|
367
369
|
*/
|
|
368
370
|
constructor(signer) {
|
|
369
371
|
this.signer = signer;
|
|
@@ -373,27 +375,268 @@ var ExactEvmScheme = class {
|
|
|
373
375
|
* Creates a payment payload for the Exact scheme.
|
|
374
376
|
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
|
|
375
377
|
*
|
|
378
|
+
* For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the
|
|
379
|
+
* signer supports `readContract`, automatically signs an EIP-2612 permit
|
|
380
|
+
* when Permit2 allowance is insufficient.
|
|
381
|
+
*
|
|
376
382
|
* @param x402Version - The x402 protocol version
|
|
377
383
|
* @param paymentRequirements - The payment requirements
|
|
378
|
-
* @
|
|
384
|
+
* @param context - Optional context with server-declared extensions
|
|
385
|
+
* @returns Promise resolving to a payment payload result (with optional extensions)
|
|
379
386
|
*/
|
|
380
|
-
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
387
|
+
async createPaymentPayload(x402Version, paymentRequirements, context) {
|
|
381
388
|
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
|
|
382
389
|
if (assetTransferMethod === "permit2") {
|
|
383
|
-
|
|
390
|
+
const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);
|
|
391
|
+
const eip2612Extensions = await this.trySignEip2612Permit(
|
|
392
|
+
paymentRequirements,
|
|
393
|
+
result,
|
|
394
|
+
context
|
|
395
|
+
);
|
|
396
|
+
if (eip2612Extensions) {
|
|
397
|
+
return {
|
|
398
|
+
...result,
|
|
399
|
+
extensions: eip2612Extensions
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
const erc20Extensions = await this.trySignErc20Approval(paymentRequirements, result, context);
|
|
403
|
+
if (erc20Extensions) {
|
|
404
|
+
return {
|
|
405
|
+
...result,
|
|
406
|
+
extensions: erc20Extensions
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return result;
|
|
384
410
|
}
|
|
385
411
|
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
|
|
386
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Attempts to sign an EIP-2612 permit for gasless Permit2 approval.
|
|
415
|
+
*
|
|
416
|
+
* Returns extension data if:
|
|
417
|
+
* 1. Server advertises eip2612GasSponsoring
|
|
418
|
+
* 2. Signer has readContract capability
|
|
419
|
+
* 3. Current Permit2 allowance is insufficient
|
|
420
|
+
*
|
|
421
|
+
* Returns undefined if the extension should not be used.
|
|
422
|
+
*
|
|
423
|
+
* @param requirements - The payment requirements from the server
|
|
424
|
+
* @param result - The payment payload result from the scheme
|
|
425
|
+
* @param context - Optional context containing server extensions and metadata
|
|
426
|
+
* @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable
|
|
427
|
+
*/
|
|
428
|
+
async trySignEip2612Permit(requirements, result, context) {
|
|
429
|
+
if (!context?.extensions?.[import_extensions2.EIP2612_GAS_SPONSORING.key]) {
|
|
430
|
+
return void 0;
|
|
431
|
+
}
|
|
432
|
+
const tokenName = requirements.extra?.name;
|
|
433
|
+
const tokenVersion = requirements.extra?.version;
|
|
434
|
+
if (!tokenName || !tokenVersion) {
|
|
435
|
+
return void 0;
|
|
436
|
+
}
|
|
437
|
+
const chainId = getEvmChainId(requirements.network);
|
|
438
|
+
const tokenAddress = (0, import_viem6.getAddress)(requirements.asset);
|
|
439
|
+
try {
|
|
440
|
+
const allowance = await this.signer.readContract({
|
|
441
|
+
address: tokenAddress,
|
|
442
|
+
abi: erc20AllowanceAbi,
|
|
443
|
+
functionName: "allowance",
|
|
444
|
+
args: [this.signer.address, PERMIT2_ADDRESS]
|
|
445
|
+
});
|
|
446
|
+
if (allowance >= BigInt(requirements.amount)) {
|
|
447
|
+
return void 0;
|
|
448
|
+
}
|
|
449
|
+
} catch {
|
|
450
|
+
}
|
|
451
|
+
const permit2Auth = result.payload?.permit2Authorization;
|
|
452
|
+
const deadline = permit2Auth?.deadline ?? Math.floor(Date.now() / 1e3 + requirements.maxTimeoutSeconds).toString();
|
|
453
|
+
const info = await signEip2612Permit(
|
|
454
|
+
this.signer,
|
|
455
|
+
tokenAddress,
|
|
456
|
+
tokenName,
|
|
457
|
+
tokenVersion,
|
|
458
|
+
chainId,
|
|
459
|
+
deadline,
|
|
460
|
+
requirements.amount
|
|
461
|
+
);
|
|
462
|
+
return {
|
|
463
|
+
[import_extensions2.EIP2612_GAS_SPONSORING.key]: { info }
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Attempts to sign an ERC-20 approval transaction for gasless Permit2 approval.
|
|
468
|
+
*
|
|
469
|
+
* This is the fallback path when the token does not support EIP-2612. The client
|
|
470
|
+
* signs (but does not broadcast) a raw `approve(Permit2, MaxUint256)` transaction.
|
|
471
|
+
* The facilitator broadcasts it atomically before settling.
|
|
472
|
+
*
|
|
473
|
+
* Returns extension data if:
|
|
474
|
+
* 1. Server advertises erc20ApprovalGasSponsoring
|
|
475
|
+
* 2. Signer has signTransaction + getTransactionCount capabilities
|
|
476
|
+
* 3. Current Permit2 allowance is insufficient
|
|
477
|
+
*
|
|
478
|
+
* Returns undefined if the extension should not be used.
|
|
479
|
+
*
|
|
480
|
+
* @param requirements - The payment requirements from the server
|
|
481
|
+
* @param _result - The payment payload result from the scheme (unused)
|
|
482
|
+
* @param context - Optional context containing server extensions and metadata
|
|
483
|
+
* @returns Extension data for ERC-20 approval gas sponsoring, or undefined if not applicable
|
|
484
|
+
*/
|
|
485
|
+
async trySignErc20Approval(requirements, _result, context) {
|
|
486
|
+
if (!context?.extensions?.[import_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key]) {
|
|
487
|
+
return void 0;
|
|
488
|
+
}
|
|
489
|
+
if (!this.signer.signTransaction || !this.signer.getTransactionCount) {
|
|
490
|
+
return void 0;
|
|
491
|
+
}
|
|
492
|
+
const chainId = getEvmChainId(requirements.network);
|
|
493
|
+
const tokenAddress = (0, import_viem6.getAddress)(requirements.asset);
|
|
494
|
+
try {
|
|
495
|
+
const allowance = await this.signer.readContract({
|
|
496
|
+
address: tokenAddress,
|
|
497
|
+
abi: erc20AllowanceAbi,
|
|
498
|
+
functionName: "allowance",
|
|
499
|
+
args: [this.signer.address, PERMIT2_ADDRESS]
|
|
500
|
+
});
|
|
501
|
+
if (allowance >= BigInt(requirements.amount)) {
|
|
502
|
+
return void 0;
|
|
503
|
+
}
|
|
504
|
+
} catch {
|
|
505
|
+
}
|
|
506
|
+
const info = await signErc20ApprovalTransaction(this.signer, tokenAddress, chainId);
|
|
507
|
+
return {
|
|
508
|
+
[import_extensions2.ERC20_APPROVAL_GAS_SPONSORING.key]: { info }
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
// src/exact/v1/client/scheme.ts
|
|
514
|
+
var import_viem8 = require("viem");
|
|
515
|
+
|
|
516
|
+
// src/exact/v1/facilitator/scheme.ts
|
|
517
|
+
var import_viem7 = require("viem");
|
|
518
|
+
|
|
519
|
+
// src/v1/index.ts
|
|
520
|
+
var EVM_NETWORK_CHAIN_ID_MAP = {
|
|
521
|
+
ethereum: 1,
|
|
522
|
+
sepolia: 11155111,
|
|
523
|
+
abstract: 2741,
|
|
524
|
+
"abstract-testnet": 11124,
|
|
525
|
+
"base-sepolia": 84532,
|
|
526
|
+
base: 8453,
|
|
527
|
+
"avalanche-fuji": 43113,
|
|
528
|
+
avalanche: 43114,
|
|
529
|
+
iotex: 4689,
|
|
530
|
+
sei: 1329,
|
|
531
|
+
"sei-testnet": 1328,
|
|
532
|
+
polygon: 137,
|
|
533
|
+
"polygon-amoy": 80002,
|
|
534
|
+
peaq: 3338,
|
|
535
|
+
story: 1514,
|
|
536
|
+
educhain: 41923,
|
|
537
|
+
"skale-base-sepolia": 324705682,
|
|
538
|
+
megaeth: 4326,
|
|
539
|
+
monad: 143
|
|
540
|
+
};
|
|
541
|
+
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
542
|
+
function getEvmChainIdV1(network) {
|
|
543
|
+
const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
|
|
544
|
+
if (!chainId) {
|
|
545
|
+
throw new Error(`Unsupported v1 network: ${network}`);
|
|
546
|
+
}
|
|
547
|
+
return chainId;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// src/exact/v1/client/scheme.ts
|
|
551
|
+
var ExactEvmSchemeV1 = class {
|
|
552
|
+
/**
|
|
553
|
+
* Creates a new ExactEvmClientV1 instance.
|
|
554
|
+
*
|
|
555
|
+
* @param signer - The EVM signer for client operations
|
|
556
|
+
*/
|
|
557
|
+
constructor(signer) {
|
|
558
|
+
this.signer = signer;
|
|
559
|
+
this.scheme = "exact";
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Creates a payment payload for the Exact scheme (V1).
|
|
563
|
+
*
|
|
564
|
+
* @param x402Version - The x402 protocol version
|
|
565
|
+
* @param paymentRequirements - The payment requirements
|
|
566
|
+
* @returns Promise resolving to a payment payload
|
|
567
|
+
*/
|
|
568
|
+
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
569
|
+
const selectedV1 = paymentRequirements;
|
|
570
|
+
const nonce = createNonce();
|
|
571
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
572
|
+
const authorization = {
|
|
573
|
+
from: this.signer.address,
|
|
574
|
+
to: (0, import_viem8.getAddress)(selectedV1.payTo),
|
|
575
|
+
value: selectedV1.maxAmountRequired,
|
|
576
|
+
validAfter: (now - 600).toString(),
|
|
577
|
+
// 10 minutes before
|
|
578
|
+
validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),
|
|
579
|
+
nonce
|
|
580
|
+
};
|
|
581
|
+
const signature = await this.signAuthorization(authorization, selectedV1);
|
|
582
|
+
const payload = {
|
|
583
|
+
authorization,
|
|
584
|
+
signature
|
|
585
|
+
};
|
|
586
|
+
return {
|
|
587
|
+
x402Version,
|
|
588
|
+
scheme: selectedV1.scheme,
|
|
589
|
+
network: selectedV1.network,
|
|
590
|
+
payload
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Sign the EIP-3009 authorization using EIP-712
|
|
595
|
+
*
|
|
596
|
+
* @param authorization - The authorization to sign
|
|
597
|
+
* @param requirements - The payment requirements
|
|
598
|
+
* @returns Promise resolving to the signature
|
|
599
|
+
*/
|
|
600
|
+
async signAuthorization(authorization, requirements) {
|
|
601
|
+
const chainId = getEvmChainIdV1(requirements.network);
|
|
602
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
603
|
+
throw new Error(
|
|
604
|
+
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
const { name, version } = requirements.extra;
|
|
608
|
+
const domain = {
|
|
609
|
+
name,
|
|
610
|
+
version,
|
|
611
|
+
chainId,
|
|
612
|
+
verifyingContract: (0, import_viem8.getAddress)(requirements.asset)
|
|
613
|
+
};
|
|
614
|
+
const message = {
|
|
615
|
+
from: (0, import_viem8.getAddress)(authorization.from),
|
|
616
|
+
to: (0, import_viem8.getAddress)(authorization.to),
|
|
617
|
+
value: BigInt(authorization.value),
|
|
618
|
+
validAfter: BigInt(authorization.validAfter),
|
|
619
|
+
validBefore: BigInt(authorization.validBefore),
|
|
620
|
+
nonce: authorization.nonce
|
|
621
|
+
};
|
|
622
|
+
return await this.signer.signTypedData({
|
|
623
|
+
domain,
|
|
624
|
+
types: authorizationTypes,
|
|
625
|
+
primaryType: "TransferWithAuthorization",
|
|
626
|
+
message
|
|
627
|
+
});
|
|
628
|
+
}
|
|
387
629
|
};
|
|
388
630
|
|
|
389
631
|
// src/exact/client/register.ts
|
|
390
632
|
function registerExactEvmScheme(client, config) {
|
|
633
|
+
const evmScheme = new ExactEvmScheme(config.signer);
|
|
391
634
|
if (config.networks && config.networks.length > 0) {
|
|
392
635
|
config.networks.forEach((network) => {
|
|
393
|
-
client.register(network,
|
|
636
|
+
client.register(network, evmScheme);
|
|
394
637
|
});
|
|
395
638
|
} else {
|
|
396
|
-
client.register("eip155:*",
|
|
639
|
+
client.register("eip155:*", evmScheme);
|
|
397
640
|
}
|
|
398
641
|
NETWORKS.forEach((network) => {
|
|
399
642
|
client.registerV1(network, new ExactEvmSchemeV1(config.signer));
|