@bankofai/x402-evm 2.6.0-beta.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/README.md +184 -0
- package/dist/cjs/exact/client/index.d.ts +53 -0
- package/dist/cjs/exact/client/index.js +661 -0
- package/dist/cjs/exact/client/index.js.map +1 -0
- package/dist/cjs/exact/facilitator/index.d.ts +121 -0
- package/dist/cjs/exact/facilitator/index.js +1458 -0
- package/dist/cjs/exact/facilitator/index.js.map +1 -0
- package/dist/cjs/exact/server/index.d.ts +125 -0
- package/dist/cjs/exact/server/index.js +229 -0
- package/dist/cjs/exact/server/index.js.map +1 -0
- package/dist/cjs/exact/v1/client/index.d.ts +37 -0
- package/dist/cjs/exact/v1/client/index.js +175 -0
- package/dist/cjs/exact/v1/client/index.js.map +1 -0
- package/dist/cjs/exact/v1/facilitator/index.d.ts +62 -0
- package/dist/cjs/exact/v1/facilitator/index.js +436 -0
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -0
- package/dist/cjs/exact_permit/client/index.d.ts +57 -0
- package/dist/cjs/exact_permit/client/index.js +223 -0
- package/dist/cjs/exact_permit/client/index.js.map +1 -0
- package/dist/cjs/exact_permit/facilitator/index.d.ts +82 -0
- package/dist/cjs/exact_permit/facilitator/index.js +437 -0
- package/dist/cjs/exact_permit/facilitator/index.js.map +1 -0
- package/dist/cjs/exact_permit/server/index.d.ts +71 -0
- package/dist/cjs/exact_permit/server/index.js +186 -0
- package/dist/cjs/exact_permit/server/index.js.map +1 -0
- package/dist/cjs/index.d.ts +76 -0
- package/dist/cjs/index.js +779 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/permit2-CpuKY2-F.d.ts +509 -0
- package/dist/cjs/permit2-D65OQ5yU.d.ts +517 -0
- package/dist/cjs/permit2-DvsTlAyj.d.ts +531 -0
- package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
- package/dist/cjs/v1/index.d.ts +39 -0
- package/dist/cjs/v1/index.js +181 -0
- package/dist/cjs/v1/index.js.map +1 -0
- package/dist/esm/chunk-4JGB4GDD.mjs +425 -0
- package/dist/esm/chunk-4JGB4GDD.mjs.map +1 -0
- package/dist/esm/chunk-TKN5V2BV.mjs +13 -0
- package/dist/esm/chunk-TKN5V2BV.mjs.map +1 -0
- package/dist/esm/chunk-UDKSVWSE.mjs +716 -0
- package/dist/esm/chunk-UDKSVWSE.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +53 -0
- package/dist/esm/exact/client/index.mjs +17 -0
- package/dist/esm/exact/client/index.mjs.map +1 -0
- package/dist/esm/exact/facilitator/index.d.mts +121 -0
- package/dist/esm/exact/facilitator/index.mjs +876 -0
- package/dist/esm/exact/facilitator/index.mjs.map +1 -0
- package/dist/esm/exact/server/index.d.mts +125 -0
- package/dist/esm/exact/server/index.mjs +201 -0
- package/dist/esm/exact/server/index.mjs.map +1 -0
- package/dist/esm/exact/v1/client/index.d.mts +37 -0
- package/dist/esm/exact/v1/client/index.mjs +7 -0
- package/dist/esm/exact/v1/client/index.mjs.map +1 -0
- package/dist/esm/exact/v1/facilitator/index.d.mts +62 -0
- package/dist/esm/exact/v1/facilitator/index.mjs +7 -0
- package/dist/esm/exact/v1/facilitator/index.mjs.map +1 -0
- package/dist/esm/index.d.mts +76 -0
- package/dist/esm/index.mjs +71 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/permit2-D7ni3g6s.d.mts +509 -0
- package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
- package/dist/esm/v1/index.d.mts +39 -0
- package/dist/esm/v1/index.mjs +13 -0
- package/dist/esm/v1/index.mjs.map +1 -0
- package/package.json +128 -0
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/exact/client/index.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
ExactEvmScheme: () => ExactEvmScheme,
|
|
24
|
+
createPermit2ApprovalTx: () => createPermit2ApprovalTx,
|
|
25
|
+
erc20AllowanceAbi: () => erc20AllowanceAbi,
|
|
26
|
+
getPermit2AllowanceReadParams: () => getPermit2AllowanceReadParams,
|
|
27
|
+
registerExactEvmScheme: () => registerExactEvmScheme
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(client_exports);
|
|
30
|
+
|
|
31
|
+
// src/exact/client/scheme.ts
|
|
32
|
+
var import_x402_extensions2 = require("@bankofai/x402-extensions");
|
|
33
|
+
|
|
34
|
+
// src/constants.ts
|
|
35
|
+
var authorizationTypes = {
|
|
36
|
+
TransferWithAuthorization: [
|
|
37
|
+
{ name: "from", type: "address" },
|
|
38
|
+
{ name: "to", type: "address" },
|
|
39
|
+
{ name: "value", type: "uint256" },
|
|
40
|
+
{ name: "validAfter", type: "uint256" },
|
|
41
|
+
{ name: "validBefore", type: "uint256" },
|
|
42
|
+
{ name: "nonce", type: "bytes32" }
|
|
43
|
+
]
|
|
44
|
+
};
|
|
45
|
+
var permit2WitnessTypes = {
|
|
46
|
+
PermitWitnessTransferFrom: [
|
|
47
|
+
{ name: "permitted", type: "TokenPermissions" },
|
|
48
|
+
{ name: "spender", type: "address" },
|
|
49
|
+
{ name: "nonce", type: "uint256" },
|
|
50
|
+
{ name: "deadline", type: "uint256" },
|
|
51
|
+
{ name: "witness", type: "Witness" }
|
|
52
|
+
],
|
|
53
|
+
TokenPermissions: [
|
|
54
|
+
{ name: "token", type: "address" },
|
|
55
|
+
{ name: "amount", type: "uint256" }
|
|
56
|
+
],
|
|
57
|
+
Witness: [
|
|
58
|
+
{ name: "to", type: "address" },
|
|
59
|
+
{ name: "validAfter", type: "uint256" }
|
|
60
|
+
]
|
|
61
|
+
};
|
|
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"
|
|
78
|
+
}
|
|
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"
|
|
90
|
+
}
|
|
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"
|
|
102
|
+
}
|
|
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 = "0xEe38Ec718255fe78e9D16aCC0e1183C731679b23";
|
|
109
|
+
|
|
110
|
+
// src/exact/client/scheme.ts
|
|
111
|
+
var import_viem6 = require("viem");
|
|
112
|
+
|
|
113
|
+
// src/utils.ts
|
|
114
|
+
var import_viem = require("viem");
|
|
115
|
+
function getEvmChainId(network) {
|
|
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;
|
|
123
|
+
}
|
|
124
|
+
throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);
|
|
125
|
+
}
|
|
126
|
+
function getCrypto() {
|
|
127
|
+
const cryptoObj = globalThis.crypto;
|
|
128
|
+
if (!cryptoObj) {
|
|
129
|
+
throw new Error("Crypto API not available");
|
|
130
|
+
}
|
|
131
|
+
return cryptoObj;
|
|
132
|
+
}
|
|
133
|
+
function createNonce() {
|
|
134
|
+
return (0, import_viem.toHex)(getCrypto().getRandomValues(new Uint8Array(32)));
|
|
135
|
+
}
|
|
136
|
+
function createPermit2Nonce() {
|
|
137
|
+
const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));
|
|
138
|
+
return BigInt((0, import_viem.toHex)(randomBytes)).toString();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/exact/client/eip3009.ts
|
|
142
|
+
var import_viem2 = require("viem");
|
|
143
|
+
async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
144
|
+
const nonce = createNonce();
|
|
145
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
146
|
+
const authorization = {
|
|
147
|
+
from: signer.address,
|
|
148
|
+
to: (0, import_viem2.getAddress)(paymentRequirements.payTo),
|
|
149
|
+
value: paymentRequirements.amount,
|
|
150
|
+
validAfter: (now - 600).toString(),
|
|
151
|
+
validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
|
|
152
|
+
nonce
|
|
153
|
+
};
|
|
154
|
+
const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements);
|
|
155
|
+
const payload = {
|
|
156
|
+
authorization,
|
|
157
|
+
signature
|
|
158
|
+
};
|
|
159
|
+
return {
|
|
160
|
+
x402Version,
|
|
161
|
+
payload
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
165
|
+
const chainId = getEvmChainId(requirements.network);
|
|
166
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
const { name, version } = requirements.extra;
|
|
172
|
+
const domain = {
|
|
173
|
+
name,
|
|
174
|
+
version,
|
|
175
|
+
chainId,
|
|
176
|
+
verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
|
|
177
|
+
};
|
|
178
|
+
const message = {
|
|
179
|
+
from: (0, import_viem2.getAddress)(authorization.from),
|
|
180
|
+
to: (0, import_viem2.getAddress)(authorization.to),
|
|
181
|
+
value: BigInt(authorization.value),
|
|
182
|
+
validAfter: BigInt(authorization.validAfter),
|
|
183
|
+
validBefore: BigInt(authorization.validBefore),
|
|
184
|
+
nonce: authorization.nonce
|
|
185
|
+
};
|
|
186
|
+
return await signer.signTypedData({
|
|
187
|
+
domain,
|
|
188
|
+
types: authorizationTypes,
|
|
189
|
+
primaryType: "TransferWithAuthorization",
|
|
190
|
+
message
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// src/exact/client/permit2.ts
|
|
195
|
+
var import_viem3 = require("viem");
|
|
196
|
+
var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
|
197
|
+
async function createPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
198
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
199
|
+
const nonce = createPermit2Nonce();
|
|
200
|
+
const validAfter = (now - 600).toString();
|
|
201
|
+
const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();
|
|
202
|
+
const permit2Authorization = {
|
|
203
|
+
from: signer.address,
|
|
204
|
+
permitted: {
|
|
205
|
+
token: (0, import_viem3.getAddress)(paymentRequirements.asset),
|
|
206
|
+
amount: paymentRequirements.amount
|
|
207
|
+
},
|
|
208
|
+
spender: x402ExactPermit2ProxyAddress,
|
|
209
|
+
nonce,
|
|
210
|
+
deadline,
|
|
211
|
+
witness: {
|
|
212
|
+
to: (0, import_viem3.getAddress)(paymentRequirements.payTo),
|
|
213
|
+
validAfter
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const signature = await signPermit2Authorization(
|
|
217
|
+
signer,
|
|
218
|
+
permit2Authorization,
|
|
219
|
+
paymentRequirements
|
|
220
|
+
);
|
|
221
|
+
const payload = {
|
|
222
|
+
signature,
|
|
223
|
+
permit2Authorization
|
|
224
|
+
};
|
|
225
|
+
return {
|
|
226
|
+
x402Version,
|
|
227
|
+
payload
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
async function signPermit2Authorization(signer, permit2Authorization, requirements) {
|
|
231
|
+
const chainId = getEvmChainId(requirements.network);
|
|
232
|
+
const domain = {
|
|
233
|
+
name: "Permit2",
|
|
234
|
+
chainId,
|
|
235
|
+
verifyingContract: PERMIT2_ADDRESS
|
|
236
|
+
};
|
|
237
|
+
const message = {
|
|
238
|
+
permitted: {
|
|
239
|
+
token: (0, import_viem3.getAddress)(permit2Authorization.permitted.token),
|
|
240
|
+
amount: BigInt(permit2Authorization.permitted.amount)
|
|
241
|
+
},
|
|
242
|
+
spender: (0, import_viem3.getAddress)(permit2Authorization.spender),
|
|
243
|
+
nonce: BigInt(permit2Authorization.nonce),
|
|
244
|
+
deadline: BigInt(permit2Authorization.deadline),
|
|
245
|
+
witness: {
|
|
246
|
+
to: (0, import_viem3.getAddress)(permit2Authorization.witness.to),
|
|
247
|
+
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
return await signer.signTypedData({
|
|
251
|
+
domain,
|
|
252
|
+
types: permit2WitnessTypes,
|
|
253
|
+
primaryType: "PermitWitnessTransferFrom",
|
|
254
|
+
message
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function createPermit2ApprovalTx(tokenAddress) {
|
|
258
|
+
const data = (0, import_viem3.encodeFunctionData)({
|
|
259
|
+
abi: erc20ApproveAbi,
|
|
260
|
+
functionName: "approve",
|
|
261
|
+
args: [PERMIT2_ADDRESS, MAX_UINT256]
|
|
262
|
+
});
|
|
263
|
+
return {
|
|
264
|
+
to: (0, import_viem3.getAddress)(tokenAddress),
|
|
265
|
+
data
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function getPermit2AllowanceReadParams(params) {
|
|
269
|
+
return {
|
|
270
|
+
address: (0, import_viem3.getAddress)(params.tokenAddress),
|
|
271
|
+
abi: erc20AllowanceAbi,
|
|
272
|
+
functionName: "allowance",
|
|
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_x402_extensions = require("@bankofai/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_x402_extensions.ERC20_APPROVAL_GAS_SPONSORING_VERSION
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/exact/client/scheme.ts
|
|
362
|
+
var ExactEvmScheme = class {
|
|
363
|
+
/**
|
|
364
|
+
* Creates a new ExactEvmClient instance.
|
|
365
|
+
*
|
|
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)`.
|
|
369
|
+
*/
|
|
370
|
+
constructor(signer) {
|
|
371
|
+
this.signer = signer;
|
|
372
|
+
this.scheme = "exact";
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Creates a payment payload for the Exact scheme.
|
|
376
|
+
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
|
|
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
|
+
*
|
|
382
|
+
* @param x402Version - The x402 protocol version
|
|
383
|
+
* @param paymentRequirements - The payment requirements
|
|
384
|
+
* @param context - Optional context with server-declared extensions
|
|
385
|
+
* @returns Promise resolving to a payment payload result (with optional extensions)
|
|
386
|
+
*/
|
|
387
|
+
async createPaymentPayload(x402Version, paymentRequirements, context) {
|
|
388
|
+
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
|
|
389
|
+
if (assetTransferMethod === "permit2") {
|
|
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;
|
|
410
|
+
}
|
|
411
|
+
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
|
|
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_x402_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_x402_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_x402_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_x402_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
|
+
bsc: 56,
|
|
541
|
+
"bsc-testnet": 97
|
|
542
|
+
};
|
|
543
|
+
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
|
|
544
|
+
function getEvmChainIdV1(network) {
|
|
545
|
+
const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
|
|
546
|
+
if (!chainId) {
|
|
547
|
+
throw new Error(`Unsupported v1 network: ${network}`);
|
|
548
|
+
}
|
|
549
|
+
return chainId;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// src/exact/v1/client/scheme.ts
|
|
553
|
+
var ExactEvmSchemeV1 = class {
|
|
554
|
+
/**
|
|
555
|
+
* Creates a new ExactEvmClientV1 instance.
|
|
556
|
+
*
|
|
557
|
+
* @param signer - The EVM signer for client operations
|
|
558
|
+
*/
|
|
559
|
+
constructor(signer) {
|
|
560
|
+
this.signer = signer;
|
|
561
|
+
this.scheme = "exact";
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Creates a payment payload for the Exact scheme (V1).
|
|
565
|
+
*
|
|
566
|
+
* @param x402Version - The x402 protocol version
|
|
567
|
+
* @param paymentRequirements - The payment requirements
|
|
568
|
+
* @returns Promise resolving to a payment payload
|
|
569
|
+
*/
|
|
570
|
+
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
571
|
+
const selectedV1 = paymentRequirements;
|
|
572
|
+
const nonce = createNonce();
|
|
573
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
574
|
+
const authorization = {
|
|
575
|
+
from: this.signer.address,
|
|
576
|
+
to: (0, import_viem8.getAddress)(selectedV1.payTo),
|
|
577
|
+
value: selectedV1.maxAmountRequired,
|
|
578
|
+
validAfter: (now - 600).toString(),
|
|
579
|
+
// 10 minutes before
|
|
580
|
+
validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),
|
|
581
|
+
nonce
|
|
582
|
+
};
|
|
583
|
+
const signature = await this.signAuthorization(authorization, selectedV1);
|
|
584
|
+
const payload = {
|
|
585
|
+
authorization,
|
|
586
|
+
signature
|
|
587
|
+
};
|
|
588
|
+
return {
|
|
589
|
+
x402Version,
|
|
590
|
+
scheme: selectedV1.scheme,
|
|
591
|
+
network: selectedV1.network,
|
|
592
|
+
payload
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Sign the EIP-3009 authorization using EIP-712
|
|
597
|
+
*
|
|
598
|
+
* @param authorization - The authorization to sign
|
|
599
|
+
* @param requirements - The payment requirements
|
|
600
|
+
* @returns Promise resolving to the signature
|
|
601
|
+
*/
|
|
602
|
+
async signAuthorization(authorization, requirements) {
|
|
603
|
+
const chainId = getEvmChainIdV1(requirements.network);
|
|
604
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
605
|
+
throw new Error(
|
|
606
|
+
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
const { name, version } = requirements.extra;
|
|
610
|
+
const domain = {
|
|
611
|
+
name,
|
|
612
|
+
version,
|
|
613
|
+
chainId,
|
|
614
|
+
verifyingContract: (0, import_viem8.getAddress)(requirements.asset)
|
|
615
|
+
};
|
|
616
|
+
const message = {
|
|
617
|
+
from: (0, import_viem8.getAddress)(authorization.from),
|
|
618
|
+
to: (0, import_viem8.getAddress)(authorization.to),
|
|
619
|
+
value: BigInt(authorization.value),
|
|
620
|
+
validAfter: BigInt(authorization.validAfter),
|
|
621
|
+
validBefore: BigInt(authorization.validBefore),
|
|
622
|
+
nonce: authorization.nonce
|
|
623
|
+
};
|
|
624
|
+
return await this.signer.signTypedData({
|
|
625
|
+
domain,
|
|
626
|
+
types: authorizationTypes,
|
|
627
|
+
primaryType: "TransferWithAuthorization",
|
|
628
|
+
message
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
// src/exact/client/register.ts
|
|
634
|
+
function registerExactEvmScheme(client, config) {
|
|
635
|
+
const evmScheme = new ExactEvmScheme(config.signer);
|
|
636
|
+
if (config.networks && config.networks.length > 0) {
|
|
637
|
+
config.networks.forEach((network) => {
|
|
638
|
+
client.register(network, evmScheme);
|
|
639
|
+
});
|
|
640
|
+
} else {
|
|
641
|
+
client.register("eip155:*", evmScheme);
|
|
642
|
+
}
|
|
643
|
+
NETWORKS.forEach((network) => {
|
|
644
|
+
client.registerV1(network, new ExactEvmSchemeV1(config.signer));
|
|
645
|
+
});
|
|
646
|
+
if (config.policies) {
|
|
647
|
+
config.policies.forEach((policy) => {
|
|
648
|
+
client.registerPolicy(policy);
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
return client;
|
|
652
|
+
}
|
|
653
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
654
|
+
0 && (module.exports = {
|
|
655
|
+
ExactEvmScheme,
|
|
656
|
+
createPermit2ApprovalTx,
|
|
657
|
+
erc20AllowanceAbi,
|
|
658
|
+
getPermit2AllowanceReadParams,
|
|
659
|
+
registerExactEvmScheme
|
|
660
|
+
});
|
|
661
|
+
//# sourceMappingURL=index.js.map
|