four-flap-meme-sdk 1.7.26 → 1.7.28

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.
@@ -10,8 +10,8 @@ import { getErc20DecimalsMerkle as _getErc20DecimalsMerkle, generateHopWallets a
10
10
  */
11
11
  function getProfitRateBps(userType) {
12
12
  if (userType === 'v1')
13
- return PROFIT_CONFIG.RATE_BPS_V1; // v1 用户:万分之5
14
- return PROFIT_CONFIG.RATE_BPS_V0; // v0 用户(默认):万分之6
13
+ return PROFIT_CONFIG.RATE_BPS_V1_DOUBLE; // v1 用户:万分之5
14
+ return PROFIT_CONFIG.RATE_BPS_V0_DOUBLE; // v0 用户(默认):万分之6
15
15
  }
16
16
  /**
17
17
  * 计算利润金额
@@ -52,18 +52,35 @@ function encodeCreateCallV4(params) {
52
52
  return portalIface.encodeFunctionData('newTokenV4', [params]);
53
53
  }
54
54
  /**
55
- * 编码内盘买入调用 (swapExactInputV3)
55
+ * 编码内盘买入调用
56
+ *
57
+ * 根据是否需要 extensionData 选择使用 swapExactInput 或 swapExactInputV3
58
+ * - V2 代币:使用 swapExactInput(无 extensionData)
59
+ * - V3/V4 代币:使用 swapExactInputV3(支持 extensionData)
56
60
  */
57
- function encodeFlapBuyCall(tokenAddress, inputAmount, extensionData = '0x') {
61
+ function encodeFlapBuyCall(tokenAddress, inputAmount, useV3OrV4 = false, extensionData = '0x') {
58
62
  const portalIface = new Interface(FLAP_PORTAL_ABI);
59
- return portalIface.encodeFunctionData('swapExactInputV3', [{
60
- inputToken: ZERO_ADDRESS,
61
- outputToken: tokenAddress,
62
- inputAmount,
63
- minOutputAmount: 0n,
64
- permitData: '0x',
65
- extensionData,
66
- }]);
63
+ if (useV3OrV4) {
64
+ // V3/V4 代币使用 swapExactInputV3(支持 extensionData)
65
+ return portalIface.encodeFunctionData('swapExactInputV3', [{
66
+ inputToken: ZERO_ADDRESS,
67
+ outputToken: tokenAddress,
68
+ inputAmount,
69
+ minOutputAmount: 0n,
70
+ permitData: '0x',
71
+ extensionData,
72
+ }]);
73
+ }
74
+ else {
75
+ // V2 代币使用 swapExactInput
76
+ return portalIface.encodeFunctionData('swapExactInput', [{
77
+ inputToken: ZERO_ADDRESS,
78
+ outputToken: tokenAddress,
79
+ inputAmount,
80
+ minOutputAmount: 0n,
81
+ permitData: '0x',
82
+ }]);
83
+ }
67
84
  }
68
85
  /**
69
86
  * 编码外盘 V3 买入调用
@@ -226,11 +243,12 @@ export async function bundleCreateBuy(params) {
226
243
  });
227
244
  // 3. 买家买入
228
245
  const extensionData = params.extensionData ?? '0x';
246
+ const useV3OrV4 = useV4 || useV3; // 根据代币版本选择买入函数
229
247
  for (let i = 0; i < buyerWallets.length; i++) {
230
248
  const buyerWallet = buyerWallets[i];
231
249
  const buyAmount = buyAmountsWei[i];
232
- // 使用 executeBatch 从 buyerWallet 调用 Portal.swapExactInputV3
233
- const buyData = encodeFlapBuyCall(tokenAddress, buyAmount, extensionData);
250
+ // 使用 executeBatch 从 buyerWallet 调用 Portal
251
+ const buyData = encodeFlapBuyCall(tokenAddress, buyAmount, useV3OrV4, extensionData);
234
252
  const buyBatchCall = delegateInterface.encodeFunctionData('executeBatch', [[{
235
253
  target: FLAP_PORTAL_ADDRESS,
236
254
  value: buyAmount,
@@ -347,12 +365,12 @@ export async function bundleCreateToDex(params) {
347
365
  value: params.quoteAmt ?? 0n,
348
366
  callData: createBatchCall,
349
367
  });
350
- // 3. 内盘买入
368
+ // 3. 内盘买入(一键发射始终使用 V4,所以 useV3OrV4 = true)
351
369
  const extensionData = params.extensionData ?? '0x';
352
370
  for (let i = 0; i < curveBuyerWallets.length; i++) {
353
371
  const buyerWallet = curveBuyerWallets[i];
354
372
  const buyAmount = curveBuyAmountsWei[i];
355
- const buyData = encodeFlapBuyCall(tokenAddress, buyAmount, extensionData);
373
+ const buyData = encodeFlapBuyCall(tokenAddress, buyAmount, true, extensionData);
356
374
  const buyBatchCall = delegateInterface.encodeFunctionData('executeBatch', [[{
357
375
  target: FLAP_PORTAL_ADDRESS,
358
376
  value: buyAmount,
@@ -547,9 +565,11 @@ export async function bundleGraduateBuy(params) {
547
565
  calls.push(buildProfitCall(payerWallet.address, profitAmount, profitRecipient, delegateInterface));
548
566
  }
549
567
  // 2. 内盘买入
568
+ // lpFeeProfile >= 0 表示 V3 池子,需要使用 swapExactInputV3
569
+ const useV3OrV4 = lpFeeProfile !== undefined && lpFeeProfile >= 0;
550
570
  for (let i = 0; i < curveBuyers.length; i++) {
551
571
  const { wallet, amount } = curveBuyers[i];
552
- const buyData = encodeFlapBuyCall(tokenAddress, amount, extensionData);
572
+ const buyData = encodeFlapBuyCall(tokenAddress, amount, useV3OrV4, extensionData);
553
573
  const buyBatchCall = delegateInterface.encodeFunctionData('executeBatch', [[{
554
574
  target: FLAP_PORTAL_ADDRESS,
555
575
  value: amount,
@@ -31,11 +31,11 @@ export declare const PROFIT_CONFIG: {
31
31
  /** 利润比例(换手模式):6 bps = 0.06% */
32
32
  readonly RATE_BPS_SWAP: 6;
33
33
  /** 利润比例(单边基点):8 bps = 0.08%(用户类型 v0) */
34
- readonly RATE_BPS_V0: 8;
34
+ readonly RATE_BPS_V0: 4;
35
35
  /** 利润比例(双边基点):4 bps = 0.04%(用户类型 v0) */
36
36
  readonly RATE_BPS_V0_DOUBLE: 4;
37
37
  /** 利润比例(单边基点):10 bps = 0.10%(用户类型 v1) */
38
- readonly RATE_BPS_V1: 10;
38
+ readonly RATE_BPS_V1: 5;
39
39
  /** 利润比例(双边基点):5 bps = 0.05%(用户类型 v1) */
40
40
  readonly RATE_BPS_V1_DOUBLE: 5;
41
41
  };
@@ -43,11 +43,11 @@ export const PROFIT_CONFIG = {
43
43
  /** 利润比例(换手模式):6 bps = 0.06% */
44
44
  RATE_BPS_SWAP: 6,
45
45
  /** 利润比例(单边基点):8 bps = 0.08%(用户类型 v0) */
46
- RATE_BPS_V0: 8,
46
+ RATE_BPS_V0: 4,
47
47
  /** 利润比例(双边基点):4 bps = 0.04%(用户类型 v0) */
48
48
  RATE_BPS_V0_DOUBLE: 4,
49
49
  /** 利润比例(单边基点):10 bps = 0.10%(用户类型 v1) */
50
- RATE_BPS_V1: 10,
50
+ RATE_BPS_V1: 5,
51
51
  /** 利润比例(双边基点):5 bps = 0.05%(用户类型 v1) */
52
52
  RATE_BPS_V1_DOUBLE: 5,
53
53
  };
@@ -176,6 +176,8 @@ export type ApproveTokenBatchParams = {
176
176
  gasLimit?: number;
177
177
  /** 链ID(可选,默认56=BSC,signOnly=true 时生效) */
178
178
  chainId?: number;
179
+ /** 跳过合约地址验证(可选,用于某些特殊场景) */
180
+ skipValidation?: boolean;
179
181
  };
180
182
  export type ApproveTokenBatchRawParams = {
181
183
  rpcUrl: string;
@@ -193,6 +195,8 @@ export type ApproveTokenBatchRawParams = {
193
195
  chainId?: number;
194
196
  /** 外部 NonceManager(可选,用于同一钱包签多笔交易时共享 nonce 状态) */
195
197
  nonceManager?: NonceManager;
198
+ /** 跳过合约地址验证(可选,用于某些特殊场景,如 RPC 返回异常时) */
199
+ skipValidation?: boolean;
196
200
  };
197
201
  /** signOnly=false 时的返回结果(直接发送交易) */
198
202
  export type ApproveTokenBatchResult = {
@@ -483,12 +483,12 @@ export async function checkAllowanceBatchRaw(rpcUrl, tokenAddress, ownerAddresse
483
483
  return batchCheckAllowances(provider, normalizedToken, normalizedOwners, normalizedSpender);
484
484
  }
485
485
  export async function approveTokenBatch(params) {
486
- const { chain, platform, rpcUrl, privateKeys, tokenAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId } = params;
486
+ const { chain, platform, rpcUrl, privateKeys, tokenAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId, skipValidation } = params;
487
487
  const spenderAddress = resolveSpenderAddress(chain, platform);
488
- return approveTokenBatchRaw({ rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId });
488
+ return approveTokenBatchRaw({ rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId, skipValidation });
489
489
  }
490
490
  export async function approveTokenBatchRaw(params) {
491
- const { rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId = 56, nonceManager: externalNonceManager } = params;
491
+ const { rpcUrl, privateKeys, tokenAddress, spenderAddress, amounts, signOnly, gasPriceGwei, gasLimit, chainId = 56, nonceManager: externalNonceManager, skipValidation } = params;
492
492
  if (privateKeys.length === 0 || amounts.length !== privateKeys.length) {
493
493
  throw new Error('❌ 私钥数量和授权数量必须匹配');
494
494
  }
@@ -496,9 +496,11 @@ export async function approveTokenBatchRaw(params) {
496
496
  // ✅ 规范化地址(转为小写,避免 checksum 错误)
497
497
  const normalizedToken = tokenAddress.toLowerCase();
498
498
  const normalizedSpender = spenderAddress.toLowerCase();
499
- // 验证地址
500
- await validateContractAddress(provider, normalizedToken, 'Token');
501
- await validateContractAddress(provider, normalizedSpender, 'Spender');
499
+ // 验证地址(如果 skipValidation=true 则跳过)
500
+ if (!skipValidation) {
501
+ await validateContractAddress(provider, normalizedToken, 'Token');
502
+ await validateContractAddress(provider, normalizedSpender, 'Spender');
503
+ }
502
504
  // ✅ 优化:批量创建钱包和合约实例
503
505
  const wallets = privateKeys.map(key => new Wallet(key, provider));
504
506
  const ownerAddresses = wallets.map(w => w.address);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.7.26",
3
+ "version": "1.7.28",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -38,4 +38,4 @@
38
38
  "solc": "^0.8.33",
39
39
  "typescript": "^5.6.3"
40
40
  }
41
- }
41
+ }