four-flap-meme-sdk 1.2.75 → 1.2.77
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.
|
@@ -5,7 +5,6 @@ import { FourClient, buildLoginMessage } from '../../clients/four.js';
|
|
|
5
5
|
import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient } from './config.js';
|
|
6
6
|
import { batchCheckAllowances } from '../../utils/erc20.js';
|
|
7
7
|
import { trySell } from '../tm.js';
|
|
8
|
-
import TM2Abi from '../../abis/TokenManager2.json' with { type: 'json' };
|
|
9
8
|
const TM2_ABI = [
|
|
10
9
|
'function createToken(bytes args, bytes signature) payable',
|
|
11
10
|
'function buyTokenAMAP(uint256 origin, address token, address to, uint256 funds, uint256 minAmount) payable',
|
|
@@ -188,18 +187,25 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
188
187
|
throw new Error('等待交易确认超时');
|
|
189
188
|
}
|
|
190
189
|
console.log(`✅ 创建交易已确认,区块: ${receipt.blockNumber}`);
|
|
191
|
-
// 解析
|
|
190
|
+
// ✅ 解析 TokenCreate 事件(Four.meme 使用的事件名,注意没有 'd')
|
|
192
191
|
let tokenAddress;
|
|
192
|
+
// 使用 TM2 ABI 解析事件
|
|
193
|
+
const tm2Interface = new ethers.Interface(TM2_ABI);
|
|
193
194
|
for (const log of receipt.logs) {
|
|
194
195
|
try {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
const parsed = tm2Interface.parseLog({
|
|
197
|
+
topics: log.topics,
|
|
198
|
+
data: log.data
|
|
199
|
+
});
|
|
200
|
+
// Four.meme 的事件是 TokenCreate(不是 TokenCreated)
|
|
201
|
+
if (parsed && parsed.name === 'TokenCreate') {
|
|
202
|
+
tokenAddress = parsed.args.token;
|
|
203
|
+
console.log(`✅ 从 TokenCreate 事件解析代币地址: ${tokenAddress}`);
|
|
198
204
|
break;
|
|
199
205
|
}
|
|
200
206
|
}
|
|
201
207
|
catch (e) {
|
|
202
|
-
//
|
|
208
|
+
// 忽略无法解析的日志
|
|
203
209
|
}
|
|
204
210
|
}
|
|
205
211
|
if (!tokenAddress) {
|
|
@@ -213,69 +219,19 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
213
219
|
txHashes
|
|
214
220
|
};
|
|
215
221
|
}
|
|
216
|
-
/**
|
|
217
|
-
* 等待交易上链并解析代币地址
|
|
218
|
-
*/
|
|
219
|
-
async function waitAndParseTokenAddress(provider, createTxSigned, bundleUuid) {
|
|
220
|
-
console.log('⏳ 等待交易上链,解析代币地址...');
|
|
221
|
-
let tokenAddress = ZERO_ADDRESS;
|
|
222
|
-
const maxAttempts = 30; // 最多等待 30 秒
|
|
223
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
224
|
-
await new Promise(resolve => setTimeout(resolve, 1000)); // 等待 1 秒
|
|
225
|
-
try {
|
|
226
|
-
// 获取创建交易的回执
|
|
227
|
-
const createTxHash = ethers.keccak256(createTxSigned);
|
|
228
|
-
const receipt = await provider.getTransactionReceipt(createTxHash);
|
|
229
|
-
if (receipt && receipt.status === 1) {
|
|
230
|
-
// 从事件日志中解析代币地址
|
|
231
|
-
const tm2Interface = new ethers.Interface(TM2Abi);
|
|
232
|
-
for (const log of receipt.logs) {
|
|
233
|
-
try {
|
|
234
|
-
const parsed = tm2Interface.parseLog({
|
|
235
|
-
topics: log.topics,
|
|
236
|
-
data: log.data
|
|
237
|
-
});
|
|
238
|
-
if (parsed && parsed.name === 'TokenCreate') {
|
|
239
|
-
tokenAddress = parsed.args.token;
|
|
240
|
-
console.log(`✅ 成功解析代币地址: ${tokenAddress}`);
|
|
241
|
-
return tokenAddress;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
catch (e) {
|
|
245
|
-
// 忽略无法解析的日志
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
// 如果没有找到 TokenCreate 事件,尝试 TokenCreated
|
|
249
|
-
const tokenCreatedTopic = ethers.id('TokenCreated(address,address,uint256,uint256,uint256,uint256)');
|
|
250
|
-
for (const log of receipt.logs) {
|
|
251
|
-
if (log.topics[0] === tokenCreatedTopic) {
|
|
252
|
-
tokenAddress = ethers.getAddress('0x' + log.topics[1].slice(26));
|
|
253
|
-
console.log(`✅ 成功解析代币地址: ${tokenAddress}`);
|
|
254
|
-
return tokenAddress;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
catch (error) {
|
|
261
|
-
// 继续等待
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
if (tokenAddress === ZERO_ADDRESS) {
|
|
265
|
-
console.warn('⚠️ 未能从事件中解析代币地址,返回 0x0');
|
|
266
|
-
}
|
|
267
|
-
return tokenAddress;
|
|
268
|
-
}
|
|
269
222
|
export async function batchBuyWithBundleMerkle(params) {
|
|
270
223
|
const { privateKeys, buyAmounts, tokenAddress, config } = params;
|
|
271
224
|
if (privateKeys.length === 0 || buyAmounts.length !== privateKeys.length) {
|
|
272
225
|
throw new Error(getErrorMessage('KEY_AMOUNT_MISMATCH'));
|
|
273
226
|
}
|
|
274
227
|
const { provider, chainId } = createChainContext(config.rpcUrl);
|
|
275
|
-
const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
|
|
276
|
-
const nonceManager = new NonceManager(provider);
|
|
277
228
|
const txType = getTxType(config);
|
|
278
229
|
const buyers = createWallets(privateKeys, provider);
|
|
230
|
+
// ✅ 优化:并行初始化 nonceManager 和获取 gasPrice
|
|
231
|
+
const [nonceManager, gasPrice] = await Promise.all([
|
|
232
|
+
Promise.resolve(new NonceManager(provider)),
|
|
233
|
+
getOptimizedGasPrice(provider, getGasPriceConfig(config))
|
|
234
|
+
]);
|
|
279
235
|
const buyFlow = await executeBuyFlow({
|
|
280
236
|
wallets: buyers,
|
|
281
237
|
buyAmounts,
|
|
@@ -128,15 +128,18 @@ export async function batchBuyWithBundleMerkle(params) {
|
|
|
128
128
|
throw new Error(getErrorMessage('KEY_AMOUNT_MISMATCH'));
|
|
129
129
|
}
|
|
130
130
|
const { provider, chainId } = createChainContext(chain, config.rpcUrl);
|
|
131
|
-
const gasPrice = await resolveGasPrice(provider, config);
|
|
132
131
|
const nonceManager = new NonceManager(provider);
|
|
133
132
|
const signedTxs = [];
|
|
134
133
|
const buyers = createWallets(privateKeys, provider);
|
|
135
134
|
const extractProfit = shouldExtractProfit(config);
|
|
136
135
|
const { fundsList, originalAmounts, totalBuyAmount, totalProfit } = analyzeBuyFunds(buyAmounts, config, extractProfit);
|
|
137
136
|
const maxFundsIndex = findMaxIndex(originalAmounts);
|
|
138
|
-
const unsignedBuys = await populateBuyTransactions(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress, fundsList);
|
|
139
137
|
const gasLimits = buildGasLimitList(buyers.length, config);
|
|
138
|
+
// ✅ 优化:并行执行 gasPrice 和 populateBuyTransactions(最耗时的两个操作)
|
|
139
|
+
const [gasPrice, unsignedBuys] = await Promise.all([
|
|
140
|
+
resolveGasPrice(provider, config),
|
|
141
|
+
populateBuyTransactions(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress, fundsList)
|
|
142
|
+
]);
|
|
140
143
|
const buyerNonces = await allocateBuyerNonces(buyers, extractProfit, maxFundsIndex, totalProfit, nonceManager);
|
|
141
144
|
const signedBuys = await signBuyTransactions({
|
|
142
145
|
unsignedBuys,
|