@payai/x402-evm 2.3.6 → 2.4.1
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 -2
- package/dist/cjs/exact/client/index.js +173 -194
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.js +220 -187
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.d.ts +14 -21
- package/dist/cjs/exact/server/index.js +109 -69
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.js +3 -1
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.js +3 -1
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +38 -2
- package/dist/cjs/index.js +441 -191
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/{permit2-U9Zolx3O.d.ts → permit2-CyZxwngN.d.ts} +278 -87
- package/dist/cjs/scheme-CXDF0D2A.d.ts +47 -0
- package/dist/cjs/upto/client/index.d.ts +32 -0
- package/dist/cjs/upto/client/index.js +507 -0
- package/dist/cjs/upto/client/index.js.map +1 -0
- package/dist/cjs/upto/facilitator/index.d.ts +52 -0
- package/dist/cjs/upto/facilitator/index.js +1233 -0
- package/dist/cjs/upto/facilitator/index.js.map +1 -0
- package/dist/cjs/upto/server/index.d.ts +69 -0
- package/dist/cjs/upto/server/index.js +239 -0
- package/dist/cjs/upto/server/index.js.map +1 -0
- package/dist/cjs/v1/index.d.ts +2 -0
- package/dist/cjs/v1/index.js +3 -1
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/chunk-C4ZQMS77.mjs +629 -0
- package/dist/esm/chunk-C4ZQMS77.mjs.map +1 -0
- package/dist/esm/chunk-CRT6YNY5.mjs +529 -0
- package/dist/esm/chunk-CRT6YNY5.mjs.map +1 -0
- package/dist/esm/{chunk-PCJKIY5G.mjs → chunk-ERK2ZPOY.mjs} +49 -501
- package/dist/esm/chunk-ERK2ZPOY.mjs.map +1 -0
- package/dist/esm/chunk-F3OOHBAW.mjs +89 -0
- package/dist/esm/chunk-F3OOHBAW.mjs.map +1 -0
- package/dist/esm/chunk-FQJR4RCF.mjs +158 -0
- package/dist/esm/chunk-FQJR4RCF.mjs.map +1 -0
- package/dist/esm/chunk-GJ57SZGI.mjs +121 -0
- package/dist/esm/chunk-GJ57SZGI.mjs.map +1 -0
- package/dist/esm/chunk-JII456TS.mjs +34 -0
- package/dist/esm/chunk-JII456TS.mjs.map +1 -0
- package/dist/esm/chunk-WKBC5YMI.mjs +291 -0
- package/dist/esm/chunk-WKBC5YMI.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +3 -2
- package/dist/esm/exact/client/index.mjs +8 -5
- package/dist/esm/exact/facilitator/index.mjs +87 -432
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.d.mts +14 -21
- package/dist/esm/exact/server/index.mjs +26 -69
- package/dist/esm/exact/server/index.mjs.map +1 -1
- package/dist/esm/exact/v1/client/index.mjs +2 -1
- package/dist/esm/exact/v1/facilitator/index.mjs +2 -1
- package/dist/esm/index.d.mts +38 -2
- package/dist/esm/index.mjs +21 -8
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/{permit2-Bbh3a8_h.d.mts → permit2-CyZxwngN.d.mts} +278 -87
- package/dist/esm/scheme-DCR7hsa3.d.mts +47 -0
- package/dist/esm/upto/client/index.d.mts +32 -0
- package/dist/esm/upto/client/index.mjs +18 -0
- package/dist/esm/upto/client/index.mjs.map +1 -0
- package/dist/esm/upto/facilitator/index.d.mts +52 -0
- package/dist/esm/upto/facilitator/index.mjs +473 -0
- package/dist/esm/upto/facilitator/index.mjs.map +1 -0
- package/dist/esm/upto/server/index.d.mts +69 -0
- package/dist/esm/upto/server/index.mjs +129 -0
- package/dist/esm/upto/server/index.mjs.map +1 -0
- package/dist/esm/v1/index.d.mts +2 -0
- package/dist/esm/v1/index.mjs +2 -1
- package/package.json +31 -1
- package/dist/esm/chunk-GD4MKCN7.mjs +0 -57
- package/dist/esm/chunk-GD4MKCN7.mjs.map +0 -1
- package/dist/esm/chunk-LWO35IGS.mjs +0 -518
- package/dist/esm/chunk-LWO35IGS.mjs.map +0 -1
- package/dist/esm/chunk-PCJKIY5G.mjs.map +0 -1
- package/dist/esm/chunk-TKN5V2BV.mjs +0 -13
- package/dist/esm/chunk-TKN5V2BV.mjs.map +0 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/shared/defaultAssets.ts
|
|
2
|
+
var DEFAULT_STABLECOINS = {
|
|
3
|
+
"eip155:8453": {
|
|
4
|
+
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
5
|
+
name: "USD Coin",
|
|
6
|
+
version: "2",
|
|
7
|
+
decimals: 6
|
|
8
|
+
},
|
|
9
|
+
// Base mainnet USDC
|
|
10
|
+
"eip155:84532": {
|
|
11
|
+
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
12
|
+
name: "USDC",
|
|
13
|
+
version: "2",
|
|
14
|
+
decimals: 6
|
|
15
|
+
},
|
|
16
|
+
// Base Sepolia USDC
|
|
17
|
+
"eip155:4326": {
|
|
18
|
+
address: "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7",
|
|
19
|
+
name: "MegaUSD",
|
|
20
|
+
version: "1",
|
|
21
|
+
decimals: 18,
|
|
22
|
+
assetTransferMethod: "permit2",
|
|
23
|
+
supportsEip2612: true
|
|
24
|
+
},
|
|
25
|
+
// MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)
|
|
26
|
+
"eip155:143": {
|
|
27
|
+
address: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
|
|
28
|
+
name: "USD Coin",
|
|
29
|
+
version: "2",
|
|
30
|
+
decimals: 6
|
|
31
|
+
},
|
|
32
|
+
// Monad mainnet USDC
|
|
33
|
+
"eip155:988": {
|
|
34
|
+
address: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
35
|
+
name: "USDT0",
|
|
36
|
+
version: "1",
|
|
37
|
+
decimals: 6
|
|
38
|
+
},
|
|
39
|
+
// Stable mainnet USDT0
|
|
40
|
+
"eip155:2201": {
|
|
41
|
+
address: "0x78Cf24370174180738C5B8E352B6D14c83a6c9A9",
|
|
42
|
+
name: "USDT0",
|
|
43
|
+
version: "1",
|
|
44
|
+
decimals: 6
|
|
45
|
+
},
|
|
46
|
+
// Stable testnet USDT0
|
|
47
|
+
"eip155:137": {
|
|
48
|
+
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
49
|
+
name: "USD Coin",
|
|
50
|
+
version: "2",
|
|
51
|
+
decimals: 6
|
|
52
|
+
},
|
|
53
|
+
// Polygon mainnet USDC
|
|
54
|
+
"eip155:42161": {
|
|
55
|
+
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
56
|
+
name: "USD Coin",
|
|
57
|
+
version: "2",
|
|
58
|
+
decimals: 6
|
|
59
|
+
},
|
|
60
|
+
// Arbitrum One USDC
|
|
61
|
+
"eip155:421614": {
|
|
62
|
+
address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
|
|
63
|
+
name: "USD Coin",
|
|
64
|
+
version: "2",
|
|
65
|
+
decimals: 6
|
|
66
|
+
},
|
|
67
|
+
// Arbitrum Sepolia USDC
|
|
68
|
+
"eip155:31611": {
|
|
69
|
+
address: "0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503",
|
|
70
|
+
name: "Mezo USD",
|
|
71
|
+
version: "1",
|
|
72
|
+
decimals: 18,
|
|
73
|
+
assetTransferMethod: "permit2",
|
|
74
|
+
supportsEip2612: true
|
|
75
|
+
}
|
|
76
|
+
// Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)
|
|
77
|
+
};
|
|
78
|
+
function getDefaultAsset(network) {
|
|
79
|
+
const info = DEFAULT_STABLECOINS[network];
|
|
80
|
+
if (!info) {
|
|
81
|
+
throw new Error(`No default asset configured for network ${network}`);
|
|
82
|
+
}
|
|
83
|
+
return info;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
getDefaultAsset
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=chunk-F3OOHBAW.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shared/defaultAssets.ts"],"sourcesContent":["import type { Network } from \"@payai/x402/types\";\n\n/**\n * Base stablecoin asset configuration shared across all EVM payment schemes.\n * Contains the core fields needed to identify and convert tokens.\n */\nexport type DefaultAssetInfo = {\n /** Token contract address */\n address: string;\n /** EIP-712 domain name (must match the token's domain separator) */\n name: string;\n /** EIP-712 domain version (must match the token's domain separator) */\n version: string;\n /** Token decimal places (typically 6 for USDC) */\n decimals: number;\n};\n\n/**\n * Extended asset configuration for the exact scheme.\n * Includes transfer method hints that control client-side behaviour.\n */\nexport type ExactDefaultAssetInfo = DefaultAssetInfo & {\n /**\n * Transfer method override: `\"permit2\"` for tokens that don't support EIP-3009.\n * Omit for EIP-3009 tokens (default behaviour).\n */\n assetTransferMethod?: string;\n /**\n * Set to `true` for permit2 tokens that implement EIP-2612 `permit()`.\n * Controls whether name/version are included in `extra` so the client can\n * sign a gasless EIP-2612 permit for Permit2 approval.\n */\n supportsEip2612?: boolean;\n};\n\n/**\n * Default stablecoins indexed by CAIP-2 network identifier.\n *\n * Each network has the right to determine its own default stablecoin that can\n * be expressed as a USD string by calling servers. See DEFAULT_ASSET.md in\n * exact/server/ for how to add new chains.\n */\nexport const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo> = {\n \"eip155:8453\": {\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Base mainnet USDC\n \"eip155:84532\": {\n address: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Base Sepolia USDC\n \"eip155:4326\": {\n address: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n name: \"MegaUSD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)\n \"eip155:143\": {\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Monad mainnet USDC\n \"eip155:988\": {\n address: \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable mainnet USDT0\n \"eip155:2201\": {\n address: \"0x78Cf24370174180738C5B8E352B6D14c83a6c9A9\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable testnet USDT0\n \"eip155:137\": {\n address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Polygon mainnet USDC\n \"eip155:42161\": {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum One USDC\n \"eip155:421614\": {\n address: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum Sepolia USDC\n \"eip155:31611\": {\n address: \"0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)\n};\n\n/**\n * Look up the default stablecoin for a network.\n *\n * @param network - CAIP-2 network identifier (e.g. \"eip155:8453\")\n * @returns The default asset info\n * @throws If no default asset is configured for the network\n */\nexport function getDefaultAsset(network: Network): ExactDefaultAssetInfo {\n const info = DEFAULT_STABLECOINS[network];\n if (!info) {\n throw new Error(`No default asset configured for network ${network}`);\n }\n return info;\n}\n"],"mappings":";AA0CO,IAAM,sBAA6D;AAAA,EACxE,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AACF;AASO,SAAS,gBAAgB,SAAyC;AACvE,QAAM,OAAO,oBAAoB,OAAO;AACxC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,2CAA2C,OAAO,EAAE;AAAA,EACtE;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExactEvmSchemeV12 as ExactEvmSchemeV1,
|
|
3
|
+
NETWORKS
|
|
4
|
+
} from "./chunk-ERK2ZPOY.mjs";
|
|
5
|
+
import {
|
|
6
|
+
createPermit2Payload,
|
|
7
|
+
trySignEip2612PermitExtension,
|
|
8
|
+
trySignErc20ApprovalExtension
|
|
9
|
+
} from "./chunk-WKBC5YMI.mjs";
|
|
10
|
+
import {
|
|
11
|
+
authorizationTypes,
|
|
12
|
+
createNonce,
|
|
13
|
+
getEvmChainId
|
|
14
|
+
} from "./chunk-C4ZQMS77.mjs";
|
|
15
|
+
|
|
16
|
+
// src/exact/client/eip3009.ts
|
|
17
|
+
import { getAddress } from "viem";
|
|
18
|
+
async function createEIP3009Payload(signer, x402Version, paymentRequirements) {
|
|
19
|
+
const nonce = createNonce();
|
|
20
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
21
|
+
const authorization = {
|
|
22
|
+
from: signer.address,
|
|
23
|
+
to: getAddress(paymentRequirements.payTo),
|
|
24
|
+
value: paymentRequirements.amount,
|
|
25
|
+
validAfter: (now - 600).toString(),
|
|
26
|
+
validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),
|
|
27
|
+
nonce
|
|
28
|
+
};
|
|
29
|
+
const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements);
|
|
30
|
+
const payload = {
|
|
31
|
+
authorization,
|
|
32
|
+
signature
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
x402Version,
|
|
36
|
+
payload
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function signEIP3009Authorization(signer, authorization, requirements) {
|
|
40
|
+
const chainId = getEvmChainId(requirements.network);
|
|
41
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const { name, version } = requirements.extra;
|
|
47
|
+
const domain = {
|
|
48
|
+
name,
|
|
49
|
+
version,
|
|
50
|
+
chainId,
|
|
51
|
+
verifyingContract: getAddress(requirements.asset)
|
|
52
|
+
};
|
|
53
|
+
const message = {
|
|
54
|
+
from: getAddress(authorization.from),
|
|
55
|
+
to: getAddress(authorization.to),
|
|
56
|
+
value: BigInt(authorization.value),
|
|
57
|
+
validAfter: BigInt(authorization.validAfter),
|
|
58
|
+
validBefore: BigInt(authorization.validBefore),
|
|
59
|
+
nonce: authorization.nonce
|
|
60
|
+
};
|
|
61
|
+
return await signer.signTypedData({
|
|
62
|
+
domain,
|
|
63
|
+
types: authorizationTypes,
|
|
64
|
+
primaryType: "TransferWithAuthorization",
|
|
65
|
+
message
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/exact/client/scheme.ts
|
|
70
|
+
var ExactEvmScheme = class {
|
|
71
|
+
/**
|
|
72
|
+
* Creates a new ExactEvmClient instance.
|
|
73
|
+
*
|
|
74
|
+
* @param signer - The EVM signer for client operations.
|
|
75
|
+
* Base flow only requires `address` + `signTypedData`.
|
|
76
|
+
* Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally
|
|
77
|
+
* requires optional capabilities like `readContract` and tx signing helpers.
|
|
78
|
+
* @param options - Optional RPC configuration used to backfill extension capabilities.
|
|
79
|
+
*/
|
|
80
|
+
constructor(signer, options) {
|
|
81
|
+
this.signer = signer;
|
|
82
|
+
this.options = options;
|
|
83
|
+
this.scheme = "exact";
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a payment payload for the Exact scheme.
|
|
87
|
+
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
|
|
88
|
+
*
|
|
89
|
+
* For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the
|
|
90
|
+
* signer supports `readContract`, automatically signs an EIP-2612 permit
|
|
91
|
+
* when Permit2 allowance is insufficient.
|
|
92
|
+
*
|
|
93
|
+
* @param x402Version - The x402 protocol version
|
|
94
|
+
* @param paymentRequirements - The payment requirements
|
|
95
|
+
* @param context - Optional context with server-declared extensions
|
|
96
|
+
* @returns Promise resolving to a payment payload result (with optional extensions)
|
|
97
|
+
*/
|
|
98
|
+
async createPaymentPayload(x402Version, paymentRequirements, context) {
|
|
99
|
+
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
|
|
100
|
+
if (assetTransferMethod === "permit2") {
|
|
101
|
+
const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);
|
|
102
|
+
const eip2612Extensions = await trySignEip2612PermitExtension(
|
|
103
|
+
this.signer,
|
|
104
|
+
this.options,
|
|
105
|
+
paymentRequirements,
|
|
106
|
+
result,
|
|
107
|
+
context
|
|
108
|
+
);
|
|
109
|
+
if (eip2612Extensions) {
|
|
110
|
+
return {
|
|
111
|
+
...result,
|
|
112
|
+
extensions: eip2612Extensions
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const erc20Extensions = await trySignErc20ApprovalExtension(
|
|
116
|
+
this.signer,
|
|
117
|
+
this.options,
|
|
118
|
+
paymentRequirements,
|
|
119
|
+
context
|
|
120
|
+
);
|
|
121
|
+
if (erc20Extensions) {
|
|
122
|
+
return {
|
|
123
|
+
...result,
|
|
124
|
+
extensions: erc20Extensions
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// src/exact/client/register.ts
|
|
134
|
+
function registerExactEvmScheme(client, config) {
|
|
135
|
+
const evmScheme = new ExactEvmScheme(config.signer, config.schemeOptions);
|
|
136
|
+
if (config.networks && config.networks.length > 0) {
|
|
137
|
+
config.networks.forEach((network) => {
|
|
138
|
+
client.register(network, evmScheme);
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
client.register("eip155:*", evmScheme);
|
|
142
|
+
}
|
|
143
|
+
NETWORKS.forEach((network) => {
|
|
144
|
+
client.registerV1(network, new ExactEvmSchemeV1(config.signer));
|
|
145
|
+
});
|
|
146
|
+
if (config.policies) {
|
|
147
|
+
config.policies.forEach((policy) => {
|
|
148
|
+
client.registerPolicy(policy);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return client;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export {
|
|
155
|
+
ExactEvmScheme,
|
|
156
|
+
registerExactEvmScheme
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=chunk-FQJR4RCF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exact/client/eip3009.ts","../../src/exact/client/scheme.ts","../../src/exact/client/register.ts"],"sourcesContent":["import { PaymentRequirements, PaymentPayloadResult } from \"@payai/x402/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 {\n SchemeNetworkClient,\n PaymentRequirements,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@payai/x402/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { AssetTransferMethod } from \"../../types\";\nimport { createEIP3009Payload } from \"./eip3009\";\nimport { createPermit2Payload } from \"./permit2\";\nimport {\n trySignEip2612PermitExtension,\n trySignErc20ApprovalExtension,\n} from \"../../shared/extensions\";\nimport { ExactEvmSchemeOptions } from \"./rpc\";\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 * Base flow only requires `address` + `signTypedData`.\n * Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally\n * requires optional capabilities like `readContract` and tx signing helpers.\n * @param options - Optional RPC configuration used to backfill extension capabilities.\n */\n constructor(\n private readonly signer: ClientEvmSigner,\n private readonly options?: ExactEvmSchemeOptions,\n ) {}\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 const eip2612Extensions = await trySignEip2612PermitExtension(\n this.signer,\n this.options,\n paymentRequirements,\n result,\n context,\n );\n\n if (eip2612Extensions) {\n return {\n ...result,\n extensions: eip2612Extensions,\n };\n }\n\n const erc20Extensions = await trySignErc20ApprovalExtension(\n this.signer,\n this.options,\n paymentRequirements,\n context,\n );\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","import { x402Client, SelectPaymentRequirements, PaymentPolicy } from \"@payai/x402/client\";\nimport { Network } from \"@payai/x402/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmScheme } from \"./scheme\";\nimport { ExactEvmSchemeOptions } from \"./rpc\";\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 Exact EVM client scheme options.\n * Supports either a single config ({ rpcUrl }) or per-chain configs\n * keyed by EVM chain ID ({ 8453: { rpcUrl: \"...\" } }).\n */\n schemeOptions?: ExactEvmSchemeOptions;\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 \"@payai/x402-evm/exact/client/register\";\n * import { x402Client } from \"@payai/x402/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, config.schemeOptions);\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":[]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
trySignEip2612PermitExtension,
|
|
3
|
+
trySignErc20ApprovalExtension
|
|
4
|
+
} from "./chunk-WKBC5YMI.mjs";
|
|
5
|
+
import {
|
|
6
|
+
PERMIT2_ADDRESS,
|
|
7
|
+
createPermit2Nonce,
|
|
8
|
+
getEvmChainId,
|
|
9
|
+
uptoPermit2WitnessTypes,
|
|
10
|
+
x402UptoPermit2ProxyAddress
|
|
11
|
+
} from "./chunk-C4ZQMS77.mjs";
|
|
12
|
+
|
|
13
|
+
// src/upto/client/permit2.ts
|
|
14
|
+
import { getAddress } from "viem";
|
|
15
|
+
async function createUptoPermit2Payload(signer, x402Version, paymentRequirements) {
|
|
16
|
+
const facilitatorAddress = paymentRequirements.extra?.facilitatorAddress;
|
|
17
|
+
if (!facilitatorAddress) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
"upto scheme requires facilitatorAddress in paymentRequirements.extra. Ensure the server is configured with an upto facilitator that provides getExtra()."
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
23
|
+
const nonce = createPermit2Nonce();
|
|
24
|
+
const validAfter = (now - 600).toString();
|
|
25
|
+
const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();
|
|
26
|
+
if (BigInt(deadline) <= BigInt(validAfter)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Invalid time window: deadline (${deadline}) must be after validAfter (${validAfter}). Check that maxTimeoutSeconds (${paymentRequirements.maxTimeoutSeconds}) is positive.`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
const permit2Authorization = {
|
|
32
|
+
from: signer.address,
|
|
33
|
+
permitted: {
|
|
34
|
+
token: getAddress(paymentRequirements.asset),
|
|
35
|
+
amount: paymentRequirements.amount
|
|
36
|
+
},
|
|
37
|
+
spender: x402UptoPermit2ProxyAddress,
|
|
38
|
+
nonce,
|
|
39
|
+
deadline,
|
|
40
|
+
witness: {
|
|
41
|
+
to: getAddress(paymentRequirements.payTo),
|
|
42
|
+
facilitator: getAddress(facilitatorAddress),
|
|
43
|
+
validAfter
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const chainId = getEvmChainId(paymentRequirements.network);
|
|
47
|
+
const signature = await signer.signTypedData({
|
|
48
|
+
domain: { name: "Permit2", chainId, verifyingContract: PERMIT2_ADDRESS },
|
|
49
|
+
types: uptoPermit2WitnessTypes,
|
|
50
|
+
primaryType: "PermitWitnessTransferFrom",
|
|
51
|
+
message: {
|
|
52
|
+
permitted: {
|
|
53
|
+
token: getAddress(permit2Authorization.permitted.token),
|
|
54
|
+
amount: BigInt(permit2Authorization.permitted.amount)
|
|
55
|
+
},
|
|
56
|
+
spender: getAddress(permit2Authorization.spender),
|
|
57
|
+
nonce: BigInt(permit2Authorization.nonce),
|
|
58
|
+
deadline: BigInt(permit2Authorization.deadline),
|
|
59
|
+
witness: {
|
|
60
|
+
to: getAddress(permit2Authorization.witness.to),
|
|
61
|
+
facilitator: getAddress(permit2Authorization.witness.facilitator),
|
|
62
|
+
validAfter: BigInt(permit2Authorization.witness.validAfter)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
x402Version,
|
|
68
|
+
payload: { signature, permit2Authorization }
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/upto/client/scheme.ts
|
|
73
|
+
var UptoEvmScheme = class {
|
|
74
|
+
/**
|
|
75
|
+
* Creates a new UptoEvmScheme instance.
|
|
76
|
+
*
|
|
77
|
+
* @param signer - The EVM signer for client operations
|
|
78
|
+
* @param options - Optional RPC configuration
|
|
79
|
+
*/
|
|
80
|
+
constructor(signer, options) {
|
|
81
|
+
this.signer = signer;
|
|
82
|
+
this.options = options;
|
|
83
|
+
this.scheme = "upto";
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a payment payload for the Upto scheme using Permit2.
|
|
87
|
+
*
|
|
88
|
+
* @param x402Version - The x402 protocol version
|
|
89
|
+
* @param paymentRequirements - The payment requirements
|
|
90
|
+
* @param context - Optional context with server-declared extensions
|
|
91
|
+
* @returns Promise resolving to a payment payload result
|
|
92
|
+
*/
|
|
93
|
+
async createPaymentPayload(x402Version, paymentRequirements, context) {
|
|
94
|
+
const result = await createUptoPermit2Payload(this.signer, x402Version, paymentRequirements);
|
|
95
|
+
const eip2612Extensions = await trySignEip2612PermitExtension(
|
|
96
|
+
this.signer,
|
|
97
|
+
this.options,
|
|
98
|
+
paymentRequirements,
|
|
99
|
+
result,
|
|
100
|
+
context
|
|
101
|
+
);
|
|
102
|
+
if (eip2612Extensions) {
|
|
103
|
+
return { ...result, extensions: eip2612Extensions };
|
|
104
|
+
}
|
|
105
|
+
const erc20Extensions = await trySignErc20ApprovalExtension(
|
|
106
|
+
this.signer,
|
|
107
|
+
this.options,
|
|
108
|
+
paymentRequirements,
|
|
109
|
+
context
|
|
110
|
+
);
|
|
111
|
+
if (erc20Extensions) {
|
|
112
|
+
return { ...result, extensions: erc20Extensions };
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
UptoEvmScheme
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=chunk-GJ57SZGI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/upto/client/permit2.ts","../../src/upto/client/scheme.ts"],"sourcesContent":["import { PaymentRequirements, PaymentPayloadResult } from \"@payai/x402/types\";\nimport {\n PERMIT2_ADDRESS,\n uptoPermit2WitnessTypes,\n x402UptoPermit2ProxyAddress,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { UptoPermit2Authorization } from \"../../types\";\nimport { createPermit2Nonce, getEvmChainId } from \"../../utils\";\nimport { getAddress } from \"viem\";\n\n// Re-export Permit2-generic approval helpers\nexport { createPermit2ApprovalTx, getPermit2AllowanceReadParams } from \"../../exact/client/permit2\";\nexport type { Permit2AllowanceParams } from \"../../exact/client/permit2\";\n\n/**\n * Creates a signed upto Permit2 payment payload for the given requirements.\n *\n * Constructs a Permit2 authorization with an upto witness (including facilitator address)\n * and signs it using EIP-712 typed data.\n *\n * @param signer - The EVM client signer for signing typed data\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements including asset, amount, and payTo\n * @returns Promise resolving to a payment payload result with the signed authorization\n */\nexport async function createUptoPermit2Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const facilitatorAddress = paymentRequirements.extra?.facilitatorAddress as\n | `0x${string}`\n | undefined;\n if (!facilitatorAddress) {\n throw new Error(\n \"upto scheme requires facilitatorAddress in paymentRequirements.extra. \" +\n \"Ensure the server is configured with an upto facilitator that provides getExtra().\",\n );\n }\n\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n const validAfter = (now - 600).toString();\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n if (BigInt(deadline) <= BigInt(validAfter)) {\n throw new Error(\n `Invalid time window: deadline (${deadline}) must be after validAfter (${validAfter}). ` +\n `Check that maxTimeoutSeconds (${paymentRequirements.maxTimeoutSeconds}) is positive.`,\n );\n }\n\n const permit2Authorization: UptoPermit2Authorization & { from: `0x${string}` } = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: x402UptoPermit2ProxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n facilitator: getAddress(facilitatorAddress),\n validAfter,\n },\n };\n\n const chainId = getEvmChainId(paymentRequirements.network);\n\n const signature = await signer.signTypedData({\n domain: { name: \"Permit2\", chainId, verifyingContract: PERMIT2_ADDRESS },\n types: uptoPermit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n 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 facilitator: getAddress(permit2Authorization.witness.facilitator),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n },\n },\n });\n\n return {\n x402Version,\n payload: { signature, permit2Authorization },\n };\n}\n","import {\n SchemeNetworkClient,\n PaymentRequirements,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@payai/x402/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { createUptoPermit2Payload } from \"./permit2\";\nimport {\n trySignEip2612PermitExtension,\n trySignErc20ApprovalExtension,\n} from \"../../shared/extensions\";\nimport { UptoEvmSchemeOptions } from \"./rpc\";\n\n/**\n * EVM client implementation for the Upto payment scheme.\n * Handles Permit2-based payment payload creation and gas-sponsoring extensions.\n */\nexport class UptoEvmScheme implements SchemeNetworkClient {\n readonly scheme = \"upto\";\n\n /**\n * Creates a new UptoEvmScheme instance.\n *\n * @param signer - The EVM signer for client operations\n * @param options - Optional RPC configuration\n */\n constructor(\n private readonly signer: ClientEvmSigner,\n private readonly options?: UptoEvmSchemeOptions,\n ) {}\n\n /**\n * Creates a payment payload for the Upto scheme using Permit2.\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\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n const result = await createUptoPermit2Payload(this.signer, x402Version, paymentRequirements);\n\n const eip2612Extensions = await trySignEip2612PermitExtension(\n this.signer,\n this.options,\n paymentRequirements,\n result,\n context,\n );\n if (eip2612Extensions) {\n return { ...result, extensions: eip2612Extensions };\n }\n\n const erc20Extensions = await trySignErc20ApprovalExtension(\n this.signer,\n this.options,\n paymentRequirements,\n context,\n );\n if (erc20Extensions) {\n return { ...result, extensions: erc20Extensions };\n }\n\n return result;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AASA,SAAS,kBAAkB;AAiB3B,eAAsB,yBACpB,QACA,aACA,qBAC+B;AAC/B,QAAM,qBAAqB,oBAAoB,OAAO;AAGtD,MAAI,CAAC,oBAAoB;AACvB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,QAAQ,mBAAmB;AACjC,QAAM,cAAc,MAAM,KAAK,SAAS;AACxC,QAAM,YAAY,MAAM,oBAAoB,mBAAmB,SAAS;AAExE,MAAI,OAAO,QAAQ,KAAK,OAAO,UAAU,GAAG;AAC1C,UAAM,IAAI;AAAA,MACR,kCAAkC,QAAQ,+BAA+B,UAAU,oCAChD,oBAAoB,iBAAiB;AAAA,IAC1E;AAAA,EACF;AAEA,QAAM,uBAA2E;AAAA,IAC/E,MAAM,OAAO;AAAA,IACb,WAAW;AAAA,MACT,OAAO,WAAW,oBAAoB,KAAK;AAAA,MAC3C,QAAQ,oBAAoB;AAAA,IAC9B;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,SAAS;AAAA,MACP,IAAI,WAAW,oBAAoB,KAAK;AAAA,MACxC,aAAa,WAAW,kBAAkB;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,cAAc,oBAAoB,OAAO;AAEzD,QAAM,YAAY,MAAM,OAAO,cAAc;AAAA,IAC3C,QAAQ,EAAE,MAAM,WAAW,SAAS,mBAAmB,gBAAgB;AAAA,IACvE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,SAAS;AAAA,MACP,WAAW;AAAA,QACT,OAAO,WAAW,qBAAqB,UAAU,KAAK;AAAA,QACtD,QAAQ,OAAO,qBAAqB,UAAU,MAAM;AAAA,MACtD;AAAA,MACA,SAAS,WAAW,qBAAqB,OAAO;AAAA,MAChD,OAAO,OAAO,qBAAqB,KAAK;AAAA,MACxC,UAAU,OAAO,qBAAqB,QAAQ;AAAA,MAC9C,SAAS;AAAA,QACP,IAAI,WAAW,qBAAqB,QAAQ,EAAE;AAAA,QAC9C,aAAa,WAAW,qBAAqB,QAAQ,WAAW;AAAA,QAChE,YAAY,OAAO,qBAAqB,QAAQ,UAAU;AAAA,MAC5D;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA,SAAS,EAAE,WAAW,qBAAqB;AAAA,EAC7C;AACF;;;AC7EO,IAAM,gBAAN,MAAmD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASxD,YACmB,QACA,SACjB;AAFiB;AACA;AAVnB,SAAS,SAAS;AAAA,EAWf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUH,MAAM,qBACJ,aACA,qBACA,SAC+B;AAC/B,UAAM,SAAS,MAAM,yBAAyB,KAAK,QAAQ,aAAa,mBAAmB;AAE3F,UAAM,oBAAoB,MAAM;AAAA,MAC9B,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,mBAAmB;AACrB,aAAO,EAAE,GAAG,QAAQ,YAAY,kBAAkB;AAAA,IACpD;AAEA,UAAM,kBAAkB,MAAM;AAAA,MAC5B,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AACA,QAAI,iBAAiB;AACnB,aAAO,EAAE,GAAG,QAAQ,YAAY,gBAAgB;AAAA,IAClD;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
function isPermit2Payload(payload) {
|
|
3
|
+
return "permit2Authorization" in payload;
|
|
4
|
+
}
|
|
5
|
+
function isEIP3009Payload(payload) {
|
|
6
|
+
return "authorization" in payload;
|
|
7
|
+
}
|
|
8
|
+
function isUptoPermit2Payload(payload) {
|
|
9
|
+
if (typeof payload.signature !== "string") return false;
|
|
10
|
+
if (!("permit2Authorization" in payload)) return false;
|
|
11
|
+
const auth = payload.permit2Authorization;
|
|
12
|
+
if (typeof auth !== "object" || auth === null) return false;
|
|
13
|
+
const a = auth;
|
|
14
|
+
if (typeof a.from !== "string") return false;
|
|
15
|
+
if (typeof a.spender !== "string") return false;
|
|
16
|
+
if (typeof a.nonce !== "string") return false;
|
|
17
|
+
if (typeof a.deadline !== "string") return false;
|
|
18
|
+
const permitted = a.permitted;
|
|
19
|
+
if (typeof permitted !== "object" || permitted === null) return false;
|
|
20
|
+
const p = permitted;
|
|
21
|
+
if (typeof p.token !== "string") return false;
|
|
22
|
+
if (typeof p.amount !== "string") return false;
|
|
23
|
+
const witness = a.witness;
|
|
24
|
+
if (typeof witness !== "object" || witness === null) return false;
|
|
25
|
+
const w = witness;
|
|
26
|
+
return typeof w.facilitator === "string" && typeof w.to === "string" && typeof w.validAfter === "string";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
isPermit2Payload,
|
|
31
|
+
isEIP3009Payload,
|
|
32
|
+
isUptoPermit2Payload
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=chunk-JII456TS.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\n/**\n * Upto Permit2 witness — includes `facilitator` field absent from exact witness.\n * Only the address matching `witness.facilitator` can call settle() on-chain.\n */\nexport type UptoPermit2Witness = {\n to: `0x${string}`;\n facilitator: `0x${string}`;\n validAfter: string;\n};\n\nexport type UptoPermit2Authorization = {\n permitted: {\n token: `0x${string}`;\n amount: string;\n };\n spender: `0x${string}`;\n nonce: string;\n deadline: string;\n witness: UptoPermit2Witness;\n};\n\nexport type UptoPermit2Payload = {\n signature: `0x${string}`;\n permit2Authorization: UptoPermit2Authorization & {\n from: `0x${string}`;\n };\n};\n\n/**\n * Type guard to check if a payload is an upto Permit2 payload.\n * Validates structural presence of all required fields: signature, permit2Authorization\n * (with from, permitted, spender, nonce, deadline), and a witness containing facilitator.\n *\n * @param payload - The payload to check\n * @returns True if the payload is an upto Permit2 payload, false otherwise\n */\nexport function isUptoPermit2Payload(\n payload: Record<string, unknown>,\n): payload is UptoPermit2Payload {\n if (typeof payload.signature !== \"string\") return false;\n if (!(\"permit2Authorization\" in payload)) return false;\n\n const auth = payload.permit2Authorization;\n if (typeof auth !== \"object\" || auth === null) return false;\n\n const a = auth as Record<string, unknown>;\n if (typeof a.from !== \"string\") return false;\n if (typeof a.spender !== \"string\") return false;\n if (typeof a.nonce !== \"string\") return false;\n if (typeof a.deadline !== \"string\") return false;\n\n const permitted = a.permitted;\n if (typeof permitted !== \"object\" || permitted === null) return false;\n const p = permitted as Record<string, unknown>;\n if (typeof p.token !== \"string\") return false;\n if (typeof p.amount !== \"string\") return false;\n\n const witness = a.witness;\n if (typeof witness !== \"object\" || witness === null) return false;\n const w = witness as Record<string, unknown>;\n return (\n typeof w.facilitator === \"string\" &&\n typeof w.to === \"string\" &&\n typeof w.validAfter === \"string\"\n );\n}\n"],"mappings":";AAoEO,SAAS,iBAAiB,SAA4D;AAC3F,SAAO,0BAA0B;AACnC;AASO,SAAS,iBAAiB,SAA4D;AAC3F,SAAO,mBAAmB;AAC5B;AAsCO,SAAS,qBACd,SAC+B;AAC/B,MAAI,OAAO,QAAQ,cAAc,SAAU,QAAO;AAClD,MAAI,EAAE,0BAA0B,SAAU,QAAO;AAEjD,QAAM,OAAO,QAAQ;AACrB,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AAEtD,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,SAAS,SAAU,QAAO;AACvC,MAAI,OAAO,EAAE,YAAY,SAAU,QAAO;AAC1C,MAAI,OAAO,EAAE,UAAU,SAAU,QAAO;AACxC,MAAI,OAAO,EAAE,aAAa,SAAU,QAAO;AAE3C,QAAM,YAAY,EAAE;AACpB,MAAI,OAAO,cAAc,YAAY,cAAc,KAAM,QAAO;AAChE,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,UAAU,SAAU,QAAO;AACxC,MAAI,OAAO,EAAE,WAAW,SAAU,QAAO;AAEzC,QAAM,UAAU,EAAE;AAClB,MAAI,OAAO,YAAY,YAAY,YAAY,KAAM,QAAO;AAC5D,QAAM,IAAI;AACV,SACE,OAAO,EAAE,gBAAgB,YACzB,OAAO,EAAE,OAAO,YAChB,OAAO,EAAE,eAAe;AAE5B;","names":[]}
|