four-flap-meme-sdk 1.2.53 → 1.2.55

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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * as Abis from './abis/index.js';
2
2
  export { ADDRESSES, CHAIN } from './utils/constants.js';
3
3
  export { isExclusiveOnChain, isExclusiveOffChain } from './utils/mpcExclusive.js';
4
- export { ensureSellApprovalV1, checkSellApprovalV1, ensureSellApprovalV2, checkSellApprovalV2, ensureSellApproval, checkSellApproval, ensureFlapSellApproval, checkFlapSellApproval, ensureFlapSellApprovalBatch, checkFlapSellApprovalBatch, checkAllowance, approveToken, checkAllowanceBatch, approveTokenBatch, type EnsureAllowanceBatchItemResult, type ApproveTokenBatchParams, type ApproveTokenBatchResult } from './utils/erc20.js';
4
+ export { ensureSellApprovalV1, checkSellApprovalV1, ensureSellApprovalV2, checkSellApprovalV2, ensureSellApproval, checkSellApproval, ensureFlapSellApproval, checkFlapSellApproval, ensureFlapSellApprovalBatch, checkFlapSellApprovalBatch, checkAllowance, approveToken, checkAllowanceBatch, approveTokenBatch, checkAllowanceRaw, approveTokenRaw, checkAllowanceBatchRaw, approveTokenBatchRaw, type EnsureAllowanceBatchItemResult, type ApproveTokenBatchParams, type ApproveTokenBatchRawParams, type ApproveTokenBatchResult } from './utils/erc20.js';
5
5
  export { parseFourError, type FourErrorCode } from './utils/errors.js';
6
6
  export { getTokenManagerV1, getTokenManagerV2, getTokenManagerHelper3, getTokenManagerV1Writer, getTokenManagerV2Writer, getTokenManagerHelper3Writer, getTokenManagerAddress, type ChainName } from './utils/contract-factory.js';
7
7
  export { FourClient, buildLoginMessage, type FourConfig, type GenerateNonceReq, type LoginReq, type CreateTokenReq, type CreateTokenResp } from './clients/four.js';
package/dist/index.js CHANGED
@@ -10,8 +10,10 @@ ensureSellApprovalV2, checkSellApprovalV2,
10
10
  ensureSellApproval, checkSellApproval,
11
11
  // Flap Protocol 授权
12
12
  ensureFlapSellApproval, checkFlapSellApproval, ensureFlapSellApprovalBatch, checkFlapSellApprovalBatch,
13
- // ✅ 通用授权方法(适用于 Flap、Four、V2、V3 等所有场景)
14
- checkAllowance, approveToken, checkAllowanceBatch, approveTokenBatch } from './utils/erc20.js';
13
+ // ✅ 智能路由授权方法(自动选择 spender,适用于 Flap、Four、V2、V3
14
+ checkAllowance, approveToken, checkAllowanceBatch, approveTokenBatch,
15
+ // ✅ 底层授权方法(手动指定 spender,适用于任意合约)
16
+ checkAllowanceRaw, approveTokenRaw, checkAllowanceBatchRaw, approveTokenBatchRaw } from './utils/erc20.js';
15
17
  export { parseFourError } from './utils/errors.js';
16
18
  export { getTokenManagerV1, getTokenManagerV2, getTokenManagerHelper3, getTokenManagerV1Writer, getTokenManagerV2Writer, getTokenManagerHelper3Writer, getTokenManagerAddress } from './utils/contract-factory.js';
17
19
  export { FourClient, buildLoginMessage } from './clients/four.js';
@@ -92,7 +92,18 @@ export declare function checkFlapSellApprovalBatch(chain: 'BSC' | 'BASE' | 'XLAY
92
92
  */
93
93
  export declare function batchCheckAllowances(provider: JsonRpcProvider, tokenAddress: string, owners: string[], spender: string): Promise<bigint[]>;
94
94
  /**
95
- * ✅ 通用方法:检查 ERC20 代币授权额度(只读,不发送交易)
95
+ * ✅ 智能路由:检查单个 ERC20 授权额度(自动选择 spender)
96
+ *
97
+ * @param chain - 链名称 ('BSC' | 'BASE' | 'XLAYER' | 'MORPH')
98
+ * @param platform - 平台名称 ('flap' | 'four' | 'pancake-v2' | 'pancake-v3')
99
+ * @param rpcUrl - RPC 节点地址
100
+ * @param tokenAddress - 代币合约地址
101
+ * @param ownerAddress - 代币持有者地址
102
+ * @returns 当前授权额度(bigint)
103
+ */
104
+ export declare function checkAllowance(chain: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH', platform: 'flap' | 'four' | 'pancake-v2' | 'pancake-v3', rpcUrl: string, tokenAddress: string, ownerAddress: string): Promise<bigint>;
105
+ /**
106
+ * ✅ 底层方法:检查 ERC20 代币授权额度(手动指定 spender)
96
107
  * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
97
108
  *
98
109
  * @param rpcUrl - RPC 节点地址
@@ -101,9 +112,21 @@ export declare function batchCheckAllowances(provider: JsonRpcProvider, tokenAdd
101
112
  * @param spenderAddress - 被授权的合约地址(如 Router、Portal、TokenManager 等)
102
113
  * @returns 当前授权额度(bigint)
103
114
  */
104
- export declare function checkAllowance(rpcUrl: string, tokenAddress: string, ownerAddress: string, spenderAddress: string): Promise<bigint>;
115
+ export declare function checkAllowanceRaw(rpcUrl: string, tokenAddress: string, ownerAddress: string, spenderAddress: string): Promise<bigint>;
105
116
  /**
106
- * ✅ 通用方法:授权 ERC20 代币给指定合约(自动检查,只在不足时才发送交易)
117
+ * ✅ 智能路由:授权 ERC20 代币(自动选择 spender,自动检查,只在不足时才发送交易)
118
+ *
119
+ * @param chain - 链名称 ('BSC' | 'BASE' | 'XLAYER' | 'MORPH')
120
+ * @param platform - 平台名称 ('flap' | 'four' | 'pancake-v2' | 'pancake-v3')
121
+ * @param rpcUrl - RPC 节点地址
122
+ * @param privateKey - 私钥
123
+ * @param tokenAddress - 代币合约地址
124
+ * @param amount - 授权数量(bigint),传 'max' 表示最大授权
125
+ * @returns 授权结果
126
+ */
127
+ export declare function approveToken(chain: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH', platform: 'flap' | 'four' | 'pancake-v2' | 'pancake-v3', rpcUrl: string, privateKey: string, tokenAddress: string, amount: bigint | 'max'): Promise<EnsureAllowanceResult>;
128
+ /**
129
+ * ✅ 底层方法:授权 ERC20 代币给指定合约(手动指定 spender)
107
130
  * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
108
131
  *
109
132
  * @param rpcUrl - RPC 节点地址
@@ -113,9 +136,20 @@ export declare function checkAllowance(rpcUrl: string, tokenAddress: string, own
113
136
  * @param amount - 授权数量(bigint),传 'max' 或 ethers.MaxUint256 表示最大授权
114
137
  * @returns 授权结果
115
138
  */
116
- export declare function approveToken(rpcUrl: string, privateKey: string, tokenAddress: string, spenderAddress: string, amount: bigint | 'max'): Promise<EnsureAllowanceResult>;
139
+ export declare function approveTokenRaw(rpcUrl: string, privateKey: string, tokenAddress: string, spenderAddress: string, amount: bigint | 'max'): Promise<EnsureAllowanceResult>;
117
140
  /**
118
- * ✅ 通用方法:批量检查多个钱包的授权额度(只读,不发送交易)
141
+ * ✅ 智能路由:批量检查多个钱包的授权额度(自动选择 spender)
142
+ *
143
+ * @param chain - 链名称 ('BSC' | 'BASE' | 'XLAYER' | 'MORPH')
144
+ * @param platform - 平台名称 ('flap' | 'four' | 'pancake-v2' | 'pancake-v3')
145
+ * @param rpcUrl - RPC 节点地址
146
+ * @param tokenAddress - 代币合约地址
147
+ * @param ownerAddresses - 代币持有者地址数组
148
+ * @returns 每个地址的授权额度数组
149
+ */
150
+ export declare function checkAllowanceBatch(chain: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH', platform: 'flap' | 'four' | 'pancake-v2' | 'pancake-v3', rpcUrl: string, tokenAddress: string, ownerAddresses: string[]): Promise<bigint[]>;
151
+ /**
152
+ * ✅ 底层方法:批量检查多个钱包的授权额度(手动指定 spender)
119
153
  * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
120
154
  *
121
155
  * @param rpcUrl - RPC 节点地址
@@ -124,8 +158,16 @@ export declare function approveToken(rpcUrl: string, privateKey: string, tokenAd
124
158
  * @param spenderAddress - 被授权的合约地址
125
159
  * @returns 每个地址的授权额度数组
126
160
  */
127
- export declare function checkAllowanceBatch(rpcUrl: string, tokenAddress: string, ownerAddresses: string[], spenderAddress: string): Promise<bigint[]>;
161
+ export declare function checkAllowanceBatchRaw(rpcUrl: string, tokenAddress: string, ownerAddresses: string[], spenderAddress: string): Promise<bigint[]>;
128
162
  export type ApproveTokenBatchParams = {
163
+ chain: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH';
164
+ platform: 'flap' | 'four' | 'pancake-v2' | 'pancake-v3';
165
+ rpcUrl: string;
166
+ privateKeys: string[];
167
+ tokenAddress: string;
168
+ amounts: (bigint | 'max')[];
169
+ };
170
+ export type ApproveTokenBatchRawParams = {
129
171
  rpcUrl: string;
130
172
  privateKeys: string[];
131
173
  tokenAddress: string;
@@ -145,10 +187,17 @@ export type ApproveTokenBatchResult = {
145
187
  }>;
146
188
  };
147
189
  /**
148
- * ✅ 通用方法:批量授权 ERC20 代币(自动检查,只在不足时才发送交易)
149
- * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
190
+ * ✅ 智能路由:批量授权 ERC20 代币(自动选择 spender,自动检查,只在不足时才发送交易)
150
191
  *
151
192
  * @param params - 批量授权参数
152
193
  * @returns 批量授权结果
153
194
  */
154
195
  export declare function approveTokenBatch(params: ApproveTokenBatchParams): Promise<ApproveTokenBatchResult>;
196
+ /**
197
+ * ✅ 底层方法:批量授权 ERC20 代币(手动指定 spender)
198
+ * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
199
+ *
200
+ * @param params - 批量授权参数
201
+ * @returns 批量授权结果
202
+ */
203
+ export declare function approveTokenBatchRaw(params: ApproveTokenBatchRawParams): Promise<ApproveTokenBatchResult>;
@@ -11,7 +11,11 @@ const ERC20_ABI = [
11
11
  */
12
12
  async function validateContractAddress(provider, address, label) {
13
13
  try {
14
- const code = await provider.getCode(address);
14
+ // 先规范化地址(转为 checksum 格式),避免 ethers v6 的严格校验报错
15
+ const normalizedAddress = address.toLowerCase().startsWith('0x')
16
+ ? address.toLowerCase()
17
+ : `0x${address.toLowerCase()}`;
18
+ const code = await provider.getCode(normalizedAddress);
15
19
  if (code === '0x' || code.length <= 2) {
16
20
  throw new Error(`❌ ${label} 地址无效或未部署合约: ${address}`);
17
21
  }
@@ -20,6 +24,10 @@ async function validateContractAddress(provider, address, label) {
20
24
  if (error.message.includes('无效或未部署')) {
21
25
  throw error;
22
26
  }
27
+ // ✅ 如果是 checksum 错误,提供更友好的提示
28
+ if (error.message.includes('bad address checksum') || error.code === 'INVALID_ARGUMENT') {
29
+ throw new Error(`❌ ${label} 地址格式错误,请使用正确的 checksum 格式: ${address}`);
30
+ }
23
31
  throw new Error(`❌ 无法验证 ${label} 地址 ${address}: ${error.message}`);
24
32
  }
25
33
  }
@@ -205,7 +213,7 @@ export async function ensureFlapSellApproval(chain, rpcUrl, privateKey, token, o
205
213
  * @param privateKeys 拥有者私钥数组(每个地址需自行签名)
206
214
  * @returns 每个地址的授权结果(包含 owner 与交易回执等信息)
207
215
  */
208
- export async function ensureFlapSellApprovalBatch(chain, rpcUrl, privateKeys, token, required = ((1n << 256n) - 1n)) {
216
+ export async function ensureFlapSellApprovalBatch(chain, rpcUrl, privateKeys, token, required = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')) {
209
217
  const results = [];
210
218
  for (const pk of privateKeys || []) {
211
219
  const owner = new Wallet(pk).address;
@@ -217,7 +225,7 @@ export async function ensureFlapSellApprovalBatch(chain, rpcUrl, privateKeys, to
217
225
  /**
218
226
  * 批量检查 Flap Protocol 授权状态(默认按上限 2^256-1 判断)
219
227
  */
220
- export async function checkFlapSellApprovalBatch(chain, rpcUrl, token, owners, required = ((1n << 256n) - 1n)) {
228
+ export async function checkFlapSellApprovalBatch(chain, rpcUrl, token, owners, required = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')) {
221
229
  const proxyAddresses = {
222
230
  BSC: ADDRESSES.BSC.FlapPortal,
223
231
  BASE: ADDRESSES.BASE.FlapPortal,
@@ -280,7 +288,60 @@ export async function batchCheckAllowances(provider, tokenAddress, owners, spend
280
288
  });
281
289
  }
282
290
  /**
283
- * 通用方法:检查 ERC20 代币授权额度(只读,不发送交易)
291
+ * 🔧 内部辅助函数:根据链和平台自动解析 spender 地址
292
+ */
293
+ function resolveSpenderAddress(chain, platform) {
294
+ const spenderMap = {
295
+ flap: {
296
+ BSC: ADDRESSES.BSC.FlapPortal,
297
+ BASE: ADDRESSES.BASE.FlapPortal,
298
+ XLAYER: ADDRESSES.XLAYER.FlapPortal,
299
+ MORPH: ADDRESSES.MORPH.FlapPortal,
300
+ },
301
+ four: {
302
+ // Four.meme 使用 TokenManagerV2Proxy(默认)
303
+ BSC: ADDRESSES.BSC.TokenManagerV2Proxy,
304
+ BASE: ADDRESSES.BASE.TokenManagerHelper3,
305
+ XLAYER: '0x0000000000000000000000000000000000000000', // XLAYER 暂不支持 Four.meme
306
+ MORPH: '0x0000000000000000000000000000000000000000', // MORPH 暂不支持 Four.meme
307
+ },
308
+ 'pancake-v2': {
309
+ // PancakeSwap V2 Router 地址(需要在 constants.ts 中添加)
310
+ BSC: '0x10ED43C718714eb63d5aA57B78B54704E256024E', // BSC PancakeSwap V2 Router
311
+ BASE: '0x8cFe327CEc66d1C090Dd72bd0FF11d690C33a2Eb', // BASE PancakeSwap V2 Router
312
+ XLAYER: '0x0000000000000000000000000000000000000000', // XLAYER 暂不支持
313
+ MORPH: '0x0000000000000000000000000000000000000000', // MORPH 暂不支持
314
+ },
315
+ 'pancake-v3': {
316
+ // PancakeSwap V3 SmartRouter 地址(需要在 constants.ts 中添加)
317
+ BSC: '0x13f4EA83D0bd40E75C8222255bc855a974568Dd4', // BSC PancakeSwap V3 SmartRouter
318
+ BASE: '0x678Aa4bF4E210cf2166753e054d5b7c31cc7fa86', // BASE PancakeSwap V3 SmartRouter
319
+ XLAYER: '0x0000000000000000000000000000000000000000', // XLAYER 暂不支持
320
+ MORPH: '0x0000000000000000000000000000000000000000', // MORPH 暂不支持
321
+ },
322
+ };
323
+ const spender = spenderMap[platform]?.[chain];
324
+ if (!spender || spender === '0x0000000000000000000000000000000000000000') {
325
+ throw new Error(`❌ 不支持的链或平台: ${chain} / ${platform}`);
326
+ }
327
+ return spender;
328
+ }
329
+ /**
330
+ * ✅ 智能路由:检查单个 ERC20 授权额度(自动选择 spender)
331
+ *
332
+ * @param chain - 链名称 ('BSC' | 'BASE' | 'XLAYER' | 'MORPH')
333
+ * @param platform - 平台名称 ('flap' | 'four' | 'pancake-v2' | 'pancake-v3')
334
+ * @param rpcUrl - RPC 节点地址
335
+ * @param tokenAddress - 代币合约地址
336
+ * @param ownerAddress - 代币持有者地址
337
+ * @returns 当前授权额度(bigint)
338
+ */
339
+ export async function checkAllowance(chain, platform, rpcUrl, tokenAddress, ownerAddress) {
340
+ const spenderAddress = resolveSpenderAddress(chain, platform);
341
+ return checkAllowanceRaw(rpcUrl, tokenAddress, ownerAddress, spenderAddress);
342
+ }
343
+ /**
344
+ * ✅ 底层方法:检查 ERC20 代币授权额度(手动指定 spender)
284
345
  * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
285
346
  *
286
347
  * @param rpcUrl - RPC 节点地址
@@ -289,14 +350,18 @@ export async function batchCheckAllowances(provider, tokenAddress, owners, spend
289
350
  * @param spenderAddress - 被授权的合约地址(如 Router、Portal、TokenManager 等)
290
351
  * @returns 当前授权额度(bigint)
291
352
  */
292
- export async function checkAllowance(rpcUrl, tokenAddress, ownerAddress, spenderAddress) {
353
+ export async function checkAllowanceRaw(rpcUrl, tokenAddress, ownerAddress, spenderAddress) {
293
354
  const provider = new JsonRpcProvider(rpcUrl);
355
+ // ✅ 规范化地址(转为小写,避免 checksum 错误)
356
+ const normalizedToken = tokenAddress.toLowerCase();
357
+ const normalizedOwner = ownerAddress.toLowerCase();
358
+ const normalizedSpender = spenderAddress.toLowerCase();
294
359
  // 验证地址
295
- await validateContractAddress(provider, tokenAddress, 'Token');
296
- await validateContractAddress(provider, spenderAddress, 'Spender');
297
- const erc20 = new Contract(tokenAddress, ERC20_ABI, provider);
360
+ await validateContractAddress(provider, normalizedToken, 'Token');
361
+ await validateContractAddress(provider, normalizedSpender, 'Spender');
362
+ const erc20 = new Contract(normalizedToken, ERC20_ABI, provider);
298
363
  try {
299
- const allowance = await erc20.allowance(ownerAddress, spenderAddress);
364
+ const allowance = await erc20.allowance(normalizedOwner, normalizedSpender);
300
365
  return allowance;
301
366
  }
302
367
  catch (error) {
@@ -304,7 +369,22 @@ export async function checkAllowance(rpcUrl, tokenAddress, ownerAddress, spender
304
369
  }
305
370
  }
306
371
  /**
307
- * ✅ 通用方法:授权 ERC20 代币给指定合约(自动检查,只在不足时才发送交易)
372
+ * ✅ 智能路由:授权 ERC20 代币(自动选择 spender,自动检查,只在不足时才发送交易)
373
+ *
374
+ * @param chain - 链名称 ('BSC' | 'BASE' | 'XLAYER' | 'MORPH')
375
+ * @param platform - 平台名称 ('flap' | 'four' | 'pancake-v2' | 'pancake-v3')
376
+ * @param rpcUrl - RPC 节点地址
377
+ * @param privateKey - 私钥
378
+ * @param tokenAddress - 代币合约地址
379
+ * @param amount - 授权数量(bigint),传 'max' 表示最大授权
380
+ * @returns 授权结果
381
+ */
382
+ export async function approveToken(chain, platform, rpcUrl, privateKey, tokenAddress, amount) {
383
+ const spenderAddress = resolveSpenderAddress(chain, platform);
384
+ return approveTokenRaw(rpcUrl, privateKey, tokenAddress, spenderAddress, amount);
385
+ }
386
+ /**
387
+ * ✅ 底层方法:授权 ERC20 代币给指定合约(手动指定 spender)
308
388
  * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
309
389
  *
310
390
  * @param rpcUrl - RPC 节点地址
@@ -314,19 +394,22 @@ export async function checkAllowance(rpcUrl, tokenAddress, ownerAddress, spender
314
394
  * @param amount - 授权数量(bigint),传 'max' 或 ethers.MaxUint256 表示最大授权
315
395
  * @returns 授权结果
316
396
  */
317
- export async function approveToken(rpcUrl, privateKey, tokenAddress, spenderAddress, amount) {
397
+ export async function approveTokenRaw(rpcUrl, privateKey, tokenAddress, spenderAddress, amount) {
318
398
  const provider = new JsonRpcProvider(rpcUrl);
319
399
  const signer = new Wallet(privateKey, provider);
320
400
  const ownerAddress = signer.address;
401
+ // ✅ 规范化地址(转为小写,避免 checksum 错误)
402
+ const normalizedToken = tokenAddress.toLowerCase();
403
+ const normalizedSpender = spenderAddress.toLowerCase();
321
404
  // 验证地址
322
- await validateContractAddress(provider, tokenAddress, 'Token');
323
- await validateContractAddress(provider, spenderAddress, 'Spender');
324
- const erc20 = new Contract(tokenAddress, ERC20_ABI, signer);
405
+ await validateContractAddress(provider, normalizedToken, 'Token');
406
+ await validateContractAddress(provider, normalizedSpender, 'Spender');
407
+ const erc20 = new Contract(normalizedToken, ERC20_ABI, signer);
325
408
  const requiredAmount = amount === 'max' ? BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff') : amount;
326
409
  // 检查当前授权额度
327
410
  let currentAllowance;
328
411
  try {
329
- currentAllowance = await erc20.allowance(ownerAddress, spenderAddress);
412
+ currentAllowance = await erc20.allowance(ownerAddress, normalizedSpender);
330
413
  }
331
414
  catch (error) {
332
415
  throw new Error(`❌ 查询授权额度失败: ${error.message}`);
@@ -341,7 +424,7 @@ export async function approveToken(rpcUrl, privateKey, tokenAddress, spenderAddr
341
424
  }
342
425
  // 发送授权交易
343
426
  try {
344
- const tx = await erc20.approve(spenderAddress, requiredAmount);
427
+ const tx = await erc20.approve(normalizedSpender, requiredAmount);
345
428
  const receipt = await tx.wait();
346
429
  return {
347
430
  alreadyApproved: false,
@@ -355,7 +438,21 @@ export async function approveToken(rpcUrl, privateKey, tokenAddress, spenderAddr
355
438
  }
356
439
  }
357
440
  /**
358
- * ✅ 通用方法:批量检查多个钱包的授权额度(只读,不发送交易)
441
+ * ✅ 智能路由:批量检查多个钱包的授权额度(自动选择 spender)
442
+ *
443
+ * @param chain - 链名称 ('BSC' | 'BASE' | 'XLAYER' | 'MORPH')
444
+ * @param platform - 平台名称 ('flap' | 'four' | 'pancake-v2' | 'pancake-v3')
445
+ * @param rpcUrl - RPC 节点地址
446
+ * @param tokenAddress - 代币合约地址
447
+ * @param ownerAddresses - 代币持有者地址数组
448
+ * @returns 每个地址的授权额度数组
449
+ */
450
+ export async function checkAllowanceBatch(chain, platform, rpcUrl, tokenAddress, ownerAddresses) {
451
+ const spenderAddress = resolveSpenderAddress(chain, platform);
452
+ return checkAllowanceBatchRaw(rpcUrl, tokenAddress, ownerAddresses, spenderAddress);
453
+ }
454
+ /**
455
+ * ✅ 底层方法:批量检查多个钱包的授权额度(手动指定 spender)
359
456
  * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
360
457
  *
361
458
  * @param rpcUrl - RPC 节点地址
@@ -364,29 +461,47 @@ export async function approveToken(rpcUrl, privateKey, tokenAddress, spenderAddr
364
461
  * @param spenderAddress - 被授权的合约地址
365
462
  * @returns 每个地址的授权额度数组
366
463
  */
367
- export async function checkAllowanceBatch(rpcUrl, tokenAddress, ownerAddresses, spenderAddress) {
464
+ export async function checkAllowanceBatchRaw(rpcUrl, tokenAddress, ownerAddresses, spenderAddress) {
368
465
  const provider = new JsonRpcProvider(rpcUrl);
466
+ // ✅ 规范化地址(转为小写,避免 checksum 错误)
467
+ const normalizedToken = tokenAddress.toLowerCase();
468
+ const normalizedOwners = ownerAddresses.map(addr => addr.toLowerCase());
469
+ const normalizedSpender = spenderAddress.toLowerCase();
369
470
  // 验证地址
370
- await validateContractAddress(provider, tokenAddress, 'Token');
371
- await validateContractAddress(provider, spenderAddress, 'Spender');
372
- return batchCheckAllowances(provider, tokenAddress, ownerAddresses, spenderAddress);
471
+ await validateContractAddress(provider, normalizedToken, 'Token');
472
+ await validateContractAddress(provider, normalizedSpender, 'Spender');
473
+ return batchCheckAllowances(provider, normalizedToken, normalizedOwners, normalizedSpender);
373
474
  }
374
475
  /**
375
- * ✅ 通用方法:批量授权 ERC20 代币(自动检查,只在不足时才发送交易)
376
- * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
476
+ * ✅ 智能路由:批量授权 ERC20 代币(自动选择 spender,自动检查,只在不足时才发送交易)
377
477
  *
378
478
  * @param params - 批量授权参数
379
479
  * @returns 批量授权结果
380
480
  */
381
481
  export async function approveTokenBatch(params) {
482
+ const { chain, platform, rpcUrl, privateKeys, tokenAddress, amounts } = params;
483
+ const spenderAddress = resolveSpenderAddress(chain, platform);
484
+ return approveTokenBatchRaw({ rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts });
485
+ }
486
+ /**
487
+ * ✅ 底层方法:批量授权 ERC20 代币(手动指定 spender)
488
+ * 适用于任意 spender 地址(Flap、Four、PancakeSwap V2/V3 等)
489
+ *
490
+ * @param params - 批量授权参数
491
+ * @returns 批量授权结果
492
+ */
493
+ export async function approveTokenBatchRaw(params) {
382
494
  const { rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts } = params;
383
495
  if (privateKeys.length === 0 || amounts.length !== privateKeys.length) {
384
496
  throw new Error('❌ 私钥数量和授权数量必须匹配');
385
497
  }
386
498
  const provider = new JsonRpcProvider(rpcUrl);
499
+ // ✅ 规范化地址(转为小写,避免 checksum 错误)
500
+ const normalizedToken = tokenAddress.toLowerCase();
501
+ const normalizedSpender = spenderAddress.toLowerCase();
387
502
  // 验证地址
388
- await validateContractAddress(provider, tokenAddress, 'Token');
389
- await validateContractAddress(provider, spenderAddress, 'Spender');
503
+ await validateContractAddress(provider, normalizedToken, 'Token');
504
+ await validateContractAddress(provider, normalizedSpender, 'Spender');
390
505
  const results = [];
391
506
  let approvedCount = 0;
392
507
  for (let i = 0; i < privateKeys.length; i++) {
@@ -396,9 +511,9 @@ export async function approveTokenBatch(params) {
396
511
  ? BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
397
512
  : amounts[i];
398
513
  try {
399
- const erc20 = new Contract(tokenAddress, ERC20_ABI, signer);
514
+ const erc20 = new Contract(normalizedToken, ERC20_ABI, signer);
400
515
  // 检查当前授权
401
- const currentAllowance = await erc20.allowance(ownerAddress, spenderAddress);
516
+ const currentAllowance = await erc20.allowance(ownerAddress, normalizedSpender);
402
517
  if (currentAllowance >= requiredAmount) {
403
518
  results.push({
404
519
  owner: ownerAddress,
@@ -409,7 +524,7 @@ export async function approveTokenBatch(params) {
409
524
  continue;
410
525
  }
411
526
  // 发送授权交易
412
- const tx = await erc20.approve(spenderAddress, requiredAmount);
527
+ const tx = await erc20.approve(normalizedSpender, requiredAmount);
413
528
  const receipt = await tx.wait();
414
529
  results.push({
415
530
  owner: ownerAddress,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.2.53",
3
+ "version": "1.2.55",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",