four-flap-meme-sdk 1.2.64 → 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
|
-
|
|
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
|
-
|
|
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
|
-
// ✅
|
|
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
|
|
192
|
+
tokenAddress,
|
|
145
193
|
metadata
|
|
146
194
|
};
|
|
147
195
|
}
|