four-flap-meme-sdk 1.2.63 → 1.2.65

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.
@@ -2,6 +2,7 @@ import { ethers, Wallet } from 'ethers';
2
2
  import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
3
3
  import { ADDRESSES } from '../../utils/constants.js';
4
4
  import { FourClient, buildLoginMessage } from '../../clients/four.js';
5
+ import { Club48Client } from '../../clients/club48.js';
5
6
  import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient } from './config.js';
6
7
  import { batchCheckAllowances } from '../../utils/erc20.js';
7
8
  import { trySell } from '../tm.js';
@@ -37,10 +38,12 @@ export async function createTokenWithBundleBuyMerkle(params) {
37
38
  }
38
39
  const creatorKey = privateKeys[0];
39
40
  const buyerKeys = privateKeys.slice(1);
40
- const { provider, chainId } = createChainContext(config.rpcUrl);
41
+ // 使用 48.club RPC 节点(不使用用户传入的 rpcUrl
42
+ const club48Endpoint = config.club48Endpoint || 'https://puissant-bsc.48.club';
43
+ const { provider, chainId } = createChainContext(club48Endpoint);
41
44
  const devWallet = new Wallet(creatorKey, provider);
42
45
  const fourClient = new FourClient({ baseUrl: config.fourApiUrl });
43
- // 🔍 检查创建者余额(如果创建者也是买家,需要更多余额)
46
+ // 🔍 检查创建者余额
44
47
  const creatorBalance = await provider.getBalance(devWallet.address);
45
48
  const estimatedB0 = ethers.parseEther(params.b0Amount ?? '0');
46
49
  const estimatedPreSale = tokenInfo.preSale ? ethers.parseEther(tokenInfo.preSale) : 0n;
@@ -78,7 +81,6 @@ export async function createTokenWithBundleBuyMerkle(params) {
78
81
  funGroup: false,
79
82
  clickFun: false,
80
83
  });
81
- // 🔍 调试:打印 createResp 的内容
82
84
  console.log('🔍 Four.meme createToken 响应:', JSON.stringify(createResp, null, 2));
83
85
  const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
84
86
  const nonceManager = new NonceManager(provider);
@@ -103,12 +105,10 @@ export async function createTokenWithBundleBuyMerkle(params) {
103
105
  };
104
106
  signedTxs.push(await devWallet.signTransaction(createTxRequest));
105
107
  // ✅ Four.meme 特殊机制:使用 0x0 地址作为占位符
106
- // Four.meme buyTokenAMAP 方法支持传入 0x0 地址,合约会自动解析为最新创建的代币
107
- // 这是 Four.meme 独有的机制,允许在创建代币的同时进行买入
108
- const predictedTokenAddress = ZERO_ADDRESS; // 使用 0x0 作为占位符
108
+ const predictedTokenAddress = ZERO_ADDRESS;
109
109
  console.log('✅ 使用 Four.meme 特殊机制:0x0 地址将被合约自动解析为新创建的代币地址');
110
110
  let metadata;
111
- // ✅ 即使地址是 0x0,也可以生成买入交易(Four.meme 会自动处理)
111
+ // ✅ 生成买入和利润交易
112
112
  if (buyerKeys.length > 0) {
113
113
  const buyers = createWallets(buyerKeys, provider);
114
114
  // 🔍 找出买入金额最多的买家(由他支付所有利润)
@@ -130,7 +130,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
130
130
  contractAddress: tmBuyAddr,
131
131
  gasPrice,
132
132
  chainId,
133
- profitMode: { type: 'aggregated', payer: buyers[maxBuyerIndex] }, // ✅ 聚合模式:由买入最多的人支付
133
+ profitMode: { type: 'aggregated', payer: buyers[maxBuyerIndex] },
134
134
  txType
135
135
  });
136
136
  console.log(`✅ 生成了 ${buyFlow.signedTxs.length} 个买入和利润交易`);
@@ -139,9 +139,57 @@ export async function createTokenWithBundleBuyMerkle(params) {
139
139
  }
140
140
  nonceManager.clearTemp();
141
141
  console.log(`✅ 总共生成了 ${signedTxs.length} 个交易签名 (1创建 + ${buyerKeys.length}买入 + 利润)`);
142
+ // ✅ 使用 48.club Bundle 内部提交
143
+ console.log('📡 开始使用 48.club Bundle 提交交易...');
144
+ const club48 = new Club48Client({
145
+ endpoint: config.club48Endpoint,
146
+ explorerEndpoint: config.club48ExplorerEndpoint
147
+ });
148
+ const bundleHash = await club48.sendBundle({
149
+ txs: signedTxs
150
+ });
151
+ if (!bundleHash) {
152
+ throw new Error(`❌ 48.club Bundle 提交失败`);
153
+ }
154
+ console.log(`✅ Bundle 提交成功!BundleHash: ${bundleHash}`);
155
+ // ✅ 等待交易上链并解析代币地址
156
+ console.log('⏳ 等待交易上链,解析代币地址...');
157
+ let tokenAddress = predictedTokenAddress;
158
+ let attempts = 0;
159
+ const maxAttempts = 30; // 最多等待 30 秒
160
+ while (attempts < maxAttempts) {
161
+ await new Promise(resolve => setTimeout(resolve, 1000)); // 等待 1 秒
162
+ attempts++;
163
+ try {
164
+ // 获取第一笔交易(创建交易)的回执
165
+ const createTxHash = ethers.keccak256(signedTxs[0]);
166
+ const receipt = await provider.getTransactionReceipt(createTxHash);
167
+ if (receipt && receipt.status === 1) {
168
+ // 从事件日志中解析代币地址
169
+ // Four.meme 的 createToken 会触发 TokenCreated 事件
170
+ // 事件签名: TokenCreated(address indexed token, address indexed creator, ...)
171
+ const tokenCreatedTopic = ethers.id('TokenCreated(address,address,uint256,uint256,uint256,uint256)');
172
+ for (const log of receipt.logs) {
173
+ if (log.topics[0] === tokenCreatedTopic) {
174
+ // topics[1] 是 indexed token address
175
+ tokenAddress = ethers.getAddress('0x' + log.topics[1].slice(26));
176
+ console.log(`✅ 成功解析代币地址: ${tokenAddress}`);
177
+ break;
178
+ }
179
+ }
180
+ break;
181
+ }
182
+ }
183
+ catch (error) {
184
+ // 继续等待
185
+ }
186
+ }
187
+ if (tokenAddress === predictedTokenAddress) {
188
+ console.warn('⚠️ 未能从事件中解析代币地址,返回 0x0 占位符');
189
+ }
142
190
  return {
143
191
  signedTransactions: signedTxs,
144
- tokenAddress: predictedTokenAddress,
192
+ tokenAddress,
145
193
  metadata
146
194
  };
147
195
  }
@@ -1,6 +1,8 @@
1
1
  export type FourSignConfig = {
2
2
  rpcUrl: string;
3
3
  fourApiUrl?: string;
4
+ club48Endpoint?: string;
5
+ club48ExplorerEndpoint?: string;
4
6
  txType?: 0 | 2;
5
7
  gasLimit?: number | bigint;
6
8
  gasLimitMultiplier?: number;
@@ -187,12 +187,24 @@ export async function createTokenWithBundleBuy(params) {
187
187
  };
188
188
  const signedCreateTx = await devWallet.signTransaction(createTxRequest);
189
189
  signedTxs.push(signedCreateTx);
190
- // 4.2 购买交易 + 利润刮取
190
+ // 4.2 购买交易
191
191
  const buyTxs = [];
192
192
  const profitTxs = [];
193
+ const buyAmountsWei = [];
194
+ // 🔍 找出买入金额最多的买家(由他支付所有利润)
195
+ let maxBuyerIndex = 0;
196
+ let maxAmount = ethers.parseEther(buyAmounts[0]);
197
+ for (let i = 1; i < buyAmounts.length; i++) {
198
+ const amount = ethers.parseEther(buyAmounts[i]);
199
+ if (amount > maxAmount) {
200
+ maxAmount = amount;
201
+ maxBuyerIndex = i;
202
+ }
203
+ }
193
204
  for (let i = 0; i < buyAmounts.length; i++) {
194
205
  const buyerWallet = new Wallet(privateKeys[i + 1], provider);
195
206
  const fundsWei = ethers.parseEther(buyAmounts[i]);
207
+ buyAmountsWei.push(fundsWei);
196
208
  const minAmount = 0n;
197
209
  const buyTm2 = new ethers.Contract(tmAddr, TM2Abi, buyerWallet);
198
210
  const buyTxUnsigned = await buyTm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyerWallet.address, fundsWei, minAmount, { value: fundsWei });
@@ -214,21 +226,23 @@ export async function createTokenWithBundleBuy(params) {
214
226
  const signedBuyTx = await buyerWallet.signTransaction(buyTxRequest);
215
227
  signedTxs.push(signedBuyTx);
216
228
  buyTxs.push(signedBuyTx);
217
- // ✅ 刮取利润:每个买家买入后,立即转账利润
218
- const profitAmount = (fundsWei * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
219
- if (profitAmount > 0n) {
220
- const profitTx = await buyerWallet.signTransaction({
221
- to: PROFIT_CONFIG.RECIPIENT,
222
- value: profitAmount,
223
- nonce: await getNextNonce(buyerWallet),
224
- gasPrice,
225
- gasLimit: 21000n,
226
- chainId: 56,
227
- type: 0 // Legacy transaction
228
- });
229
- signedTxs.push(profitTx);
230
- profitTxs.push(profitTx);
231
- }
229
+ }
230
+ // 聚合利润:由买入最多的人支付总利润
231
+ const totalBuyAmount = buyAmountsWei.reduce((sum, amount) => sum + amount, 0n);
232
+ const totalProfitAmount = (totalBuyAmount * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
233
+ if (totalProfitAmount > 0n) {
234
+ const payerWallet = new Wallet(privateKeys[maxBuyerIndex + 1], provider);
235
+ const profitTx = await payerWallet.signTransaction({
236
+ to: PROFIT_CONFIG.RECIPIENT,
237
+ value: totalProfitAmount,
238
+ nonce: await getNextNonce(payerWallet),
239
+ gasPrice,
240
+ gasLimit: 21000n,
241
+ chainId: 56,
242
+ type: 0 // Legacy transaction
243
+ });
244
+ signedTxs.push(profitTx);
245
+ profitTxs.push(profitTx);
232
246
  }
233
247
  // 可选 tipTx
234
248
  if (config.tipAmountWei && config.tipAmountWei > 0n) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.2.63",
3
+ "version": "1.2.65",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",