@payai/x402-evm 2.2.3 → 2.3.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 +3 -3
- package/dist/cjs/exact/client/index.js +412 -168
- 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 +477 -163
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.js +8 -1
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.d.ts +1 -1
- package/dist/cjs/exact/v1/client/index.js +18 -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 +11 -10
- 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 -109
- 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 +12 -2
- package/dist/cjs/v1/index.js +15 -11
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/chunk-LBIJBD7Q.mjs +425 -0
- package/dist/esm/chunk-LBIJBD7Q.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/{chunk-MVERYV34.mjs → chunk-XL6IFXCP.mjs} +96 -39
- package/dist/esm/chunk-XL6IFXCP.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +3 -3
- 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 +407 -103
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.mjs +8 -1
- package/dist/esm/exact/server/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 +12 -2
- package/dist/esm/v1/index.mjs +6 -4
- package/package.json +5 -5
- package/dist/esm/chunk-MVERYV34.mjs.map +0 -1
- package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
- package/dist/esm/chunk-W556LH23.mjs +0 -229
- package/dist/esm/chunk-W556LH23.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,130 +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
|
-
};
|
|
174
|
-
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
110
|
+
// src/exact/client/scheme.ts
|
|
111
|
+
var import_viem6 = require("viem");
|
|
175
112
|
|
|
176
113
|
// src/utils.ts
|
|
114
|
+
var import_viem = require("viem");
|
|
177
115
|
function getEvmChainId(network) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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;
|
|
181
123
|
}
|
|
182
|
-
|
|
124
|
+
throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);
|
|
183
125
|
}
|
|
184
126
|
function getCrypto() {
|
|
185
127
|
const cryptoObj = globalThis.crypto;
|
|
@@ -189,20 +131,21 @@ function getCrypto() {
|
|
|
189
131
|
return cryptoObj;
|
|
190
132
|
}
|
|
191
133
|
function createNonce() {
|
|
192
|
-
return (0,
|
|
134
|
+
return (0, import_viem.toHex)(getCrypto().getRandomValues(new Uint8Array(32)));
|
|
193
135
|
}
|
|
194
136
|
function createPermit2Nonce() {
|
|
195
137
|
const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));
|
|
196
|
-
return BigInt((0,
|
|
138
|
+
return BigInt((0, import_viem.toHex)(randomBytes)).toString();
|
|
197
139
|
}
|
|
198
140
|
|
|
199
141
|
// src/exact/client/eip3009.ts
|
|
142
|
+
var import_viem2 = require("viem");
|
|
200
143
|
async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
201
144
|
const nonce = createNonce();
|
|
202
145
|
const now = Math.floor(Date.now() / 1e3);
|
|
203
146
|
const authorization = {
|
|
204
147
|
from: signer.address,
|
|
205
|
-
to: (0,
|
|
148
|
+
to: (0, import_viem2.getAddress)(paymentRequirements.payTo),
|
|
206
149
|
value: paymentRequirements.amount,
|
|
207
150
|
validAfter: (now - 600).toString(),
|
|
208
151
|
validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
|
|
@@ -219,7 +162,7 @@ async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
|
219
162
|
};
|
|
220
163
|
}
|
|
221
164
|
async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
222
|
-
const chainId =
|
|
165
|
+
const chainId = getEvmChainId(requirements.network);
|
|
223
166
|
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
224
167
|
throw new Error(
|
|
225
168
|
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
@@ -230,11 +173,11 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
230
173
|
name,
|
|
231
174
|
version,
|
|
232
175
|
chainId,
|
|
233
|
-
verifyingContract: (0,
|
|
176
|
+
verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
|
|
234
177
|
};
|
|
235
178
|
const message = {
|
|
236
|
-
from: (0,
|
|
237
|
-
to: (0,
|
|
179
|
+
from: (0, import_viem2.getAddress)(authorization.from),
|
|
180
|
+
to: (0, import_viem2.getAddress)(authorization.to),
|
|
238
181
|
value: BigInt(authorization.value),
|
|
239
182
|
validAfter: BigInt(authorization.validAfter),
|
|
240
183
|
validBefore: BigInt(authorization.validBefore),
|
|
@@ -249,7 +192,7 @@ async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
|
249
192
|
}
|
|
250
193
|
|
|
251
194
|
// src/exact/client/permit2.ts
|
|
252
|
-
var
|
|
195
|
+
var import_viem3 = require("viem");
|
|
253
196
|
var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
254
197
|
async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
255
198
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -259,16 +202,15 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
259
202
|
const permit2Authorization = {
|
|
260
203
|
from: signer.address,
|
|
261
204
|
permitted: {
|
|
262
|
-
token: (0,
|
|
205
|
+
token: (0, import_viem3.getAddress)(paymentRequirements.asset),
|
|
263
206
|
amount: paymentRequirements.amount
|
|
264
207
|
},
|
|
265
208
|
spender: x402ExactPermit2ProxyAddress,
|
|
266
209
|
nonce,
|
|
267
210
|
deadline,
|
|
268
211
|
witness: {
|
|
269
|
-
to: (0,
|
|
270
|
-
validAfter
|
|
271
|
-
extra: "0x"
|
|
212
|
+
to: (0, import_viem3.getAddress)(paymentRequirements.payTo),
|
|
213
|
+
validAfter
|
|
272
214
|
}
|
|
273
215
|
};
|
|
274
216
|
const signature = await signPermit2Authorization(
|
|
@@ -286,7 +228,7 @@ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
|
286
228
|
};
|
|
287
229
|
}
|
|
288
230
|
async function signPermit2Authorization(signer, permit2Authorization, requirements) {
|
|
289
|
-
const chainId =
|
|
231
|
+
const chainId = getEvmChainId(requirements.network);
|
|
290
232
|
const domain = {
|
|
291
233
|
name: "Permit2",
|
|
292
234
|
chainId,
|
|
@@ -294,16 +236,15 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
294
236
|
};
|
|
295
237
|
const message = {
|
|
296
238
|
permitted: {
|
|
297
|
-
token: (0,
|
|
239
|
+
token: (0, import_viem3.getAddress)(permit2Authorization.permitted.token),
|
|
298
240
|
amount: BigInt(permit2Authorization.permitted.amount)
|
|
299
241
|
},
|
|
300
|
-
spender: (0,
|
|
242
|
+
spender: (0, import_viem3.getAddress)(permit2Authorization.spender),
|
|
301
243
|
nonce: BigInt(permit2Authorization.nonce),
|
|
302
244
|
deadline: BigInt(permit2Authorization.deadline),
|
|
303
245
|
witness: {
|
|
304
|
-
to: (0,
|
|
305
|
-
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
306
|
-
extra: permit2Authorization.witness.extra
|
|
246
|
+
to: (0, import_viem3.getAddress)(permit2Authorization.witness.to),
|
|
247
|
+
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
307
248
|
}
|
|
308
249
|
};
|
|
309
250
|
return await signer.signTypedData({
|
|
@@ -313,47 +254,107 @@ async function signPermit2Authorization(signer, permit2Authorization, requiremen
|
|
|
313
254
|
message
|
|
314
255
|
});
|
|
315
256
|
}
|
|
316
|
-
var erc20ApproveAbi = [
|
|
317
|
-
{
|
|
318
|
-
type: "function",
|
|
319
|
-
name: "approve",
|
|
320
|
-
inputs: [
|
|
321
|
-
{ name: "spender", type: "address" },
|
|
322
|
-
{ name: "amount", type: "uint256" }
|
|
323
|
-
],
|
|
324
|
-
outputs: [{ type: "bool" }],
|
|
325
|
-
stateMutability: "nonpayable"
|
|
326
|
-
}
|
|
327
|
-
];
|
|
328
|
-
var erc20AllowanceAbi = [
|
|
329
|
-
{
|
|
330
|
-
type: "function",
|
|
331
|
-
name: "allowance",
|
|
332
|
-
inputs: [
|
|
333
|
-
{ name: "owner", type: "address" },
|
|
334
|
-
{ name: "spender", type: "address" }
|
|
335
|
-
],
|
|
336
|
-
outputs: [{ type: "uint256" }],
|
|
337
|
-
stateMutability: "view"
|
|
338
|
-
}
|
|
339
|
-
];
|
|
340
257
|
function createPermit2ApprovalTx(tokenAddress) {
|
|
341
|
-
const data = (0,
|
|
258
|
+
const data = (0, import_viem3.encodeFunctionData)({
|
|
342
259
|
abi: erc20ApproveAbi,
|
|
343
260
|
functionName: "approve",
|
|
344
261
|
args: [PERMIT2_ADDRESS, MAX_UINT256]
|
|
345
262
|
});
|
|
346
263
|
return {
|
|
347
|
-
to: (0,
|
|
264
|
+
to: (0, import_viem3.getAddress)(tokenAddress),
|
|
348
265
|
data
|
|
349
266
|
};
|
|
350
267
|
}
|
|
351
268
|
function getPermit2AllowanceReadParams(params) {
|
|
352
269
|
return {
|
|
353
|
-
address: (0,
|
|
270
|
+
address: (0, import_viem3.getAddress)(params.tokenAddress),
|
|
354
271
|
abi: erc20AllowanceAbi,
|
|
355
272
|
functionName: "allowance",
|
|
356
|
-
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
|
|
357
358
|
};
|
|
358
359
|
}
|
|
359
360
|
|
|
@@ -362,7 +363,9 @@ var ExactEvmScheme = class {
|
|
|
362
363
|
/**
|
|
363
364
|
* Creates a new ExactEvmClient instance.
|
|
364
365
|
*
|
|
365
|
-
* @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)`.
|
|
366
369
|
*/
|
|
367
370
|
constructor(signer) {
|
|
368
371
|
this.signer = signer;
|
|
@@ -372,27 +375,268 @@ var ExactEvmScheme = class {
|
|
|
372
375
|
* Creates a payment payload for the Exact scheme.
|
|
373
376
|
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
|
|
374
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
|
+
*
|
|
375
382
|
* @param x402Version - The x402 protocol version
|
|
376
383
|
* @param paymentRequirements - The payment requirements
|
|
377
|
-
* @
|
|
384
|
+
* @param context - Optional context with server-declared extensions
|
|
385
|
+
* @returns Promise resolving to a payment payload result (with optional extensions)
|
|
378
386
|
*/
|
|
379
|
-
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
387
|
+
async createPaymentPayload(x402Version, paymentRequirements, context) {
|
|
380
388
|
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
|
|
381
389
|
if (assetTransferMethod === "permit2") {
|
|
382
|
-
|
|
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;
|
|
383
410
|
}
|
|
384
411
|
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
|
|
385
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
|
+
}
|
|
386
629
|
};
|
|
387
630
|
|
|
388
631
|
// src/exact/client/register.ts
|
|
389
632
|
function registerExactEvmScheme(client, config) {
|
|
633
|
+
const evmScheme = new ExactEvmScheme(config.signer);
|
|
390
634
|
if (config.networks && config.networks.length > 0) {
|
|
391
635
|
config.networks.forEach((network) => {
|
|
392
|
-
client.register(network,
|
|
636
|
+
client.register(network, evmScheme);
|
|
393
637
|
});
|
|
394
638
|
} else {
|
|
395
|
-
client.register("eip155:*",
|
|
639
|
+
client.register("eip155:*", evmScheme);
|
|
396
640
|
}
|
|
397
641
|
NETWORKS.forEach((network) => {
|
|
398
642
|
client.registerV1(network, new ExactEvmSchemeV1(config.signer));
|