@wtflabs/x402 0.0.1-beta.10 → 0.0.1-beta.13
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/facilitator/index.js +1 -1
- package/dist/cjs/facilitator/index.js.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/schemes/index.d.ts +10 -7
- package/dist/cjs/schemes/index.js +181 -9
- package/dist/cjs/schemes/index.js.map +1 -1
- package/dist/esm/{chunk-XGQBEMP7.mjs → chunk-H4GSYKL2.mjs} +183 -11
- package/dist/esm/chunk-H4GSYKL2.mjs.map +1 -0
- package/dist/esm/{chunk-LXLCF4IW.mjs → chunk-KCTRIOXS.mjs} +2 -2
- package/dist/esm/facilitator/index.mjs +2 -2
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/schemes/index.d.mts +10 -7
- package/dist/esm/schemes/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/esm/chunk-XGQBEMP7.mjs.map +0 -1
- /package/dist/esm/{chunk-LXLCF4IW.mjs.map → chunk-KCTRIOXS.mjs.map} +0 -0
|
@@ -353,27 +353,30 @@ interface TokenPaymentCapabilities {
|
|
|
353
353
|
};
|
|
354
354
|
}
|
|
355
355
|
/**
|
|
356
|
-
*
|
|
356
|
+
* Detect the payment methods supported by the token
|
|
357
357
|
*
|
|
358
358
|
* @param tokenAddress - token address
|
|
359
359
|
* @param client - viem PublicClient
|
|
360
|
-
* @returns
|
|
360
|
+
* @returns detection result
|
|
361
361
|
*/
|
|
362
362
|
declare function detectTokenPaymentMethods(tokenAddress: string, client: PublicClient): Promise<TokenPaymentCapabilities>;
|
|
363
363
|
/**
|
|
364
|
-
*
|
|
364
|
+
* Get the recommended payment method (only return types supported by the schema)
|
|
365
|
+
* Sort by priority: eip3009 > permit > permit2
|
|
366
|
+
* Note: permit2-witness is mapped to permit2 because they are the same payment type in the schema
|
|
365
367
|
*
|
|
366
368
|
* @param tokenAddress - token address
|
|
367
369
|
* @param client - viem PublicClient
|
|
368
|
-
* @returns
|
|
370
|
+
* @returns recommended payment method
|
|
369
371
|
*/
|
|
370
|
-
declare function getRecommendedPaymentMethod(tokenAddress: string, client: PublicClient): Promise<"eip3009" | "
|
|
372
|
+
declare function getRecommendedPaymentMethod(tokenAddress: string, client: PublicClient): Promise<"eip3009" | "permit2" | "permit" | null>;
|
|
371
373
|
/**
|
|
372
|
-
*
|
|
374
|
+
* Get the name and version information of the token (for EIP-712 signing)
|
|
375
|
+
* Supports proxy contracts (will automatically read from the proxy contract, because the proxy contract will delegatecall to the implementation contract)
|
|
373
376
|
*
|
|
374
377
|
* @param tokenAddress - token address
|
|
375
378
|
* @param client - viem PublicClient
|
|
376
|
-
* @returns
|
|
379
|
+
* @returns name and version information of the token
|
|
377
380
|
*/
|
|
378
381
|
declare function getTokenInfo(tokenAddress: string, client: PublicClient): Promise<TokenInfo>;
|
|
379
382
|
|
|
@@ -1996,7 +1996,7 @@ async function settle(wallet, paymentPayload, paymentRequirements) {
|
|
|
1996
1996
|
// token
|
|
1997
1997
|
payload.authorization.from,
|
|
1998
1998
|
// payer
|
|
1999
|
-
|
|
1999
|
+
paymentRequirements.payTo,
|
|
2000
2000
|
// seller
|
|
2001
2001
|
BigInt(payload.authorization.value),
|
|
2002
2002
|
// amount
|
|
@@ -2955,14 +2955,104 @@ async function createPaymentHeader3(client, x402Version, paymentRequirements) {
|
|
|
2955
2955
|
}
|
|
2956
2956
|
|
|
2957
2957
|
// src/schemes/exact/evm/utils/tokenDetection.ts
|
|
2958
|
+
var paymentMethodsCache = /* @__PURE__ */ new Map();
|
|
2959
|
+
var recommendedMethodCache = /* @__PURE__ */ new Map();
|
|
2960
|
+
var PRESET_TOKEN_CAPABILITIES = {
|
|
2961
|
+
// World Liberty Financial USD - 只支持 permit
|
|
2962
|
+
"0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d": {
|
|
2963
|
+
supportedMethods: ["permit"],
|
|
2964
|
+
supportedNetworks: [56],
|
|
2965
|
+
description: "World Liberty Financial USD (WLFI)"
|
|
2966
|
+
}
|
|
2967
|
+
// 可以继续添加更多预设代币
|
|
2968
|
+
// 示例:
|
|
2969
|
+
// "0x其他代币地址": {
|
|
2970
|
+
// supportedMethods: ["eip3009", "permit"],
|
|
2971
|
+
// description: "代币名称",
|
|
2972
|
+
// },
|
|
2973
|
+
};
|
|
2958
2974
|
var EIP3009_SIGNATURES = ["0xe3ee160e", "0xcf092995"];
|
|
2959
2975
|
var EIP2612_PERMIT = "0xd505accf";
|
|
2960
2976
|
var PERMIT2_ADDRESS2 = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
2977
|
+
var EIP1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
|
|
2978
|
+
var EIP1822_IMPLEMENTATION_SLOT = "0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3";
|
|
2979
|
+
async function getImplementationAddress(client, proxyAddress) {
|
|
2980
|
+
try {
|
|
2981
|
+
try {
|
|
2982
|
+
const implSlotData = await client.getStorageAt({
|
|
2983
|
+
address: proxyAddress,
|
|
2984
|
+
slot: EIP1967_IMPLEMENTATION_SLOT
|
|
2985
|
+
});
|
|
2986
|
+
if (implSlotData && implSlotData !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
2987
|
+
const implAddress = `0x${implSlotData.slice(-40)}`;
|
|
2988
|
+
if (implAddress !== "0x0000000000000000000000000000000000000000") {
|
|
2989
|
+
console.log(` \u{1F4E6} Detected EIP-1967 proxy, implementation: ${implAddress}`);
|
|
2990
|
+
return implAddress;
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
} catch {
|
|
2994
|
+
}
|
|
2995
|
+
try {
|
|
2996
|
+
const uupsSlotData = await client.getStorageAt({
|
|
2997
|
+
address: proxyAddress,
|
|
2998
|
+
slot: EIP1822_IMPLEMENTATION_SLOT
|
|
2999
|
+
});
|
|
3000
|
+
if (uupsSlotData && uupsSlotData !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
3001
|
+
const implAddress = `0x${uupsSlotData.slice(-40)}`;
|
|
3002
|
+
if (implAddress !== "0x0000000000000000000000000000000000000000") {
|
|
3003
|
+
console.log(` \u{1F4E6} Detected EIP-1822 UUPS proxy, implementation: ${implAddress}`);
|
|
3004
|
+
return implAddress;
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
} catch {
|
|
3008
|
+
}
|
|
3009
|
+
try {
|
|
3010
|
+
const implABI = [
|
|
3011
|
+
{
|
|
3012
|
+
inputs: [],
|
|
3013
|
+
name: "implementation",
|
|
3014
|
+
outputs: [{ name: "", type: "address" }],
|
|
3015
|
+
stateMutability: "view",
|
|
3016
|
+
type: "function"
|
|
3017
|
+
}
|
|
3018
|
+
];
|
|
3019
|
+
const implAddress = await client.readContract({
|
|
3020
|
+
address: proxyAddress,
|
|
3021
|
+
abi: implABI,
|
|
3022
|
+
functionName: "implementation"
|
|
3023
|
+
});
|
|
3024
|
+
if (implAddress && implAddress !== "0x0000000000000000000000000000000000000000") {
|
|
3025
|
+
console.log(` \u{1F4E6} Detected proxy via implementation(), implementation: ${implAddress}`);
|
|
3026
|
+
return implAddress;
|
|
3027
|
+
}
|
|
3028
|
+
} catch {
|
|
3029
|
+
}
|
|
3030
|
+
return null;
|
|
3031
|
+
} catch (error) {
|
|
3032
|
+
console.error("Error detecting proxy implementation:", error);
|
|
3033
|
+
return null;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
2961
3036
|
async function hasMethod(client, tokenAddress, methodSelector) {
|
|
2962
3037
|
try {
|
|
2963
3038
|
const code = await client.getBytecode({ address: tokenAddress });
|
|
2964
3039
|
if (!code) return false;
|
|
2965
|
-
|
|
3040
|
+
const hasMethodInProxy = code.toLowerCase().includes(methodSelector.slice(2).toLowerCase());
|
|
3041
|
+
if (hasMethodInProxy) {
|
|
3042
|
+
return true;
|
|
3043
|
+
}
|
|
3044
|
+
const implAddress = await getImplementationAddress(client, tokenAddress);
|
|
3045
|
+
if (implAddress) {
|
|
3046
|
+
const implCode = await client.getBytecode({ address: implAddress });
|
|
3047
|
+
if (implCode) {
|
|
3048
|
+
const hasMethodInImpl = implCode.toLowerCase().includes(methodSelector.slice(2).toLowerCase());
|
|
3049
|
+
if (hasMethodInImpl) {
|
|
3050
|
+
console.log(` \u2705 Method ${methodSelector} found in implementation contract`);
|
|
3051
|
+
}
|
|
3052
|
+
return hasMethodInImpl;
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
return false;
|
|
2966
3056
|
} catch (error) {
|
|
2967
3057
|
console.error(`Error checking method ${methodSelector}:`, error);
|
|
2968
3058
|
return false;
|
|
@@ -2973,7 +3063,27 @@ async function hasAnyMethod(client, tokenAddress, methodSelectors) {
|
|
|
2973
3063
|
const code = await client.getBytecode({ address: tokenAddress });
|
|
2974
3064
|
if (!code) return false;
|
|
2975
3065
|
const codeLower = code.toLowerCase();
|
|
2976
|
-
|
|
3066
|
+
const hasMethodInProxy = methodSelectors.some(
|
|
3067
|
+
(selector) => codeLower.includes(selector.slice(2).toLowerCase())
|
|
3068
|
+
);
|
|
3069
|
+
if (hasMethodInProxy) {
|
|
3070
|
+
return true;
|
|
3071
|
+
}
|
|
3072
|
+
const implAddress = await getImplementationAddress(client, tokenAddress);
|
|
3073
|
+
if (implAddress) {
|
|
3074
|
+
const implCode = await client.getBytecode({ address: implAddress });
|
|
3075
|
+
if (implCode) {
|
|
3076
|
+
const implCodeLower = implCode.toLowerCase();
|
|
3077
|
+
const hasMethodInImpl = methodSelectors.some(
|
|
3078
|
+
(selector) => implCodeLower.includes(selector.slice(2).toLowerCase())
|
|
3079
|
+
);
|
|
3080
|
+
if (hasMethodInImpl) {
|
|
3081
|
+
console.log(` \u2705 Method(s) found in implementation contract`);
|
|
3082
|
+
}
|
|
3083
|
+
return hasMethodInImpl;
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
return false;
|
|
2977
3087
|
} catch (error) {
|
|
2978
3088
|
console.error(`Error checking methods ${methodSelectors.join(", ")}:`, error);
|
|
2979
3089
|
return false;
|
|
@@ -2991,6 +3101,48 @@ async function checkPermit2Support(client) {
|
|
|
2991
3101
|
}
|
|
2992
3102
|
async function detectTokenPaymentMethods(tokenAddress, client) {
|
|
2993
3103
|
const address = tokenAddress.toLowerCase();
|
|
3104
|
+
const chainId = await client.getChainId();
|
|
3105
|
+
const cacheKey = `${chainId}:${address}`;
|
|
3106
|
+
const cached = paymentMethodsCache.get(cacheKey);
|
|
3107
|
+
if (cached) {
|
|
3108
|
+
console.log(`\u{1F4BE} Using cached payment methods for token ${address}`);
|
|
3109
|
+
return cached;
|
|
3110
|
+
}
|
|
3111
|
+
const presetCapabilities = PRESET_TOKEN_CAPABILITIES[address];
|
|
3112
|
+
if (presetCapabilities) {
|
|
3113
|
+
if (!chainId || !presetCapabilities.supportedNetworks.includes(chainId)) {
|
|
3114
|
+
return {
|
|
3115
|
+
address,
|
|
3116
|
+
supportedMethods: [],
|
|
3117
|
+
details: {
|
|
3118
|
+
hasEIP3009: false,
|
|
3119
|
+
hasPermit: false,
|
|
3120
|
+
hasPermit2Approval: false
|
|
3121
|
+
}
|
|
3122
|
+
};
|
|
3123
|
+
}
|
|
3124
|
+
const hasEIP30092 = presetCapabilities.supportedMethods.includes("eip3009");
|
|
3125
|
+
const hasPermit2 = presetCapabilities.supportedMethods.includes("permit");
|
|
3126
|
+
const hasPermit2Approval2 = presetCapabilities.supportedMethods.includes("permit2") || presetCapabilities.supportedMethods.includes("permit2-witness");
|
|
3127
|
+
if (hasEIP30092) {
|
|
3128
|
+
console.log(" \u2705 EIP-3009 (transferWithAuthorization) - from preset");
|
|
3129
|
+
}
|
|
3130
|
+
if (hasPermit2) {
|
|
3131
|
+
console.log(" \u2705 EIP-2612 (permit) - from preset");
|
|
3132
|
+
}
|
|
3133
|
+
if (hasPermit2Approval2) {
|
|
3134
|
+
console.log(" \u2705 Permit2 support - from preset");
|
|
3135
|
+
}
|
|
3136
|
+
return {
|
|
3137
|
+
address,
|
|
3138
|
+
supportedMethods: presetCapabilities.supportedMethods,
|
|
3139
|
+
details: {
|
|
3140
|
+
hasEIP3009: hasEIP30092,
|
|
3141
|
+
hasPermit: hasPermit2,
|
|
3142
|
+
hasPermit2Approval: hasPermit2Approval2
|
|
3143
|
+
}
|
|
3144
|
+
};
|
|
3145
|
+
}
|
|
2994
3146
|
console.log(`\u{1F50D} Detecting payment methods for token ${address}...`);
|
|
2995
3147
|
const [hasEIP3009, hasPermit, hasPermit2Approval] = await Promise.all([
|
|
2996
3148
|
hasAnyMethod(client, address, EIP3009_SIGNATURES),
|
|
@@ -3014,7 +3166,7 @@ async function detectTokenPaymentMethods(tokenAddress, client) {
|
|
|
3014
3166
|
if (supportedMethods.length === 0) {
|
|
3015
3167
|
console.log(" \u26A0\uFE0F No advanced payment methods detected (standard ERC-20 only)");
|
|
3016
3168
|
}
|
|
3017
|
-
|
|
3169
|
+
const result = {
|
|
3018
3170
|
address,
|
|
3019
3171
|
supportedMethods,
|
|
3020
3172
|
details: {
|
|
@@ -3023,16 +3175,30 @@ async function detectTokenPaymentMethods(tokenAddress, client) {
|
|
|
3023
3175
|
hasPermit2Approval
|
|
3024
3176
|
}
|
|
3025
3177
|
};
|
|
3178
|
+
paymentMethodsCache.set(cacheKey, result);
|
|
3179
|
+
return result;
|
|
3026
3180
|
}
|
|
3027
3181
|
async function getRecommendedPaymentMethod(tokenAddress, client) {
|
|
3182
|
+
const address = tokenAddress.toLowerCase();
|
|
3183
|
+
const chainId = await client.getChainId();
|
|
3184
|
+
const cacheKey = `${chainId}:${address}`;
|
|
3185
|
+
const cached = recommendedMethodCache.get(cacheKey);
|
|
3186
|
+
if (cached !== void 0) {
|
|
3187
|
+
console.log(`\u{1F4BE} Using cached recommended method for token ${address}`);
|
|
3188
|
+
return cached;
|
|
3189
|
+
}
|
|
3028
3190
|
const capabilities = await detectTokenPaymentMethods(tokenAddress, client);
|
|
3029
3191
|
const { supportedMethods } = capabilities;
|
|
3030
|
-
|
|
3031
|
-
if (supportedMethods.includes("
|
|
3032
|
-
|
|
3033
|
-
|
|
3192
|
+
let result = null;
|
|
3193
|
+
if (supportedMethods.includes("eip3009")) {
|
|
3194
|
+
result = "eip3009";
|
|
3195
|
+
} else if (supportedMethods.includes("permit")) {
|
|
3196
|
+
result = "permit";
|
|
3197
|
+
} else if (supportedMethods.includes("permit2") || supportedMethods.includes("permit2-witness")) {
|
|
3198
|
+
result = "permit2";
|
|
3034
3199
|
}
|
|
3035
|
-
|
|
3200
|
+
recommendedMethodCache.set(cacheKey, result);
|
|
3201
|
+
return result;
|
|
3036
3202
|
}
|
|
3037
3203
|
async function getTokenInfo(tokenAddress, client) {
|
|
3038
3204
|
const address = tokenAddress.toLowerCase();
|
|
@@ -3072,6 +3238,12 @@ async function getTokenInfo(tokenAddress, client) {
|
|
|
3072
3238
|
}
|
|
3073
3239
|
];
|
|
3074
3240
|
try {
|
|
3241
|
+
const implAddress = await getImplementationAddress(client, address);
|
|
3242
|
+
if (implAddress) {
|
|
3243
|
+
console.log(
|
|
3244
|
+
` \u{1F4E6} Reading token info from proxy, actual calls will be delegated to implementation`
|
|
3245
|
+
);
|
|
3246
|
+
}
|
|
3075
3247
|
const name = await client.readContract({
|
|
3076
3248
|
address,
|
|
3077
3249
|
abi: erc20ABI,
|