@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.
Files changed (51) hide show
  1. package/dist/cjs/exact/client/index.d.ts +2 -2
  2. package/dist/cjs/exact/client/index.js +412 -169
  3. package/dist/cjs/exact/client/index.js.map +1 -1
  4. package/dist/cjs/exact/facilitator/index.d.ts +18 -18
  5. package/dist/cjs/exact/facilitator/index.js +467 -157
  6. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  7. package/dist/cjs/exact/v1/client/index.d.ts +1 -1
  8. package/dist/cjs/exact/v1/client/index.js +17 -18
  9. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  10. package/dist/cjs/exact/v1/facilitator/index.d.ts +1 -1
  11. package/dist/cjs/exact/v1/facilitator/index.js +7 -8
  12. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  13. package/dist/cjs/index.d.ts +3 -390
  14. package/dist/cjs/index.js +363 -110
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/permit2-CQbXqCMC.d.ts +517 -0
  17. package/dist/cjs/signer-DC81R8wQ.d.ts +161 -0
  18. package/dist/cjs/v1/index.d.ts +11 -2
  19. package/dist/cjs/v1/index.js +14 -11
  20. package/dist/cjs/v1/index.js.map +1 -1
  21. package/dist/esm/{chunk-RPL6OFJL.mjs → chunk-7KHQD5KT.mjs} +92 -37
  22. package/dist/esm/chunk-7KHQD5KT.mjs.map +1 -0
  23. package/dist/esm/chunk-GY6X5A3G.mjs +425 -0
  24. package/dist/esm/chunk-GY6X5A3G.mjs.map +1 -0
  25. package/dist/esm/{chunk-PFULIQAE.mjs → chunk-TKN5V2BV.mjs} +1 -1
  26. package/dist/esm/chunk-TKN5V2BV.mjs.map +1 -0
  27. package/dist/esm/exact/client/index.d.mts +2 -2
  28. package/dist/esm/exact/client/index.mjs +4 -3
  29. package/dist/esm/exact/facilitator/index.d.mts +18 -18
  30. package/dist/esm/exact/facilitator/index.mjs +401 -99
  31. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  32. package/dist/esm/exact/v1/client/index.d.mts +1 -1
  33. package/dist/esm/exact/v1/client/index.mjs +2 -2
  34. package/dist/esm/exact/v1/facilitator/index.d.mts +1 -1
  35. package/dist/esm/exact/v1/facilitator/index.mjs +2 -2
  36. package/dist/esm/index.d.mts +3 -390
  37. package/dist/esm/index.mjs +29 -6
  38. package/dist/esm/index.mjs.map +1 -1
  39. package/dist/esm/permit2-CGOcN7Et.d.mts +517 -0
  40. package/dist/esm/signer-DC81R8wQ.d.mts +161 -0
  41. package/dist/esm/v1/index.d.mts +11 -2
  42. package/dist/esm/v1/index.mjs +6 -4
  43. package/package.json +3 -2
  44. package/dist/cjs/permit2-BYv82va2.d.ts +0 -103
  45. package/dist/cjs/signer-5OVDxViv.d.ts +0 -79
  46. package/dist/esm/chunk-E2YMUI3X.mjs +0 -229
  47. package/dist/esm/chunk-E2YMUI3X.mjs.map +0 -1
  48. package/dist/esm/chunk-PFULIQAE.mjs.map +0 -1
  49. package/dist/esm/chunk-RPL6OFJL.mjs.map +0 -1
  50. package/dist/esm/permit2-BsAoJiWD.d.mts +0 -103
  51. package/dist/esm/signer-5OVDxViv.d.mts +0 -79
@@ -0,0 +1,425 @@
1
+ import {
2
+ DEFAULT_MAX_FEE_PER_GAS,
3
+ DEFAULT_MAX_PRIORITY_FEE_PER_GAS,
4
+ ERC20_APPROVE_GAS_LIMIT,
5
+ ExactEvmSchemeV12 as ExactEvmSchemeV1,
6
+ NETWORKS,
7
+ PERMIT2_ADDRESS,
8
+ authorizationTypes,
9
+ createNonce,
10
+ createPermit2Nonce,
11
+ eip2612NoncesAbi,
12
+ eip2612PermitTypes,
13
+ erc20AllowanceAbi,
14
+ erc20ApproveAbi,
15
+ getEvmChainId,
16
+ permit2WitnessTypes,
17
+ x402ExactPermit2ProxyAddress
18
+ } from "./chunk-7KHQD5KT.mjs";
19
+
20
+ // src/exact/client/scheme.ts
21
+ import { EIP2612_GAS_SPONSORING, ERC20_APPROVAL_GAS_SPONSORING } from "@x402/extensions";
22
+ import { getAddress as getAddress5 } from "viem";
23
+
24
+ // src/exact/client/eip3009.ts
25
+ import { getAddress } from "viem";
26
+ async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
27
+ const nonce = createNonce();
28
+ const now = Math.floor(Date.now() / 1e3);
29
+ const authorization = {
30
+ from: signer.address,
31
+ to: getAddress(paymentRequirements.payTo),
32
+ value: paymentRequirements.amount,
33
+ validAfter: (now - 600).toString(),
34
+ validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
35
+ nonce
36
+ };
37
+ const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements);
38
+ const payload = {
39
+ authorization,
40
+ signature
41
+ };
42
+ return {
43
+ x402Version,
44
+ payload
45
+ };
46
+ }
47
+ async function signEIP3009Authorization(signer, authorization, requirements) {
48
+ const chainId = getEvmChainId(requirements.network);
49
+ if (!requirements.extra?.name || !requirements.extra?.version) {
50
+ throw new Error(
51
+ `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
52
+ );
53
+ }
54
+ const { name, version } = requirements.extra;
55
+ const domain = {
56
+ name,
57
+ version,
58
+ chainId,
59
+ verifyingContract: getAddress(requirements.asset)
60
+ };
61
+ const message = {
62
+ from: getAddress(authorization.from),
63
+ to: getAddress(authorization.to),
64
+ value: BigInt(authorization.value),
65
+ validAfter: BigInt(authorization.validAfter),
66
+ validBefore: BigInt(authorization.validBefore),
67
+ nonce: authorization.nonce
68
+ };
69
+ return await signer.signTypedData({
70
+ domain,
71
+ types: authorizationTypes,
72
+ primaryType: "TransferWithAuthorization",
73
+ message
74
+ });
75
+ }
76
+
77
+ // src/exact/client/permit2.ts
78
+ import { encodeFunctionData, getAddress as getAddress2 } from "viem";
79
+ var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
80
+ async function createPermit2Payload(signer, x402Version, paymentRequirements) {
81
+ const now = Math.floor(Date.now() / 1e3);
82
+ const nonce = createPermit2Nonce();
83
+ const validAfter = (now - 600).toString();
84
+ const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();
85
+ const permit2Authorization = {
86
+ from: signer.address,
87
+ permitted: {
88
+ token: getAddress2(paymentRequirements.asset),
89
+ amount: paymentRequirements.amount
90
+ },
91
+ spender: x402ExactPermit2ProxyAddress,
92
+ nonce,
93
+ deadline,
94
+ witness: {
95
+ to: getAddress2(paymentRequirements.payTo),
96
+ validAfter
97
+ }
98
+ };
99
+ const signature = await signPermit2Authorization(
100
+ signer,
101
+ permit2Authorization,
102
+ paymentRequirements
103
+ );
104
+ const payload = {
105
+ signature,
106
+ permit2Authorization
107
+ };
108
+ return {
109
+ x402Version,
110
+ payload
111
+ };
112
+ }
113
+ async function signPermit2Authorization(signer, permit2Authorization, requirements) {
114
+ const chainId = getEvmChainId(requirements.network);
115
+ const domain = {
116
+ name: "Permit2",
117
+ chainId,
118
+ verifyingContract: PERMIT2_ADDRESS
119
+ };
120
+ const message = {
121
+ permitted: {
122
+ token: getAddress2(permit2Authorization.permitted.token),
123
+ amount: BigInt(permit2Authorization.permitted.amount)
124
+ },
125
+ spender: getAddress2(permit2Authorization.spender),
126
+ nonce: BigInt(permit2Authorization.nonce),
127
+ deadline: BigInt(permit2Authorization.deadline),
128
+ witness: {
129
+ to: getAddress2(permit2Authorization.witness.to),
130
+ validAfter: BigInt(permit2Authorization.witness.validAfter)
131
+ }
132
+ };
133
+ return await signer.signTypedData({
134
+ domain,
135
+ types: permit2WitnessTypes,
136
+ primaryType: "PermitWitnessTransferFrom",
137
+ message
138
+ });
139
+ }
140
+ function createPermit2ApprovalTx(tokenAddress) {
141
+ const data = encodeFunctionData({
142
+ abi: erc20ApproveAbi,
143
+ functionName: "approve",
144
+ args: [PERMIT2_ADDRESS, MAX_UINT256]
145
+ });
146
+ return {
147
+ to: getAddress2(tokenAddress),
148
+ data
149
+ };
150
+ }
151
+ function getPermit2AllowanceReadParams(params) {
152
+ return {
153
+ address: getAddress2(params.tokenAddress),
154
+ abi: erc20AllowanceAbi,
155
+ functionName: "allowance",
156
+ args: [getAddress2(params.ownerAddress), PERMIT2_ADDRESS]
157
+ };
158
+ }
159
+
160
+ // src/exact/client/eip2612.ts
161
+ import { getAddress as getAddress3 } from "viem";
162
+ async function signEip2612Permit(signer, tokenAddress, tokenName, tokenVersion, chainId, deadline, permittedAmount) {
163
+ const owner = signer.address;
164
+ const spender = getAddress3(PERMIT2_ADDRESS);
165
+ const nonce = await signer.readContract({
166
+ address: tokenAddress,
167
+ abi: eip2612NoncesAbi,
168
+ functionName: "nonces",
169
+ args: [owner]
170
+ });
171
+ const domain = {
172
+ name: tokenName,
173
+ version: tokenVersion,
174
+ chainId,
175
+ verifyingContract: tokenAddress
176
+ };
177
+ const approvalAmount = BigInt(permittedAmount);
178
+ const message = {
179
+ owner,
180
+ spender,
181
+ value: approvalAmount,
182
+ nonce,
183
+ deadline: BigInt(deadline)
184
+ };
185
+ const signature = await signer.signTypedData({
186
+ domain,
187
+ types: eip2612PermitTypes,
188
+ primaryType: "Permit",
189
+ message
190
+ });
191
+ return {
192
+ from: owner,
193
+ asset: tokenAddress,
194
+ spender,
195
+ amount: approvalAmount.toString(),
196
+ nonce: nonce.toString(),
197
+ deadline,
198
+ signature,
199
+ version: "1"
200
+ };
201
+ }
202
+
203
+ // src/exact/client/erc20approval.ts
204
+ import { encodeFunctionData as encodeFunctionData2, getAddress as getAddress4, maxUint256 } from "viem";
205
+ import {
206
+ ERC20_APPROVAL_GAS_SPONSORING_VERSION
207
+ } from "@x402/extensions";
208
+ async function signErc20ApprovalTransaction(signer, tokenAddress, chainId) {
209
+ const from = signer.address;
210
+ const spender = getAddress4(PERMIT2_ADDRESS);
211
+ const data = encodeFunctionData2({
212
+ abi: erc20ApproveAbi,
213
+ functionName: "approve",
214
+ args: [spender, maxUint256]
215
+ });
216
+ const nonce = await signer.getTransactionCount({ address: from });
217
+ let maxFeePerGas;
218
+ let maxPriorityFeePerGas;
219
+ try {
220
+ const fees = await signer.estimateFeesPerGas();
221
+ maxFeePerGas = fees.maxFeePerGas;
222
+ maxPriorityFeePerGas = fees.maxPriorityFeePerGas;
223
+ } catch {
224
+ maxFeePerGas = DEFAULT_MAX_FEE_PER_GAS;
225
+ maxPriorityFeePerGas = DEFAULT_MAX_PRIORITY_FEE_PER_GAS;
226
+ }
227
+ const signedTransaction = await signer.signTransaction({
228
+ to: tokenAddress,
229
+ data,
230
+ nonce,
231
+ gas: ERC20_APPROVE_GAS_LIMIT,
232
+ maxFeePerGas,
233
+ maxPriorityFeePerGas,
234
+ chainId
235
+ });
236
+ return {
237
+ from,
238
+ asset: tokenAddress,
239
+ spender,
240
+ amount: maxUint256.toString(),
241
+ signedTransaction,
242
+ version: ERC20_APPROVAL_GAS_SPONSORING_VERSION
243
+ };
244
+ }
245
+
246
+ // src/exact/client/scheme.ts
247
+ var ExactEvmScheme = class {
248
+ /**
249
+ * Creates a new ExactEvmClient instance.
250
+ *
251
+ * @param signer - The EVM signer for client operations.
252
+ * Must support `readContract` for EIP-2612 gas sponsoring.
253
+ * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`.
254
+ */
255
+ constructor(signer) {
256
+ this.signer = signer;
257
+ this.scheme = "exact";
258
+ }
259
+ /**
260
+ * Creates a payment payload for the Exact scheme.
261
+ * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
262
+ *
263
+ * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the
264
+ * signer supports `readContract`, automatically signs an EIP-2612 permit
265
+ * when Permit2 allowance is insufficient.
266
+ *
267
+ * @param x402Version - The x402 protocol version
268
+ * @param paymentRequirements - The payment requirements
269
+ * @param context - Optional context with server-declared extensions
270
+ * @returns Promise resolving to a payment payload result (with optional extensions)
271
+ */
272
+ async createPaymentPayload(x402Version, paymentRequirements, context) {
273
+ const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
274
+ if (assetTransferMethod === "permit2") {
275
+ const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);
276
+ const eip2612Extensions = await this.trySignEip2612Permit(
277
+ paymentRequirements,
278
+ result,
279
+ context
280
+ );
281
+ if (eip2612Extensions) {
282
+ return {
283
+ ...result,
284
+ extensions: eip2612Extensions
285
+ };
286
+ }
287
+ const erc20Extensions = await this.trySignErc20Approval(paymentRequirements, result, context);
288
+ if (erc20Extensions) {
289
+ return {
290
+ ...result,
291
+ extensions: erc20Extensions
292
+ };
293
+ }
294
+ return result;
295
+ }
296
+ return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
297
+ }
298
+ /**
299
+ * Attempts to sign an EIP-2612 permit for gasless Permit2 approval.
300
+ *
301
+ * Returns extension data if:
302
+ * 1. Server advertises eip2612GasSponsoring
303
+ * 2. Signer has readContract capability
304
+ * 3. Current Permit2 allowance is insufficient
305
+ *
306
+ * Returns undefined if the extension should not be used.
307
+ *
308
+ * @param requirements - The payment requirements from the server
309
+ * @param result - The payment payload result from the scheme
310
+ * @param context - Optional context containing server extensions and metadata
311
+ * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable
312
+ */
313
+ async trySignEip2612Permit(requirements, result, context) {
314
+ if (!context?.extensions?.[EIP2612_GAS_SPONSORING.key]) {
315
+ return void 0;
316
+ }
317
+ const tokenName = requirements.extra?.name;
318
+ const tokenVersion = requirements.extra?.version;
319
+ if (!tokenName || !tokenVersion) {
320
+ return void 0;
321
+ }
322
+ const chainId = getEvmChainId(requirements.network);
323
+ const tokenAddress = getAddress5(requirements.asset);
324
+ try {
325
+ const allowance = await this.signer.readContract({
326
+ address: tokenAddress,
327
+ abi: erc20AllowanceAbi,
328
+ functionName: "allowance",
329
+ args: [this.signer.address, PERMIT2_ADDRESS]
330
+ });
331
+ if (allowance >= BigInt(requirements.amount)) {
332
+ return void 0;
333
+ }
334
+ } catch {
335
+ }
336
+ const permit2Auth = result.payload?.permit2Authorization;
337
+ const deadline = permit2Auth?.deadline ?? Math.floor(Date.now() / 1e3 + requirements.maxTimeoutSeconds).toString();
338
+ const info = await signEip2612Permit(
339
+ this.signer,
340
+ tokenAddress,
341
+ tokenName,
342
+ tokenVersion,
343
+ chainId,
344
+ deadline,
345
+ requirements.amount
346
+ );
347
+ return {
348
+ [EIP2612_GAS_SPONSORING.key]: { info }
349
+ };
350
+ }
351
+ /**
352
+ * Attempts to sign an ERC-20 approval transaction for gasless Permit2 approval.
353
+ *
354
+ * This is the fallback path when the token does not support EIP-2612. The client
355
+ * signs (but does not broadcast) a raw `approve(Permit2, MaxUint256)` transaction.
356
+ * The facilitator broadcasts it atomically before settling.
357
+ *
358
+ * Returns extension data if:
359
+ * 1. Server advertises erc20ApprovalGasSponsoring
360
+ * 2. Signer has signTransaction + getTransactionCount capabilities
361
+ * 3. Current Permit2 allowance is insufficient
362
+ *
363
+ * Returns undefined if the extension should not be used.
364
+ *
365
+ * @param requirements - The payment requirements from the server
366
+ * @param _result - The payment payload result from the scheme (unused)
367
+ * @param context - Optional context containing server extensions and metadata
368
+ * @returns Extension data for ERC-20 approval gas sponsoring, or undefined if not applicable
369
+ */
370
+ async trySignErc20Approval(requirements, _result, context) {
371
+ if (!context?.extensions?.[ERC20_APPROVAL_GAS_SPONSORING.key]) {
372
+ return void 0;
373
+ }
374
+ if (!this.signer.signTransaction || !this.signer.getTransactionCount) {
375
+ return void 0;
376
+ }
377
+ const chainId = getEvmChainId(requirements.network);
378
+ const tokenAddress = getAddress5(requirements.asset);
379
+ try {
380
+ const allowance = await this.signer.readContract({
381
+ address: tokenAddress,
382
+ abi: erc20AllowanceAbi,
383
+ functionName: "allowance",
384
+ args: [this.signer.address, PERMIT2_ADDRESS]
385
+ });
386
+ if (allowance >= BigInt(requirements.amount)) {
387
+ return void 0;
388
+ }
389
+ } catch {
390
+ }
391
+ const info = await signErc20ApprovalTransaction(this.signer, tokenAddress, chainId);
392
+ return {
393
+ [ERC20_APPROVAL_GAS_SPONSORING.key]: { info }
394
+ };
395
+ }
396
+ };
397
+
398
+ // src/exact/client/register.ts
399
+ function registerExactEvmScheme(client, config) {
400
+ const evmScheme = new ExactEvmScheme(config.signer);
401
+ if (config.networks && config.networks.length > 0) {
402
+ config.networks.forEach((network) => {
403
+ client.register(network, evmScheme);
404
+ });
405
+ } else {
406
+ client.register("eip155:*", evmScheme);
407
+ }
408
+ NETWORKS.forEach((network) => {
409
+ client.registerV1(network, new ExactEvmSchemeV1(config.signer));
410
+ });
411
+ if (config.policies) {
412
+ config.policies.forEach((policy) => {
413
+ client.registerPolicy(policy);
414
+ });
415
+ }
416
+ return client;
417
+ }
418
+
419
+ export {
420
+ createPermit2ApprovalTx,
421
+ getPermit2AllowanceReadParams,
422
+ ExactEvmScheme,
423
+ registerExactEvmScheme
424
+ };
425
+ //# sourceMappingURL=chunk-GY6X5A3G.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exact/client/scheme.ts","../../src/exact/client/eip3009.ts","../../src/exact/client/permit2.ts","../../src/exact/client/eip2612.ts","../../src/exact/client/erc20approval.ts","../../src/exact/client/register.ts"],"sourcesContent":["import {\n PaymentRequirements,\n SchemeNetworkClient,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@x402/core/types\";\nimport { EIP2612_GAS_SPONSORING, ERC20_APPROVAL_GAS_SPONSORING } from \"@x402/extensions\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { AssetTransferMethod } from \"../../types\";\nimport { PERMIT2_ADDRESS, erc20AllowanceAbi } from \"../../constants\";\nimport { getAddress } from \"viem\";\nimport { getEvmChainId } from \"../../utils\";\nimport { createEIP3009Payload } from \"./eip3009\";\nimport { createPermit2Payload } from \"./permit2\";\nimport { signEip2612Permit } from \"./eip2612\";\nimport { signErc20ApprovalTransaction } from \"./erc20approval\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows.\n *\n * Routes to the appropriate authorization method based on\n * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009\n * for backward compatibility with older facilitators.\n *\n * When the server advertises `eip2612GasSponsoring` and the asset transfer\n * method is `permit2`, the scheme automatically signs an EIP-2612 permit\n * if the user lacks Permit2 approval. This requires `readContract` on the signer.\n */\nexport class ExactEvmScheme implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClient instance.\n *\n * @param signer - The EVM signer for client operations.\n * Must support `readContract` for EIP-2612 gas sponsoring.\n * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`.\n */\n constructor(private readonly signer: ClientEvmSigner) {}\n\n /**\n * Creates a payment payload for the Exact scheme.\n * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.\n *\n * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the\n * signer supports `readContract`, automatically signs an EIP-2612 permit\n * when Permit2 allowance is insufficient.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @param context - Optional context with server-declared extensions\n * @returns Promise resolving to a payment payload result (with optional extensions)\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n const assetTransferMethod =\n (paymentRequirements.extra?.assetTransferMethod as AssetTransferMethod) ?? \"eip3009\";\n\n if (assetTransferMethod === \"permit2\") {\n const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);\n\n // Check if EIP-2612 gas sponsoring is advertised and we can handle it\n const eip2612Extensions = await this.trySignEip2612Permit(\n paymentRequirements,\n result,\n context,\n );\n\n if (eip2612Extensions) {\n return {\n ...result,\n extensions: eip2612Extensions,\n };\n }\n\n // EIP-2612 not applicable — try ERC-20 approval gas sponsoring as fallback\n const erc20Extensions = await this.trySignErc20Approval(paymentRequirements, result, context);\n if (erc20Extensions) {\n return {\n ...result,\n extensions: erc20Extensions,\n };\n }\n\n return result;\n }\n\n return createEIP3009Payload(this.signer, x402Version, paymentRequirements);\n }\n\n /**\n * Attempts to sign an EIP-2612 permit for gasless Permit2 approval.\n *\n * Returns extension data if:\n * 1. Server advertises eip2612GasSponsoring\n * 2. Signer has readContract capability\n * 3. Current Permit2 allowance is insufficient\n *\n * Returns undefined if the extension should not be used.\n *\n * @param requirements - The payment requirements from the server\n * @param result - The payment payload result from the scheme\n * @param context - Optional context containing server extensions and metadata\n * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable\n */\n private async trySignEip2612Permit(\n requirements: PaymentRequirements,\n result: PaymentPayloadResult,\n context?: PaymentPayloadContext,\n ): Promise<Record<string, unknown> | undefined> {\n // Check if server advertises eip2612GasSponsoring\n if (!context?.extensions?.[EIP2612_GAS_SPONSORING.key]) {\n return undefined;\n }\n\n // Check that required token metadata is available\n const tokenName = requirements.extra?.name as string | undefined;\n const tokenVersion = requirements.extra?.version as string | undefined;\n if (!tokenName || !tokenVersion) {\n return undefined;\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset) as `0x${string}`;\n\n // Check if user already has sufficient Permit2 allowance\n try {\n const allowance = (await this.signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [this.signer.address, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return undefined; // Already approved, no need for EIP-2612\n }\n } catch {\n // If we can't check allowance, proceed with EIP-2612 signing\n }\n\n // Use the same deadline as the Permit2 authorization\n const permit2Auth = result.payload?.permit2Authorization as Record<string, unknown> | undefined;\n const deadline =\n (permit2Auth?.deadline as string) ??\n Math.floor(Date.now() / 1000 + requirements.maxTimeoutSeconds).toString();\n\n // Sign the EIP-2612 permit with the exact Permit2 permitted amount\n // (the contract enforces permit2612.value == permit.permitted.amount)\n const info = await signEip2612Permit(\n this.signer,\n tokenAddress,\n tokenName,\n tokenVersion,\n chainId,\n deadline,\n requirements.amount,\n );\n\n return {\n [EIP2612_GAS_SPONSORING.key]: { info },\n };\n }\n\n /**\n * Attempts to sign an ERC-20 approval transaction for gasless Permit2 approval.\n *\n * This is the fallback path when the token does not support EIP-2612. The client\n * signs (but does not broadcast) a raw `approve(Permit2, MaxUint256)` transaction.\n * The facilitator broadcasts it atomically before settling.\n *\n * Returns extension data if:\n * 1. Server advertises erc20ApprovalGasSponsoring\n * 2. Signer has signTransaction + getTransactionCount capabilities\n * 3. Current Permit2 allowance is insufficient\n *\n * Returns undefined if the extension should not be used.\n *\n * @param requirements - The payment requirements from the server\n * @param _result - The payment payload result from the scheme (unused)\n * @param context - Optional context containing server extensions and metadata\n * @returns Extension data for ERC-20 approval gas sponsoring, or undefined if not applicable\n */\n private async trySignErc20Approval(\n requirements: PaymentRequirements,\n _result: PaymentPayloadResult,\n context?: PaymentPayloadContext,\n ): Promise<Record<string, unknown> | undefined> {\n // Check if server advertises erc20ApprovalGasSponsoring\n if (!context?.extensions?.[ERC20_APPROVAL_GAS_SPONSORING.key]) {\n return undefined;\n }\n\n // Check that signer has the required capabilities for signing raw transactions\n if (!this.signer.signTransaction || !this.signer.getTransactionCount) {\n return undefined;\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset) as `0x${string}`;\n\n // Check if user already has sufficient Permit2 allowance\n try {\n const allowance = (await this.signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [this.signer.address, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return undefined; // Already approved, no need for ERC-20 approval tx\n }\n } catch {\n // If we can't check allowance, proceed with signing\n }\n\n // Sign the approve(Permit2, MaxUint256) transaction\n const info = await signErc20ApprovalTransaction(this.signer, tokenAddress, chainId);\n\n return {\n [ERC20_APPROVAL_GAS_SPONSORING.key]: { info },\n };\n }\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport { createNonce, getEvmChainId } from \"../../utils\";\n\n/**\n * Creates an EIP-3009 (transferWithAuthorization) payload.\n *\n * @param signer - The EVM signer for client operations\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createEIP3009Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEIP3009Payload[\"authorization\"] = {\n from: signer.address,\n to: getAddress(paymentRequirements.payTo),\n value: paymentRequirements.amount,\n validAfter: (now - 600).toString(),\n validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements);\n\n const payload: ExactEIP3009Payload = {\n authorization,\n signature,\n };\n\n return {\n x402Version,\n payload,\n };\n}\n\n/**\n * Sign the EIP-3009 authorization using EIP-712.\n *\n * @param signer - The EVM signer\n * @param authorization - The authorization to sign\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\nasync function signEIP3009Authorization(\n signer: ClientEvmSigner,\n authorization: ExactEIP3009Payload[\"authorization\"],\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(requirements.network);\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n throw new Error(\n `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`,\n );\n }\n\n const { name, version } = requirements.extra;\n\n const domain = {\n name,\n version,\n chainId,\n verifyingContract: getAddress(requirements.asset),\n };\n\n const message = {\n from: getAddress(authorization.from),\n to: getAddress(authorization.to),\n value: BigInt(authorization.value),\n validAfter: BigInt(authorization.validAfter),\n validBefore: BigInt(authorization.validBefore),\n nonce: authorization.nonce,\n };\n\n return await signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { encodeFunctionData, getAddress } from \"viem\";\nimport {\n permit2WitnessTypes,\n PERMIT2_ADDRESS,\n x402ExactPermit2ProxyAddress,\n erc20ApproveAbi,\n erc20AllowanceAbi,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactPermit2Payload } from \"../../types\";\nimport { createPermit2Nonce, getEvmChainId } from \"../../utils\";\n\n/** Maximum uint256 value for unlimited approval. */\nconst MAX_UINT256 = BigInt(\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\");\n\n/**\n * Creates a Permit2 payload using the x402Permit2Proxy witness pattern.\n * The spender is set to x402Permit2Proxy, which enforces that funds\n * can only be sent to the witness.to address.\n *\n * @param signer - The EVM signer for client operations\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createPermit2Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n\n // Lower time bound - allow some clock skew\n const validAfter = (now - 600).toString();\n // Upper time bound is enforced by Permit2's deadline field\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n const permit2Authorization: ExactPermit2Payload[\"permit2Authorization\"] = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: x402ExactPermit2ProxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n validAfter,\n },\n };\n\n const signature = await signPermit2Authorization(\n signer,\n permit2Authorization,\n paymentRequirements,\n );\n\n const payload: ExactPermit2Payload = {\n signature,\n permit2Authorization,\n };\n\n return {\n x402Version,\n payload,\n };\n}\n\n/**\n * Sign the Permit2 authorization using EIP-712 with witness data.\n * The signature authorizes the x402Permit2Proxy to transfer tokens on behalf of the signer.\n *\n * @param signer - The EVM signer\n * @param permit2Authorization - The Permit2 authorization parameters\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\nasync function signPermit2Authorization(\n signer: ClientEvmSigner,\n permit2Authorization: ExactPermit2Payload[\"permit2Authorization\"],\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(requirements.network);\n\n const domain = {\n name: \"Permit2\",\n chainId,\n verifyingContract: PERMIT2_ADDRESS,\n };\n\n const message = {\n permitted: {\n token: getAddress(permit2Authorization.permitted.token),\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Authorization.spender),\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Authorization.witness.to),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n },\n };\n\n return await signer.signTypedData({\n domain,\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message,\n });\n}\n\n/**\n * Creates transaction data to approve Permit2 to spend tokens.\n * The user sends this transaction (paying gas) before using Permit2 flow.\n *\n * @param tokenAddress - The ERC20 token contract address\n * @returns Transaction data to send for approval\n *\n * @example\n * ```typescript\n * const tx = createPermit2ApprovalTx(\"0x...\");\n * await walletClient.sendTransaction({\n * to: tx.to,\n * data: tx.data,\n * });\n * ```\n */\nexport function createPermit2ApprovalTx(tokenAddress: `0x${string}`): {\n to: `0x${string}`;\n data: `0x${string}`;\n} {\n const data = encodeFunctionData({\n abi: erc20ApproveAbi,\n functionName: \"approve\",\n args: [PERMIT2_ADDRESS, MAX_UINT256],\n });\n\n return {\n to: getAddress(tokenAddress),\n data,\n };\n}\n\n/**\n * Parameters for checking Permit2 allowance.\n * Application provides these to check if approval is needed.\n */\nexport interface Permit2AllowanceParams {\n tokenAddress: `0x${string}`;\n ownerAddress: `0x${string}`;\n}\n\n/**\n * Returns contract read parameters for checking Permit2 allowance.\n * Use with a public client to check if the user has approved Permit2.\n *\n * @param params - The allowance check parameters\n * @returns Contract read parameters for checking allowance\n *\n * @example\n * ```typescript\n * const readParams = getPermit2AllowanceReadParams({\n * tokenAddress: \"0x...\",\n * ownerAddress: \"0x...\",\n * });\n *\n * const allowance = await publicClient.readContract(readParams);\n * const needsApproval = allowance < requiredAmount;\n * ```\n */\nexport function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): {\n address: `0x${string}`;\n abi: typeof erc20AllowanceAbi;\n functionName: \"allowance\";\n args: [`0x${string}`, `0x${string}`];\n} {\n return {\n address: getAddress(params.tokenAddress),\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [getAddress(params.ownerAddress), PERMIT2_ADDRESS],\n };\n}\n","import { getAddress } from \"viem\";\nimport type { Eip2612GasSponsoringInfo } from \"@x402/extensions\";\nimport { eip2612PermitTypes, eip2612NoncesAbi, PERMIT2_ADDRESS } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\n\n/**\n * Signs an EIP-2612 permit authorizing the Permit2 contract to spend tokens.\n *\n * This creates a gasless off-chain signature that the facilitator can submit\n * on-chain via `x402Permit2Proxy.settleWithPermit()`.\n *\n * The `permittedAmount` must match the Permit2 `permitted.amount` exactly, as the\n * proxy contract enforces `permit2612.value == permittedAmount`.\n *\n * @param signer - The client EVM signer (must support readContract for nonce query)\n * @param tokenAddress - The ERC-20 token contract address\n * @param tokenName - The token name (from paymentRequirements.extra.name)\n * @param tokenVersion - The token version (from paymentRequirements.extra.version)\n * @param chainId - The chain ID\n * @param deadline - The deadline for the permit (unix timestamp as string)\n * @param permittedAmount - The Permit2 permitted amount (must match exactly)\n * @returns The EIP-2612 gas sponsoring info object\n */\nexport async function signEip2612Permit(\n signer: ClientEvmSigner,\n tokenAddress: `0x${string}`,\n tokenName: string,\n tokenVersion: string,\n chainId: number,\n deadline: string,\n permittedAmount: string,\n): Promise<Eip2612GasSponsoringInfo> {\n const owner = signer.address;\n const spender = getAddress(PERMIT2_ADDRESS);\n\n // Query the current EIP-2612 nonce from the token contract\n const nonce = (await signer.readContract({\n address: tokenAddress,\n abi: eip2612NoncesAbi,\n functionName: \"nonces\",\n args: [owner],\n })) as bigint;\n\n // Construct EIP-712 domain for the token's permit function\n const domain = {\n name: tokenName,\n version: tokenVersion,\n chainId,\n verifyingContract: tokenAddress,\n };\n\n const approvalAmount = BigInt(permittedAmount);\n\n const message = {\n owner,\n spender,\n value: approvalAmount,\n nonce,\n deadline: BigInt(deadline),\n };\n\n // Sign the EIP-2612 permit\n const signature = await signer.signTypedData({\n domain,\n types: eip2612PermitTypes,\n primaryType: \"Permit\",\n message,\n });\n\n return {\n from: owner,\n asset: tokenAddress,\n spender,\n amount: approvalAmount.toString(),\n nonce: nonce.toString(),\n deadline,\n signature,\n version: \"1\",\n };\n}\n","import { encodeFunctionData, getAddress, maxUint256 } from \"viem\";\nimport {\n ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n type Erc20ApprovalGasSponsoringInfo,\n} from \"@x402/extensions\";\nimport {\n PERMIT2_ADDRESS,\n erc20ApproveAbi,\n ERC20_APPROVE_GAS_LIMIT,\n DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_MAX_PRIORITY_FEE_PER_GAS,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\n\n/**\n * Signs an EIP-1559 `approve(Permit2, MaxUint256)` transaction for the given token.\n *\n * The signed transaction is NOT broadcast here — the facilitator broadcasts it\n * atomically before settling the Permit2 payment. This enables Permit2 payments\n * for generic ERC-20 tokens that do NOT implement EIP-2612.\n *\n * Always approves MaxUint256 regardless of the payment amount.\n *\n * @param signer - The client EVM signer (must support signTransaction, getTransactionCount)\n * @param tokenAddress - The ERC-20 token contract address\n * @param chainId - The chain ID\n * @returns The ERC-20 approval gas sponsoring info object\n */\nexport async function signErc20ApprovalTransaction(\n signer: ClientEvmSigner,\n tokenAddress: `0x${string}`,\n chainId: number,\n): Promise<Erc20ApprovalGasSponsoringInfo> {\n const from = signer.address;\n const spender = getAddress(PERMIT2_ADDRESS);\n\n // Encode approve(PERMIT2_ADDRESS, MaxUint256) calldata\n const data = encodeFunctionData({\n abi: erc20ApproveAbi,\n functionName: \"approve\",\n args: [spender, maxUint256],\n });\n\n // Get current nonce for the sender\n const nonce = await signer.getTransactionCount!({ address: from });\n\n // Get current fee estimates, with fallback values\n let maxFeePerGas: bigint;\n let maxPriorityFeePerGas: bigint;\n try {\n const fees = await signer.estimateFeesPerGas!();\n maxFeePerGas = fees.maxFeePerGas;\n maxPriorityFeePerGas = fees.maxPriorityFeePerGas;\n } catch {\n maxFeePerGas = DEFAULT_MAX_FEE_PER_GAS;\n maxPriorityFeePerGas = DEFAULT_MAX_PRIORITY_FEE_PER_GAS;\n }\n\n // Sign the EIP-1559 transaction (not broadcast)\n const signedTransaction = await signer.signTransaction!({\n to: tokenAddress,\n data,\n nonce,\n gas: ERC20_APPROVE_GAS_LIMIT,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chainId,\n });\n\n return {\n from,\n asset: tokenAddress,\n spender,\n amount: maxUint256.toString(),\n signedTransaction,\n version: ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n };\n}\n","import { x402Client, SelectPaymentRequirements, PaymentPolicy } from \"@x402/core/client\";\nimport { Network } from \"@x402/core/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmScheme } from \"./scheme\";\nimport { ExactEvmSchemeV1 } from \"../v1/client/scheme\";\nimport { NETWORKS } from \"../../v1\";\n\n/**\n * Configuration options for registering EVM schemes to an x402Client\n */\nexport interface EvmClientConfig {\n /**\n * The EVM signer to use for creating payment payloads\n */\n signer: ClientEvmSigner;\n\n /**\n * Optional payment requirements selector function\n * If not provided, uses the default selector (first available option)\n */\n paymentRequirementsSelector?: SelectPaymentRequirements;\n\n /**\n * Optional policies to apply to the client\n */\n policies?: PaymentPolicy[];\n\n /**\n * Optional specific networks to register\n * If not provided, registers wildcard support (eip155:*)\n */\n networks?: Network[];\n}\n\n/**\n * Registers EVM exact payment schemes to an x402Client instance.\n *\n * This function registers:\n * - V2: eip155:* wildcard scheme with ExactEvmScheme (or specific networks if provided)\n * - V1: All supported EVM networks with ExactEvmSchemeV1\n *\n * @param client - The x402Client instance to register schemes to\n * @param config - Configuration for EVM client registration\n * @returns The client instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/client/register\";\n * import { x402Client } from \"@x402/core/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const client = new x402Client();\n * registerExactEvmScheme(client, { signer: account });\n * ```\n */\nexport function registerExactEvmScheme(client: x402Client, config: EvmClientConfig): x402Client {\n const evmScheme = new ExactEvmScheme(config.signer);\n\n // Register V2 scheme\n // EIP-2612 gas sponsoring is handled internally by the scheme when the\n // server advertises support - no separate extension registration needed.\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach(network => {\n client.register(network, evmScheme);\n });\n } else {\n // Register wildcard for all EVM chains\n client.register(\"eip155:*\", evmScheme);\n }\n\n // Register all V1 networks\n NETWORKS.forEach(network => {\n client.registerV1(network as Network, new ExactEvmSchemeV1(config.signer));\n });\n\n // Apply policies if provided\n if (config.policies) {\n config.policies.forEach(policy => {\n client.registerPolicy(policy);\n });\n }\n\n return client;\n}\n"],"mappings":"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","names":["getAddress","getAddress","getAddress","getAddress","getAddress","encodeFunctionData","getAddress","getAddress","encodeFunctionData","getAddress"]}
@@ -10,4 +10,4 @@ export {
10
10
  isPermit2Payload,
11
11
  isEIP3009Payload
12
12
  };
13
- //# sourceMappingURL=chunk-PFULIQAE.mjs.map
13
+ //# sourceMappingURL=chunk-TKN5V2BV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["/**\n * Asset transfer methods for the exact EVM scheme.\n * - eip3009: Uses transferWithAuthorization (USDC, etc.) - recommended for compatible tokens\n * - permit2: Uses Permit2 + x402Permit2Proxy - universal fallback for any ERC-20\n */\nexport type AssetTransferMethod = \"eip3009\" | \"permit2\";\n\n/**\n * EIP-3009 payload for tokens with native transferWithAuthorization support.\n */\nexport type ExactEIP3009Payload = {\n signature?: `0x${string}`;\n authorization: {\n from: `0x${string}`;\n to: `0x${string}`;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: `0x${string}`;\n };\n};\n\n/**\n * Permit2 witness data structure.\n * Matches the Witness struct in x402Permit2Proxy contract.\n * Note: Upper time bound is enforced by Permit2's `deadline` field, not a witness field.\n */\nexport type Permit2Witness = {\n to: `0x${string}`;\n validAfter: string;\n};\n\n/**\n * Permit2 authorization parameters.\n * Used to reconstruct the signed message for verification.\n */\nexport type Permit2Authorization = {\n permitted: {\n token: `0x${string}`;\n amount: string;\n };\n spender: `0x${string}`;\n nonce: string;\n deadline: string;\n witness: Permit2Witness;\n};\n\n/**\n * Permit2 payload for tokens using the Permit2 + x402Permit2Proxy flow.\n */\nexport type ExactPermit2Payload = {\n signature: `0x${string}`;\n permit2Authorization: Permit2Authorization & {\n from: `0x${string}`;\n };\n};\n\nexport type ExactEvmPayloadV1 = ExactEIP3009Payload;\n\nexport type ExactEvmPayloadV2 = ExactEIP3009Payload | ExactPermit2Payload;\n\n/**\n * Type guard to check if a payload is a Permit2 payload.\n * Permit2 payloads have a `permit2Authorization` field.\n *\n * @param payload - The payload to check.\n * @returns True if the payload is a Permit2 payload, false otherwise.\n */\nexport function isPermit2Payload(payload: ExactEvmPayloadV2): payload is ExactPermit2Payload {\n return \"permit2Authorization\" in payload;\n}\n\n/**\n * Type guard to check if a payload is an EIP-3009 payload.\n * EIP-3009 payloads have an `authorization` field.\n *\n * @param payload - The payload to check.\n * @returns True if the payload is an EIP-3009 payload, false otherwise.\n */\nexport function isEIP3009Payload(payload: ExactEvmPayloadV2): payload is ExactEIP3009Payload {\n return \"authorization\" in payload;\n}\n"],"mappings":";AAoEO,SAAS,iBAAiB,SAA4D;AAC3F,SAAO,0BAA0B;AACnC;AASO,SAAS,iBAAiB,SAA4D;AAC3F,SAAO,mBAAmB;AAC5B;","names":[]}
@@ -1,7 +1,7 @@
1
- export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-BsAoJiWD.mjs';
1
+ export { E as ExactEvmScheme, a as Permit2AllowanceParams, c as createPermit2ApprovalTx, d as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-CGOcN7Et.mjs';
2
2
  import { SelectPaymentRequirements, PaymentPolicy, x402Client } from '@x402/core/client';
3
3
  import { Network } from '@x402/core/types';
4
- import { C as ClientEvmSigner } from '../../signer-5OVDxViv.mjs';
4
+ import { C as ClientEvmSigner } from '../../signer-DC81R8wQ.mjs';
5
5
 
6
6
  /**
7
7
  * Configuration options for registering EVM schemes to an x402Client
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  ExactEvmScheme,
3
3
  createPermit2ApprovalTx,
4
- erc20AllowanceAbi,
5
4
  getPermit2AllowanceReadParams,
6
5
  registerExactEvmScheme
7
- } from "../../chunk-E2YMUI3X.mjs";
8
- import "../../chunk-RPL6OFJL.mjs";
6
+ } from "../../chunk-GY6X5A3G.mjs";
7
+ import {
8
+ erc20AllowanceAbi
9
+ } from "../../chunk-7KHQD5KT.mjs";
9
10
  export {
10
11
  ExactEvmScheme,
11
12
  createPermit2ApprovalTx,
@@ -1,5 +1,5 @@
1
- import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse, Network } from '@x402/core/types';
2
- import { F as FacilitatorEvmSigner } from '../../signer-5OVDxViv.mjs';
1
+ import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, FacilitatorContext, VerifyResponse, SettleResponse, Network } from '@x402/core/types';
2
+ import { F as FacilitatorEvmSigner } from '../../signer-DC81R8wQ.mjs';
3
3
  import { x402Facilitator } from '@x402/core/facilitator';
4
4
 
5
5
  interface ExactEvmSchemeConfig {
@@ -13,7 +13,9 @@ interface ExactEvmSchemeConfig {
13
13
  }
14
14
  /**
15
15
  * EVM facilitator implementation for the Exact payment scheme.
16
- * Routes between EIP-3009 and Permit2 based on payload type.
16
+ * Thin router that delegates to EIP-3009 or Permit2 based on payload type.
17
+ * All extension handling (EIP-2612, ERC-20 approval gas sponsoring) is owned
18
+ * by the Permit2 functions via FacilitatorContext.
17
19
  */
18
20
  declare class ExactEvmScheme implements SchemeNetworkFacilitator {
19
21
  private readonly signer;
@@ -21,46 +23,44 @@ declare class ExactEvmScheme implements SchemeNetworkFacilitator {
21
23
  readonly caipFamily = "eip155:*";
22
24
  private readonly config;
23
25
  /**
24
- * Creates a new ExactEvmFacilitator instance.
26
+ * Creates a new ExactEvmScheme facilitator instance.
25
27
  *
26
28
  * @param signer - The EVM signer for facilitator operations
27
- * @param config - Optional configuration for the facilitator
29
+ * @param config - Optional configuration
28
30
  */
29
31
  constructor(signer: FacilitatorEvmSigner, config?: ExactEvmSchemeConfig);
30
32
  /**
31
- * Get mechanism-specific extra data for the supported kinds endpoint.
32
- * For EVM, no extra data is needed.
33
+ * Returns undefined — EVM has no mechanism-specific extra data.
33
34
  *
34
- * @param _ - The network identifier (unused for EVM)
35
- * @returns undefined (EVM has no extra data)
35
+ * @param _ - The network identifier (unused)
36
+ * @returns undefined
36
37
  */
37
38
  getExtra(_: string): Record<string, unknown> | undefined;
38
39
  /**
39
- * Get signer addresses used by this facilitator.
40
- * Returns all addresses this facilitator can use for signing/settling transactions.
40
+ * Returns facilitator wallet addresses for the supported response.
41
41
  *
42
- * @param _ - The network identifier (unused for EVM, addresses are network-agnostic)
42
+ * @param _ - The network identifier (unused, addresses are network-agnostic)
43
43
  * @returns Array of facilitator wallet addresses
44
44
  */
45
45
  getSigners(_: string): string[];
46
46
  /**
47
- * Verifies a payment payload.
48
- * Routes to the appropriate verification logic based on payload type.
47
+ * Verifies a payment payload. Routes to Permit2 or EIP-3009 based on payload type.
49
48
  *
50
49
  * @param payload - The payment payload to verify
51
50
  * @param requirements - The payment requirements
51
+ * @param context - Optional facilitator context for extension capabilities
52
52
  * @returns Promise resolving to verification response
53
53
  */
54
- verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
54
+ verify(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<VerifyResponse>;
55
55
  /**
56
- * Settles a payment by executing the transfer.
57
- * Routes to the appropriate settlement logic based on payload type.
56
+ * Settles a payment. Routes to Permit2 or EIP-3009 based on payload type.
58
57
  *
59
58
  * @param payload - The payment payload to settle
60
59
  * @param requirements - The payment requirements
60
+ * @param context - Optional facilitator context for extension capabilities
61
61
  * @returns Promise resolving to settlement response
62
62
  */
63
- settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;
63
+ settle(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<SettleResponse>;
64
64
  }
65
65
 
66
66
  /**