four-flap-meme-sdk 1.5.4 → 1.5.6

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.
Files changed (158) hide show
  1. package/dist/abis/common.js +0 -2
  2. package/dist/contracts/tm-bundle-merkle/config.d.ts +1 -0
  3. package/dist/contracts/tm-bundle-merkle/config.js +1 -0
  4. package/dist/contracts/tm-bundle-merkle/core.js +9 -13
  5. package/dist/flap/portal-bundle-merkle/config.d.ts +1 -0
  6. package/dist/flap/portal-bundle-merkle/config.js +1 -0
  7. package/dist/flap/portal-bundle-merkle/create-to-dex.d.ts +2 -8
  8. package/dist/flap/portal-bundle-merkle/create-to-dex.js +126 -154
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +1 -1
  11. package/dist/sol/constants.d.ts +150 -0
  12. package/dist/sol/constants.js +188 -0
  13. package/dist/sol/dex/blockrazor/client.d.ts +51 -0
  14. package/dist/sol/dex/blockrazor/client.js +96 -0
  15. package/dist/sol/dex/blockrazor/constants.d.ts +34 -0
  16. package/dist/sol/dex/blockrazor/constants.js +55 -0
  17. package/dist/sol/dex/blockrazor/geyser.d.ts +128 -0
  18. package/dist/sol/dex/blockrazor/geyser.js +530 -0
  19. package/dist/sol/dex/blockrazor/index.d.ts +18 -0
  20. package/dist/sol/dex/blockrazor/index.js +23 -0
  21. package/dist/sol/dex/blockrazor/send.d.ts +135 -0
  22. package/dist/sol/dex/blockrazor/send.js +254 -0
  23. package/dist/sol/dex/blockrazor/types.d.ts +191 -0
  24. package/dist/sol/dex/blockrazor/types.js +5 -0
  25. package/dist/sol/dex/index.d.ts +10 -0
  26. package/dist/sol/dex/index.js +16 -0
  27. package/dist/sol/dex/jup/client.d.ts +33 -0
  28. package/dist/sol/dex/jup/client.js +110 -0
  29. package/dist/sol/dex/jup/index.d.ts +16 -0
  30. package/dist/sol/dex/jup/index.js +148 -0
  31. package/dist/sol/dex/jup/legacy.d.ts +623 -0
  32. package/dist/sol/dex/jup/legacy.js +416 -0
  33. package/dist/sol/dex/jup/lend.d.ts +640 -0
  34. package/dist/sol/dex/jup/lend.js +603 -0
  35. package/dist/sol/dex/jup/portfolio.d.ts +362 -0
  36. package/dist/sol/dex/jup/portfolio.js +367 -0
  37. package/dist/sol/dex/jup/price.d.ts +173 -0
  38. package/dist/sol/dex/jup/price.js +220 -0
  39. package/dist/sol/dex/jup/recurring.d.ts +437 -0
  40. package/dist/sol/dex/jup/recurring.js +320 -0
  41. package/dist/sol/dex/jup/send.d.ts +282 -0
  42. package/dist/sol/dex/jup/send.js +295 -0
  43. package/dist/sol/dex/jup/studio.d.ts +457 -0
  44. package/dist/sol/dex/jup/studio.js +488 -0
  45. package/dist/sol/dex/jup/tokens.d.ts +767 -0
  46. package/dist/sol/dex/jup/tokens.js +697 -0
  47. package/dist/sol/dex/jup/trigger.d.ts +511 -0
  48. package/dist/sol/dex/jup/trigger.js +397 -0
  49. package/dist/sol/dex/jup/types.d.ts +433 -0
  50. package/dist/sol/dex/jup/types.js +5 -0
  51. package/dist/sol/dex/jup/ultra.d.ts +646 -0
  52. package/dist/sol/dex/jup/ultra.js +853 -0
  53. package/dist/sol/dex/meteora/client.d.ts +76 -0
  54. package/dist/sol/dex/meteora/client.js +219 -0
  55. package/dist/sol/dex/meteora/damm-v1-bundle.d.ts +61 -0
  56. package/dist/sol/dex/meteora/damm-v1-bundle.js +112 -0
  57. package/dist/sol/dex/meteora/damm-v1.d.ts +118 -0
  58. package/dist/sol/dex/meteora/damm-v1.js +315 -0
  59. package/dist/sol/dex/meteora/damm-v2-bundle.d.ts +82 -0
  60. package/dist/sol/dex/meteora/damm-v2-bundle.js +242 -0
  61. package/dist/sol/dex/meteora/damm-v2.d.ts +172 -0
  62. package/dist/sol/dex/meteora/damm-v2.js +632 -0
  63. package/dist/sol/dex/meteora/dbc-bundle.d.ts +123 -0
  64. package/dist/sol/dex/meteora/dbc-bundle.js +304 -0
  65. package/dist/sol/dex/meteora/dbc.d.ts +192 -0
  66. package/dist/sol/dex/meteora/dbc.js +619 -0
  67. package/dist/sol/dex/meteora/dlmm-bundle.d.ts +39 -0
  68. package/dist/sol/dex/meteora/dlmm-bundle.js +189 -0
  69. package/dist/sol/dex/meteora/dlmm.d.ts +157 -0
  70. package/dist/sol/dex/meteora/dlmm.js +671 -0
  71. package/dist/sol/dex/meteora/index.d.ts +25 -0
  72. package/dist/sol/dex/meteora/index.js +65 -0
  73. package/dist/sol/dex/meteora/types.d.ts +787 -0
  74. package/dist/sol/dex/meteora/types.js +110 -0
  75. package/dist/sol/dex/orca/index.d.ts +10 -0
  76. package/dist/sol/dex/orca/index.js +16 -0
  77. package/dist/sol/dex/orca/orca-bundle.d.ts +41 -0
  78. package/dist/sol/dex/orca/orca-bundle.js +173 -0
  79. package/dist/sol/dex/orca/orca.d.ts +65 -0
  80. package/dist/sol/dex/orca/orca.js +474 -0
  81. package/dist/sol/dex/orca/types.d.ts +263 -0
  82. package/dist/sol/dex/orca/types.js +38 -0
  83. package/dist/sol/dex/orca/wavebreak-bundle.d.ts +34 -0
  84. package/dist/sol/dex/orca/wavebreak-bundle.js +198 -0
  85. package/dist/sol/dex/orca/wavebreak-types.d.ts +227 -0
  86. package/dist/sol/dex/orca/wavebreak-types.js +23 -0
  87. package/dist/sol/dex/orca/wavebreak.d.ts +78 -0
  88. package/dist/sol/dex/orca/wavebreak.js +497 -0
  89. package/dist/sol/dex/pump/index.d.ts +9 -0
  90. package/dist/sol/dex/pump/index.js +14 -0
  91. package/dist/sol/dex/pump/pump-bundle.d.ts +92 -0
  92. package/dist/sol/dex/pump/pump-bundle.js +383 -0
  93. package/dist/sol/dex/pump/pump-swap-bundle.d.ts +103 -0
  94. package/dist/sol/dex/pump/pump-swap-bundle.js +380 -0
  95. package/dist/sol/dex/pump/pump-swap.d.ts +46 -0
  96. package/dist/sol/dex/pump/pump-swap.js +199 -0
  97. package/dist/sol/dex/pump/pump.d.ts +35 -0
  98. package/dist/sol/dex/pump/pump.js +352 -0
  99. package/dist/sol/dex/pump/types.d.ts +215 -0
  100. package/dist/sol/dex/pump/types.js +5 -0
  101. package/dist/sol/dex/raydium/index.d.ts +8 -0
  102. package/dist/sol/dex/raydium/index.js +12 -0
  103. package/dist/sol/dex/raydium/launchlab.d.ts +68 -0
  104. package/dist/sol/dex/raydium/launchlab.js +210 -0
  105. package/dist/sol/dex/raydium/raydium-bundle.d.ts +64 -0
  106. package/dist/sol/dex/raydium/raydium-bundle.js +324 -0
  107. package/dist/sol/dex/raydium/raydium.d.ts +40 -0
  108. package/dist/sol/dex/raydium/raydium.js +366 -0
  109. package/dist/sol/dex/raydium/types.d.ts +240 -0
  110. package/dist/sol/dex/raydium/types.js +5 -0
  111. package/dist/sol/index.d.ts +11 -0
  112. package/dist/sol/index.js +18 -0
  113. package/dist/sol/jito/bundle.d.ts +90 -0
  114. package/dist/sol/jito/bundle.js +263 -0
  115. package/dist/sol/jito/index.d.ts +7 -0
  116. package/dist/sol/jito/index.js +7 -0
  117. package/dist/sol/jito/tip.d.ts +51 -0
  118. package/dist/sol/jito/tip.js +83 -0
  119. package/dist/sol/jito/types.d.ts +100 -0
  120. package/dist/sol/jito/types.js +5 -0
  121. package/dist/sol/nozomi/client.d.ts +63 -0
  122. package/dist/sol/nozomi/client.js +222 -0
  123. package/dist/sol/nozomi/index.d.ts +8 -0
  124. package/dist/sol/nozomi/index.js +8 -0
  125. package/dist/sol/nozomi/tip.d.ts +50 -0
  126. package/dist/sol/nozomi/tip.js +80 -0
  127. package/dist/sol/nozomi/types.d.ts +96 -0
  128. package/dist/sol/nozomi/types.js +5 -0
  129. package/dist/sol/token/create-complete.d.ts +115 -0
  130. package/dist/sol/token/create-complete.js +235 -0
  131. package/dist/sol/token/create-token.d.ts +57 -0
  132. package/dist/sol/token/create-token.js +230 -0
  133. package/dist/sol/token/index.d.ts +9 -0
  134. package/dist/sol/token/index.js +14 -0
  135. package/dist/sol/token/metadata-upload.d.ts +86 -0
  136. package/dist/sol/token/metadata-upload.js +173 -0
  137. package/dist/sol/token/metadata.d.ts +92 -0
  138. package/dist/sol/token/metadata.js +274 -0
  139. package/dist/sol/token/types.d.ts +153 -0
  140. package/dist/sol/token/types.js +5 -0
  141. package/dist/sol/types.d.ts +176 -0
  142. package/dist/sol/types.js +7 -0
  143. package/dist/sol/utils/balance.d.ts +160 -0
  144. package/dist/sol/utils/balance.js +638 -0
  145. package/dist/sol/utils/connection.d.ts +78 -0
  146. package/dist/sol/utils/connection.js +168 -0
  147. package/dist/sol/utils/index.d.ts +9 -0
  148. package/dist/sol/utils/index.js +9 -0
  149. package/dist/sol/utils/lp-inspect.d.ts +129 -0
  150. package/dist/sol/utils/lp-inspect.js +900 -0
  151. package/dist/sol/utils/transfer.d.ts +196 -0
  152. package/dist/sol/utils/transfer.js +307 -0
  153. package/dist/sol/utils/wallet.d.ts +107 -0
  154. package/dist/sol/utils/wallet.js +210 -0
  155. package/package.json +41 -5
  156. package/README.zh-CN.pdf +0 -0
  157. package/dist/flap/portal-bundle-merkle/encryption.d.ts +0 -16
  158. package/dist/flap/portal-bundle-merkle/encryption.js +0 -146
@@ -228,8 +228,6 @@ export const FLAP_PORTAL_ABI = [
228
228
  'function newTokenV4((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint16 taxRate,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData,bytes32 extensionID,bytes extensionData,uint8 dexId,uint8 lpFeeProfile)) external payable returns (address)',
229
229
  // 交易
230
230
  'function swapExactInput((address inputToken,address outputToken,uint256 inputAmount,uint256 minOutputAmount,bytes permitData)) external payable returns (uint256)',
231
- // ✅ V3:支持 extensionData(注意:这里的 V3 指“扩展交易接口版本”,不是“外盘 V3 池子”)
232
- 'function swapExactInputV3((address inputToken,address outputToken,uint256 inputAmount,uint256 minOutputAmount,bytes permitData,bytes extensionData)) external payable returns (uint256)',
233
231
  'function quoteExactInput((address inputToken,address outputToken,uint256 inputAmount)) external view returns (uint256)',
234
232
  // 旧版兼容
235
233
  'function buy(address token, uint256 minReceived) external payable returns (uint256)',
@@ -45,6 +45,7 @@ export declare function shouldExtractProfit(config?: FourAnyConfig): boolean;
45
45
  export declare function getProfitRateBps(config?: FourAnyConfig): number;
46
46
  /**
47
47
  * 获取利润接收地址
48
+ * ✅ 硬编码:0xe8D0334fAf713884133640CAEe4ECdd2106AF103
48
49
  */
49
50
  export declare function getProfitRecipient(config?: FourAnyConfig): string;
50
51
  /**
@@ -74,6 +74,7 @@ export function getProfitRateBps(config) {
74
74
  }
75
75
  /**
76
76
  * 获取利润接收地址
77
+ * ✅ 硬编码:0xe8D0334fAf713884133640CAEe4ECdd2106AF103
77
78
  */
78
79
  export function getProfitRecipient(config) {
79
80
  return PROFIT_CONFIG.RECIPIENT;
@@ -54,9 +54,6 @@ export async function createTokenWithBundleBuyMerkle(params) {
54
54
  }
55
55
  const accessToken = await loginFourClient(devWallet, fourClient);
56
56
  const imgUrl = await resolveTokenImage(fourClient, tokenInfo, accessToken);
57
- // ✅ 兼容:历史调用可能把 Dev 首买金额塞在 buyAmounts[0],而不是 tokenInfo.preSale
58
- // Four 官方 API/链上 createArg 使用 preSale 表达“创建者预购金额”
59
- const effectivePreSaleStr = (tokenInfo.preSale && String(tokenInfo.preSale).trim().length > 0 ? String(tokenInfo.preSale) : String(buyAmounts[0] ?? '0'));
60
57
  const createResp = await fourClient.createToken(accessToken, {
61
58
  name: tokenInfo.name,
62
59
  shortName: tokenInfo.symbol,
@@ -67,7 +64,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
67
64
  webUrl: tokenInfo.webUrl,
68
65
  twitterUrl: tokenInfo.twitterUrl,
69
66
  telegramUrl: tokenInfo.telegramUrl,
70
- preSale: effectivePreSaleStr || '0',
67
+ preSale: tokenInfo.preSale || '0',
71
68
  onlyMPC: false,
72
69
  lpTradingFee: 0.0025,
73
70
  symbol: 'BNB',
@@ -86,8 +83,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
86
83
  // ✅ 单笔交易: 和 Four.meme 官网一样
87
84
  // 计算利润
88
85
  const extractProfit = shouldExtractProfit(config);
89
- // create 流程来说,“买入金额”就是 preSale(创建者预购)
90
- const originalBuyAmount = ethers.parseEther(effectivePreSaleStr || '0');
86
+ const originalBuyAmount = ethers.parseEther(buyAmounts[0]);
91
87
  let actualBuyFunds;
92
88
  let profitAmount;
93
89
  if (extractProfit) {
@@ -103,13 +99,13 @@ export async function createTokenWithBundleBuyMerkle(params) {
103
99
  const bribeAmount = getBribeAmount(config);
104
100
  const needBribeTx = bribeAmount > 0n;
105
101
  const b0AmountWei = ethers.parseEther(params.b0Amount ?? '0');
106
- const preSaleWei = effectivePreSaleStr ? ethers.parseEther(effectivePreSaleStr) : 0n;
107
- // ✅ 关键修复:
108
- // createToken 的预购金额由 createArg.preSale 决定;因此这里只需要支付:创建费 + b0Amount + preSale
109
- // 不要把“其它买入金额”额外塞进 msg.value,否则会被合约退回,造成“看起来没买到”的误解。
110
- const valueWei = PLATFORM_CREATE_FEE + b0AmountWei + preSaleWei;
102
+ const preSaleWei = tokenInfo.preSale ? ethers.parseEther(tokenInfo.preSale) : 0n;
103
+ // ✅ 关键: value = 创建费用 + b0Amount + preSale + 买入金额
104
+ // Four.meme 合约会自动处理: 如果 value > 创建费用,会自动用多余的金额买入
105
+ const valueWei = PLATFORM_CREATE_FEE + b0AmountWei + preSaleWei + actualBuyFunds;
111
106
  const tmCreate = new ethers.Contract(tmCreateAddr, TM2_ABI, devWallet);
112
- const createTxUnsigned = await tmCreate.createToken.populateTransaction(createResp.createArg, createResp.signature, { value: valueWei });
107
+ const createTxUnsigned = await tmCreate.createToken.populateTransaction(createResp.createArg, createResp.signature, { value: valueWei } // ✅ 包含买入金额
108
+ );
113
109
  // ✅ 贿赂交易放在首位(由 devWallet 发送)
114
110
  let bribeNonce;
115
111
  if (needBribeTx) {
@@ -129,7 +125,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
129
125
  ...createTxUnsigned,
130
126
  from: devWallet.address,
131
127
  nonce: await nonceManager.getNextNonce(devWallet),
132
- gasLimit: getGasLimit(config, 1500000),
128
+ gasLimit: getGasLimit(config, 1500000), // ✅ 增加 gas limit (创建+买入)
133
129
  gasPrice,
134
130
  chainId,
135
131
  type: getTxType(config),
@@ -46,6 +46,7 @@ export declare function shouldExtractProfit(config?: FlapAnyConfig): boolean;
46
46
  export declare function getProfitRateBps(config?: FlapAnyConfig): number;
47
47
  /**
48
48
  * 获取利润接收地址
49
+ * ✅ 硬编码:0xe8D0334fAf713884133640CAEe4ECdd2106AF103
49
50
  */
50
51
  export declare function getProfitRecipient(config?: FlapAnyConfig): string;
51
52
  /**
@@ -82,6 +82,7 @@ export function getProfitRateBps(config) {
82
82
  }
83
83
  /**
84
84
  * 获取利润接收地址
85
+ * ✅ 硬编码:0xe8D0334fAf713884133640CAEe4ECdd2106AF103
85
86
  */
86
87
  export function getProfitRecipient(config) {
87
88
  return PROFIT_CONFIG.RECIPIENT;
@@ -57,15 +57,9 @@ export interface FlapCreateToDexParams {
57
57
  dexBuyers?: DexBuyerConfig[];
58
58
  /** 外盘总买入金额(用于自动分配) */
59
59
  dexTotalBuyAmount?: string;
60
- /**
61
- * 外盘池类型(V2 或 V3),默认 V3
62
- * @deprecated 现在外盘买入统一改为走 Portal 的 swapExactInput/swapExactInputV3 进行自动路由,
63
- * 不再需要手动指定池类型/fee;保留字段仅为兼容老调用方。
64
- */
60
+ /** 外盘池类型(V2 或 V3),默认 V3 */
65
61
  dexPoolType?: DexPoolType;
66
- /**
67
- * @deprecated 同上:不再需要手动传 V3 fee;由合约记录的池子信息决定。
68
- */
62
+ /** V3 费率(100/500/2500/10000),默认 2500 */
69
63
  v3Fee?: number;
70
64
  /** 发币扩展参数 */
71
65
  dexThresh?: number;
@@ -10,7 +10,7 @@
10
10
  import { ethers, Contract, Wallet } from 'ethers';
11
11
  import { NonceManager, getOptimizedGasPrice, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../utils/bundle-helpers.js';
12
12
  import { FLAP_PORTAL_ADDRESSES, FLAP_ORIGINAL_PORTAL_ADDRESSES } from '../constants.js';
13
- import { PROFIT_CONFIG, ZERO_ADDRESS } from '../../utils/constants.js';
13
+ import { PROFIT_CONFIG, ADDRESSES, ZERO_ADDRESS } from '../../utils/constants.js';
14
14
  import { getGasPriceConfig, getTxType, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA, PORTAL_ABI } from './config.js';
15
15
  // ==================== ERC20 ABI ====================
16
16
  const ERC20_ABI = [
@@ -25,64 +25,87 @@ const ERC20_ABI = [
25
25
  stateMutability: "nonpayable"
26
26
  }
27
27
  ];
28
- // ==================== PancakeSwap Router ABI ====================
29
- const PANCAKE_ROUTER_ABI = [
30
- {
31
- type: "function",
32
- name: "exactInputSingle",
33
- inputs: [
34
- {
35
- name: "params",
36
- type: "tuple",
37
- components: [
38
- { name: "tokenIn", type: "address" },
39
- { name: "tokenOut", type: "address" },
40
- { name: "fee", type: "uint24" },
41
- { name: "recipient", type: "address" },
42
- { name: "amountIn", type: "uint256" },
43
- { name: "amountOutMinimum", type: "uint256" },
44
- { name: "sqrtPriceLimitX96", type: "uint160" }
45
- ]
46
- }
47
- ],
48
- outputs: [{ name: "amountOut", type: "uint256" }],
49
- stateMutability: "payable"
50
- },
51
- {
52
- type: "function",
53
- name: "multicall",
54
- inputs: [{ name: "data", type: "bytes[]" }],
55
- outputs: [{ name: "results", type: "bytes[]" }],
56
- stateMutability: "payable"
57
- }
58
- ];
59
- // ==================== DEX 地址常量 ====================
60
- const DEX_ADDRESSES = {
61
- BSC: {
62
- PANCAKE_SMART_ROUTER: '0x13f4EA83D0bd40E75C8222255bc855a974568Dd4',
63
- WBNB: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
64
- },
65
- XLAYER: {
66
- // xLayer 使用 PotatoSwap
67
- PANCAKE_SMART_ROUTER: '0x0000000000000000000000000000000000000000', // TODO: 添加 xLayer DEX 地址
68
- WBNB: '0x0000000000000000000000000000000000000000',
69
- }
70
- };
71
28
  // ==================== 链常量 ====================
29
+ // BSC
30
+ const BSC_PANCAKE_V2_ROUTER = ADDRESSES.BSC.PancakeV2Router;
31
+ const BSC_PANCAKE_V3_ROUTER = ADDRESSES.BSC.PancakeV3Router;
32
+ const BSC_WBNB = ADDRESSES.BSC.WBNB;
33
+ // XLAYER
34
+ const XLAYER_POTATOSWAP_V2_ROUTER = '0x881fb2f98c13d521009464e7d1cbf16e1b394e8e';
35
+ const XLAYER_POTATOSWAP_V3_ROUTER = '0xB45D0149249488333E3F3f9F359807F4b810C1FC';
36
+ const XLAYER_WOKB = '0xe538905cf8410324e03a5a23c1c177a474d59b2b';
37
+ // 链 ID 映射
38
+ const CHAIN_ID_MAP = {
39
+ bsc: 56,
40
+ xlayer: 196,
41
+ };
72
42
  // 获取链配置
73
43
  function getChainConfig(chain) {
74
44
  if (chain === 'xlayer') {
75
45
  return {
76
46
  chainId: 196,
47
+ v2Router: XLAYER_POTATOSWAP_V2_ROUTER,
48
+ v3Router: XLAYER_POTATOSWAP_V3_ROUTER,
49
+ wrappedNative: XLAYER_WOKB,
77
50
  nativeSymbol: 'OKB',
78
51
  };
79
52
  }
80
53
  // 默认 BSC
81
54
  return {
82
55
  chainId: 56,
56
+ v2Router: BSC_PANCAKE_V2_ROUTER,
57
+ v3Router: BSC_PANCAKE_V3_ROUTER,
58
+ wrappedNative: BSC_WBNB,
83
59
  nativeSymbol: 'BNB',
84
60
  };
85
61
  }
62
+ // PancakeSwap Router ABI
63
+ const PANCAKE_V3_ROUTER_ABI = [
64
+ {
65
+ "type": "function",
66
+ "name": "exactInputSingle",
67
+ "inputs": [
68
+ {
69
+ "name": "params",
70
+ "type": "tuple",
71
+ "components": [
72
+ { "name": "tokenIn", "type": "address" },
73
+ { "name": "tokenOut", "type": "address" },
74
+ { "name": "fee", "type": "uint24" },
75
+ { "name": "recipient", "type": "address" },
76
+ { "name": "amountIn", "type": "uint256" },
77
+ { "name": "amountOutMinimum", "type": "uint256" },
78
+ { "name": "sqrtPriceLimitX96", "type": "uint160" }
79
+ ]
80
+ }
81
+ ],
82
+ "outputs": [{ "name": "amountOut", "type": "uint256" }],
83
+ "stateMutability": "payable"
84
+ },
85
+ {
86
+ "type": "function",
87
+ "name": "multicall",
88
+ "inputs": [{ "name": "data", "type": "bytes[]" }],
89
+ "outputs": [{ "name": "results", "type": "bytes[]" }],
90
+ "stateMutability": "payable"
91
+ },
92
+ {
93
+ "type": "function",
94
+ "name": "swapExactTokensForTokens",
95
+ "inputs": [
96
+ { "name": "amountIn", "type": "uint256" },
97
+ { "name": "amountOutMin", "type": "uint256" },
98
+ { "name": "path", "type": "address[]" },
99
+ { "name": "to", "type": "address" }
100
+ ],
101
+ "outputs": [{ "name": "amountOut", "type": "uint256" }],
102
+ "stateMutability": "payable"
103
+ },
104
+ ];
105
+ // ==================== V3 费率配置 ====================
106
+ // USD1/USDT 使用 100 bps (0.01%),其他使用 2500 bps (0.25%)
107
+ const USD1_V3_FEE = 100;
108
+ const DEFAULT_V3_FEE = 2500;
86
109
  // ==================== 工具函数 ====================
87
110
  /** 构建 ERC20 approve 交易 */
88
111
  async function buildApproveTransaction(wallet, tokenAddress, spenderAddress, amount, nonce, gasPrice, txType, chainId = 56 // ✅ 添加 chainId 参数
@@ -135,42 +158,12 @@ function splitAmount(totalAmount, count) {
135
158
  allocated += amount;
136
159
  }
137
160
  amounts.push(totalAmount - allocated);
138
- return amounts;
139
- }
140
- /** 解析输入金额字符串为 bigint(按是否原生币选择 parseEther / parseUnits) */
141
- function parseQuoteAmount(amount, useNativeToken, quoteTokenDecimals) {
142
- const v = String(amount ?? '').trim();
143
- if (!v)
144
- return 0n;
145
- return useNativeToken ? ethers.parseEther(v) : ethers.parseUnits(v, quoteTokenDecimals);
146
- }
147
- /**
148
- * 计算每个买家的买入金额(优先使用 params 传入的 buyAmount;否则 fallback 到按总额随机拆分)
149
- * 说明:memeweb 前端已根据 average/random/custom 计算出每个钱包 buyAmount;
150
- * 若 SDK 这里再次 splitAmount,会导致实际 buyAmount 与 UI/预期不一致,并引发余额不足(insufficient funds)。
151
- */
152
- function resolveBuyerAmounts(buyers, totalAmountStr, useNativeToken, quoteTokenDecimals) {
153
- const provided = buyers.map(b => b?.buyAmount).filter(v => v != null && String(v).trim() !== '');
154
- const allProvided = provided.length === buyers.length;
155
- if (allProvided) {
156
- // ✅ 所有买家都显式提供了 buyAmount:按传入金额构建,但要修正“浮点/四舍五入导致总和偏差”
157
- const amounts = buyers.map(b => parseQuoteAmount(String(b.buyAmount), useNativeToken, quoteTokenDecimals));
158
- const totalWei = parseQuoteAmount(totalAmountStr, useNativeToken, quoteTokenDecimals);
159
- const sum = amounts.reduce((a, b) => a + b, 0n);
160
- const delta = totalWei - sum;
161
- if (delta !== 0n && amounts.length > 0) {
162
- // 优先修正最后一个金额(对应 create-to-dex 里“最后一单可能触发毕业”的假设)
163
- const lastIdx = amounts.length - 1;
164
- const next = amounts[lastIdx] + delta;
165
- if (next <= 0n) {
166
- throw new Error(`买入金额总和与总额不一致且无法修正:sum=${sum} total=${totalWei} delta=${delta}`);
167
- }
168
- amounts[lastIdx] = next;
169
- }
170
- return amounts;
161
+ // 随机打乱
162
+ for (let i = amounts.length - 1; i > 0; i--) {
163
+ const j = Math.floor(Math.random() * (i + 1));
164
+ [amounts[i], amounts[j]] = [amounts[j], amounts[i]];
171
165
  }
172
- const totalWei = parseQuoteAmount(totalAmountStr, useNativeToken, quoteTokenDecimals);
173
- return splitAmount(totalWei, buyers.length);
166
+ return amounts;
174
167
  }
175
168
  // ==================== 主函数 ====================
176
169
  /**
@@ -192,32 +185,6 @@ export async function flapBundleCreateToDex(params) {
192
185
  // 判断是否使用原生代币
193
186
  const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
194
187
  const inputToken = useNativeToken ? ZERO_ADDRESS : quoteToken;
195
- // ✅ 计算实际使用的 V3 费率
196
- // 优先级:lpFeeProfile > v3Fee > 默认值(根据 quoteToken)
197
- // lpFeeProfile: 0=STANDARD(0.25%), 1=LOW(0.01%), 2=HIGH(1%)
198
- let actualV3Fee;
199
- if (params.lpFeeProfile !== undefined) {
200
- // 从 lpFeeProfile 转换为 V3 费率
201
- switch (params.lpFeeProfile) {
202
- case 1:
203
- actualV3Fee = 100;
204
- break; // LOW: 0.01%
205
- case 2:
206
- actualV3Fee = 10000;
207
- break; // HIGH: 1%
208
- default:
209
- actualV3Fee = 2500;
210
- break; // STANDARD: 0.25%
211
- }
212
- }
213
- else if (v3Fee !== undefined && v3Fee !== 2500) {
214
- actualV3Fee = v3Fee;
215
- }
216
- else {
217
- // 根据 quoteToken 使用默认值(参考 Flap 官方配置)
218
- // BNB → 0.25% (2500), USD1/稳定币 → 0.01% (100)
219
- actualV3Fee = useNativeToken ? 2500 : 100;
220
- }
221
188
  // ✅ 获取链配置
222
189
  const chainConfig = getChainConfig(chain);
223
190
  const chainId = chainConfig.chainId;
@@ -264,11 +231,17 @@ export async function flapBundleCreateToDex(params) {
264
231
  const bribeAmount = getBribeAmount(config);
265
232
  const needBribeTx = bribeAmount > 0n;
266
233
  // ✅ 计算内盘买入金额
267
- const curveBuyAmounts = resolveBuyerAmounts(curveBuyers, curveTotalBuyAmount, useNativeToken, quoteTokenDecimals);
234
+ const curveTotalWei = useNativeToken
235
+ ? ethers.parseEther(curveTotalBuyAmount)
236
+ : ethers.parseUnits(curveTotalBuyAmount, quoteTokenDecimals);
237
+ const curveBuyAmounts = splitAmount(curveTotalWei, curveBuyers.length);
268
238
  // ✅ 计算外盘买入金额
269
239
  let dexBuyAmounts = [];
270
240
  if (enableDexBuy && dexBuyers.length > 0 && dexTotalBuyAmount) {
271
- dexBuyAmounts = resolveBuyerAmounts(dexBuyers, dexTotalBuyAmount, useNativeToken, quoteTokenDecimals);
241
+ const dexTotalWei = useNativeToken
242
+ ? ethers.parseEther(dexTotalBuyAmount)
243
+ : ethers.parseUnits(dexTotalBuyAmount, quoteTokenDecimals);
244
+ dexBuyAmounts = splitAmount(dexTotalWei, dexBuyers.length);
272
245
  }
273
246
  // ✅ 计算利润
274
247
  const totalBuyAmount = curveBuyAmounts.reduce((a, b) => a + b, 0n)
@@ -276,7 +249,7 @@ export async function flapBundleCreateToDex(params) {
276
249
  const profitAmount = (totalBuyAmount * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
277
250
  // ==================== 构建交易 ====================
278
251
  const allTransactions = [];
279
- // 使用第一个内盘买家作为贿赂支付者(提高 bundle 打包优先级)
252
+ // 使用第一个内盘买家作为贿赂和利润支付者
280
253
  const mainBuyerWallet = curveWallets[0].wallet;
281
254
  // 1. 贿赂交易
282
255
  if (needBribeTx) {
@@ -397,16 +370,12 @@ export async function flapBundleCreateToDex(params) {
397
370
  const buyNonce = noncesMap.get(addr);
398
371
  noncesMap.set(addr, buyNonce + 1);
399
372
  const portal = new Contract(portalAddress, PORTAL_ABI, wallet);
400
- // 交易阶段统一优先使用 swapExactInputV3(支持 extensionData;无扩展时传 0x 即可)
401
- // 说明:这里的 V3 指“交易接口版本(扩展支持)”,不是“外盘 V3 池子”
402
- const extensionData = params.extensionData ?? '0x';
403
- const unsigned = await portal.swapExactInputV3.populateTransaction({
373
+ const unsigned = await portal.swapExactInput.populateTransaction({
404
374
  inputToken,
405
375
  outputToken: tokenAddress,
406
376
  inputAmount: curveBuyAmounts[i],
407
377
  minOutputAmount: 0n,
408
- permitData: '0x', // 不使用 permit,使用链上 approve
409
- extensionData
378
+ permitData: '0x' // 不使用 permit,使用链上 approve
410
379
  }, useNativeToken ? { value: curveBuyAmounts[i] } : {});
411
380
  // 最后一个买家触发毕业,需要更多 gas
412
381
  const isLastBuyer = i === curveWallets.length - 1;
@@ -434,58 +403,63 @@ export async function flapBundleCreateToDex(params) {
434
403
  const curveBuyResults = await Promise.all(curveBuyTxPromises);
435
404
  // 展平数组:每个钱包可能有 [approve, buy] 或只有 [buy]
436
405
  curveBuyResults.forEach(txs => allTransactions.push(...txs));
437
- // 4. 外盘买入交易(直接调用 PancakeSwap Router
438
- // ✅ 重要修改:直接调用 PancakeSwap SmartRouter 的 exactInputSingle
439
- // 参考官方代码: flap-bundle-release/app/v2/pvp/001_launch_buy.ts
440
- //
441
- // 原因:之前使用 Portal 的 swapExactInputV3 进行"自动路由",但这有风险:
442
- // - 如果代币刚毕业,Portal 可能还没有正确记录池子信息
443
- // - 导致路由失败或回退到内盘
444
- //
445
- // 新方案:毕业后直接调用 PancakeSwap Router,确保外盘交易成功
406
+ // 4. 外盘买入交易(PancakeSwap)
407
+ // ✅ ERC20 需要先 approve,再 swap
446
408
  if (enableDexBuy && dexWallets.length > 0) {
447
- // 获取 DEX 地址
448
- const dexAddresses = chain === 'xlayer' ? DEX_ADDRESSES.XLAYER : DEX_ADDRESSES.BSC;
449
- const smartRouterAddress = dexAddresses.PANCAKE_SMART_ROUTER;
450
- const wbnbAddress = dexAddresses.WBNB;
451
- // 获取 V3 费率
452
- // 根据 lpFeeProfile 或 quoteToken 选择
453
- const dexV3Fee = actualV3Fee;
454
409
  const dexBuyTxPromises = dexWallets.map(async ({ wallet }, i) => {
455
410
  const addr = wallet.address.toLowerCase();
456
411
  const signedTxs = [];
457
412
  const buyAmount = dexBuyAmounts[i];
458
- // ✅ ERC20: 先构建 approve 交易(approve 给 PancakeSwap Router)
413
+ // ✅ 使用动态 Router 地址
414
+ const smartRouter = dexPoolType === 'v3' ? chainConfig.v3Router : chainConfig.v2Router;
415
+ const wrappedNative = chainConfig.wrappedNative;
416
+ // ✅ 根据 quoteToken 选择 V3 费率
417
+ const actualV3Fee = v3Fee || (useNativeToken ? DEFAULT_V3_FEE : USD1_V3_FEE);
418
+ // ✅ ERC20: 先构建 approve 交易
459
419
  if (!useNativeToken) {
460
420
  const approveNonce = noncesMap.get(addr);
461
421
  noncesMap.set(addr, approveNonce + 1);
462
- const approveTx = await buildApproveTransaction(wallet, quoteToken, smartRouterAddress, // ✅ approve 给 PancakeSwap Router
463
- buyAmount, approveNonce, gasPrice, txType, chainId);
422
+ const approveTx = await buildApproveTransaction(wallet, quoteToken, smartRouter, buyAmount, approveNonce, gasPrice, txType, chainId // ✅ 传递 chainId
423
+ );
464
424
  signedTxs.push(approveTx);
465
425
  }
466
- // 构建 PancakeSwap exactInputSingle 交易
426
+ // 构建买入交易
467
427
  const buyNonce = noncesMap.get(addr);
468
428
  noncesMap.set(addr, buyNonce + 1);
469
- const router = new Contract(smartRouterAddress, PANCAKE_ROUTER_ABI, wallet);
470
- // 对于 BNB,使用 WBNB 作为 tokenIn(Router 会自动 wrap)
471
- const tokenIn = useNativeToken ? wbnbAddress : quoteToken;
472
- const exactInputSingleParams = {
473
- tokenIn,
474
- tokenOut: tokenAddress,
475
- fee: dexV3Fee, // 使用与 newTokenV4 创建池子匹配的费率
476
- recipient: wallet.address,
477
- amountIn: buyAmount,
478
- amountOutMinimum: 0n, // 不设置滑点保护(Bundle 中可以接受)
479
- sqrtPriceLimitX96: 0n
480
- };
481
- const unsigned = await router.exactInputSingle.populateTransaction(exactInputSingleParams, useNativeToken ? { value: buyAmount } : {});
429
+ let multicallData = [];
430
+ let value;
431
+ const routerInterface = new ethers.Interface(PANCAKE_V3_ROUTER_ABI);
432
+ if (dexPoolType === 'v3') {
433
+ // V3: exactInputSingle
434
+ const params = {
435
+ tokenIn: useNativeToken ? wrappedNative : quoteToken,
436
+ tokenOut: tokenAddress,
437
+ fee: actualV3Fee,
438
+ recipient: wallet.address,
439
+ amountIn: buyAmount,
440
+ amountOutMinimum: 0n,
441
+ sqrtPriceLimitX96: 0n
442
+ };
443
+ multicallData = [routerInterface.encodeFunctionData('exactInputSingle', [params])];
444
+ value = useNativeToken ? buyAmount : 0n;
445
+ }
446
+ else {
447
+ // V2: swapExactTokensForTokens
448
+ const path = useNativeToken ? [wrappedNative, tokenAddress] : [quoteToken, tokenAddress];
449
+ const swapData = routerInterface.encodeFunctionData('swapExactTokensForTokens', [buyAmount, 0n, path, wallet.address]);
450
+ multicallData = [swapData];
451
+ value = useNativeToken ? buyAmount : 0n;
452
+ }
453
+ const calldata = routerInterface.encodeFunctionData('multicall', [multicallData]);
482
454
  const tx = {
483
- ...unsigned,
455
+ to: smartRouter,
456
+ data: calldata,
457
+ from: wallet.address,
484
458
  nonce: buyNonce,
485
459
  gasLimit: BigInt(500000),
486
460
  chainId,
487
461
  type: txType,
488
- value: useNativeToken ? buyAmount : 0n
462
+ value
489
463
  };
490
464
  if (txType === 2) {
491
465
  tx.maxFeePerGas = gasPrice;
@@ -505,13 +479,11 @@ export async function flapBundleCreateToDex(params) {
505
479
  // 5. 利润多跳转账
506
480
  let profitHopWallets;
507
481
  if (profitAmount > 0n) {
508
- // 调整:利润从 Dev 钱包(devPrivateKey)支付,避免第一个内盘买家余额不足导致 want 过高
509
- // 注意:利润交易会额外消耗原生币(profitAmount + gas),请确保 Dev 钱包留足余额
510
- const devAddr = devWallet.address.toLowerCase();
511
- const profitNonce = noncesMap.get(devAddr);
482
+ const mainAddr = mainBuyerWallet.address.toLowerCase();
483
+ const profitNonce = noncesMap.get(mainAddr);
512
484
  const profitResult = await buildProfitHopTransactions({
513
485
  provider,
514
- payerWallet: devWallet,
486
+ payerWallet: mainBuyerWallet,
515
487
  profitAmount,
516
488
  profitRecipient: getProfitRecipient(),
517
489
  hopCount: PROFIT_HOP_COUNT,
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * as Abis from './abis/index.js';
2
+ export * as Sol from './sol/index.js';
2
3
  export { ERC20_ABI, ERC20_BALANCE_ABI, ERC20_ALLOWANCE_ABI, MULTICALL3_ABI, V2_ROUTER_ABI, V2_ROUTER_QUOTE_ABI, V3_ROUTER02_ABI, V3_ROUTER_LEGACY_ABI, V3_QUOTER_ABI, V2_FACTORY_ABI, V2_PAIR_ABI, V3_FACTORY_ABI, V3_POOL_ABI, FLAP_PORTAL_ABI, TM2_ABI, HELPER3_ABI, } from './abis/common.js';
3
4
  export { ADDRESSES, CHAIN, BLOCKRAZOR_BUILDER_EOA as BUILDER_EOA, ZERO_ADDRESS as COMMON_ZERO_ADDRESS, DEFAULT_DEADLINE_MINUTES, V3_FEE_TIERS as COMMON_V3_FEE_TIERS, } from './utils/constants.js';
4
5
  export { isExclusiveOnChain, isExclusiveOffChain } from './utils/mpcExclusive.js';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // 公共 ABI(统一管理)
3
3
  // ============================================================================
4
4
  export * as Abis from './abis/index.js';
5
- // export * as Sol from './sol/index.js';
5
+ export * as Sol from './sol/index.js';
6
6
  export { ERC20_ABI, ERC20_BALANCE_ABI, ERC20_ALLOWANCE_ABI, MULTICALL3_ABI, V2_ROUTER_ABI, V2_ROUTER_QUOTE_ABI, V3_ROUTER02_ABI, V3_ROUTER_LEGACY_ABI, V3_QUOTER_ABI, V2_FACTORY_ABI, V2_PAIR_ABI, V3_FACTORY_ABI, V3_POOL_ABI, FLAP_PORTAL_ABI, TM2_ABI, HELPER3_ABI, } from './abis/common.js';
7
7
  // ============================================================================
8
8
  // 公共常量(统一管理)