@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.
@@ -353,27 +353,30 @@ interface TokenPaymentCapabilities {
353
353
  };
354
354
  }
355
355
  /**
356
- * detect the payment methods supported by the token
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 the payment capabilities of the token
360
+ * @returns detection result
361
361
  */
362
362
  declare function detectTokenPaymentMethods(tokenAddress: string, client: PublicClient): Promise<TokenPaymentCapabilities>;
363
363
  /**
364
- * get the recommended payment method for the token
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 the recommended payment method
370
+ * @returns recommended payment method
369
371
  */
370
- declare function getRecommendedPaymentMethod(tokenAddress: string, client: PublicClient): Promise<"eip3009" | "permit" | "permit2" | null>;
372
+ declare function getRecommendedPaymentMethod(tokenAddress: string, client: PublicClient): Promise<"eip3009" | "permit2" | "permit" | null>;
371
373
  /**
372
- * get the name and version information of the token (for EIP-712 signing)
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 the name and version information of the token
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
- payload.authorization.to,
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
- return code.toLowerCase().includes(methodSelector.slice(2).toLowerCase());
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
- return methodSelectors.some((selector) => codeLower.includes(selector.slice(2).toLowerCase()));
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
- return {
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
- if (supportedMethods.includes("eip3009")) return "eip3009";
3031
- if (supportedMethods.includes("permit")) return "permit";
3032
- if (supportedMethods.includes("permit2") || supportedMethods.includes("permit2-witness")) {
3033
- return "permit2";
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
- return null;
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,