four-flap-meme-sdk 1.2.76 → 1.2.78
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.
|
@@ -225,17 +225,12 @@ export async function batchBuyWithBundleMerkle(params) {
|
|
|
225
225
|
throw new Error(getErrorMessage('KEY_AMOUNT_MISMATCH'));
|
|
226
226
|
}
|
|
227
227
|
const { provider, chainId } = createChainContext(config.rpcUrl);
|
|
228
|
-
const buyers = createWallets(privateKeys, provider);
|
|
229
228
|
const txType = getTxType(config);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
(
|
|
234
|
-
|
|
235
|
-
// 预加载所有钱包的 nonce(批量查询)
|
|
236
|
-
await Promise.all(buyers.map(w => nm.getNextNonce(w)));
|
|
237
|
-
return nm;
|
|
238
|
-
})()
|
|
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))
|
|
239
234
|
]);
|
|
240
235
|
const buyFlow = await executeBuyFlow({
|
|
241
236
|
wallets: buyers,
|
|
@@ -261,17 +256,12 @@ export async function batchSellWithBundleMerkle(params) {
|
|
|
261
256
|
throw new Error(getErrorMessage('SELL_KEY_AMOUNT_MISMATCH'));
|
|
262
257
|
}
|
|
263
258
|
const { provider, chainId } = createChainContext(config.rpcUrl);
|
|
264
|
-
const sellers = createWallets(privateKeys, provider);
|
|
265
259
|
const txType = getTxType(config);
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
(
|
|
270
|
-
|
|
271
|
-
// 预加载所有钱包的 nonce(批量查询)
|
|
272
|
-
await Promise.all(sellers.map(w => nm.getNextNonce(w)));
|
|
273
|
-
return nm;
|
|
274
|
-
})()
|
|
260
|
+
const sellers = createWallets(privateKeys, provider);
|
|
261
|
+
// ✅ 优化:并行初始化 nonceManager 和获取 gasPrice
|
|
262
|
+
const [nonceManager, gasPrice] = await Promise.all([
|
|
263
|
+
Promise.resolve(new NonceManager(provider)),
|
|
264
|
+
getOptimizedGasPrice(provider, getGasPriceConfig(config))
|
|
275
265
|
]);
|
|
276
266
|
const sellFlow = await executeSellFlow({
|
|
277
267
|
wallets: sellers,
|
|
@@ -128,21 +128,16 @@ 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 nonceManager = new NonceManager(provider);
|
|
132
|
+
const signedTxs = [];
|
|
131
133
|
const buyers = createWallets(privateKeys, provider);
|
|
132
134
|
const extractProfit = shouldExtractProfit(config);
|
|
133
135
|
const { fundsList, originalAmounts, totalBuyAmount, totalProfit } = analyzeBuyFunds(buyAmounts, config, extractProfit);
|
|
134
136
|
const maxFundsIndex = findMaxIndex(originalAmounts);
|
|
135
137
|
const gasLimits = buildGasLimitList(buyers.length, config);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const [gasPrice, nonceManager, unsignedBuys] = await Promise.all([
|
|
138
|
+
// ✅ 优化:并行执行 gasPrice 和 populateBuyTransactions(最耗时的两个操作)
|
|
139
|
+
const [gasPrice, unsignedBuys] = await Promise.all([
|
|
139
140
|
resolveGasPrice(provider, config),
|
|
140
|
-
(async () => {
|
|
141
|
-
const nm = new NonceManager(provider);
|
|
142
|
-
// 预加载所有钱包的 nonce(批量查询)
|
|
143
|
-
await Promise.all(buyers.map(w => nm.getNextNonce(w)));
|
|
144
|
-
return nm;
|
|
145
|
-
})(),
|
|
146
141
|
populateBuyTransactions(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress, fundsList)
|
|
147
142
|
]);
|
|
148
143
|
const buyerNonces = await allocateBuyerNonces(buyers, extractProfit, maxFundsIndex, totalProfit, nonceManager);
|
|
@@ -184,35 +179,28 @@ export async function batchSellWithBundleMerkle(params) {
|
|
|
184
179
|
throw new Error(getErrorMessage('SELL_KEY_AMOUNT_MISMATCH'));
|
|
185
180
|
}
|
|
186
181
|
const { provider, chainId } = createChainContext(chain, config.rpcUrl);
|
|
182
|
+
const nonceManager = new NonceManager(provider);
|
|
183
|
+
const signedTxs = [];
|
|
187
184
|
const wallets = createWallets(privateKeys, provider);
|
|
188
185
|
const amountsWei = sellAmounts.map(a => ethers.parseUnits(a, 18));
|
|
189
186
|
const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
|
|
190
187
|
const readOnlyPortal = new ethers.Contract(portalAddr, PORTAL_ABI, provider);
|
|
191
188
|
const gasLimits = buildGasLimitList(wallets.length, config);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const [gasPrice, nonceManager, quotedOutputs] = await Promise.all([
|
|
189
|
+
// ✅ 优化:并行执行 gasPrice 和 quoteSellOutputs(最耗时的两个操作)
|
|
190
|
+
const [gasPrice, quotedOutputs] = await Promise.all([
|
|
195
191
|
resolveGasPrice(provider, config),
|
|
196
|
-
(async () => {
|
|
197
|
-
const nm = new NonceManager(provider);
|
|
198
|
-
// 预加载所有钱包的 nonce(批量查询)
|
|
199
|
-
await Promise.all(wallets.map(w => nm.getNextNonce(w)));
|
|
200
|
-
return nm;
|
|
201
|
-
})(),
|
|
202
192
|
quoteSellOutputs(readOnlyPortal, tokenAddress, amountsWei)
|
|
203
193
|
]);
|
|
204
194
|
const minOuts = resolveMinOutputs(minOutputAmounts, wallets.length, quotedOutputs);
|
|
205
|
-
|
|
206
|
-
const unsignedList = await Promise.all(
|
|
195
|
+
const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
|
|
196
|
+
const unsignedList = await Promise.all(portals.map((portal, i) => portal.swapExactInput.populateTransaction({
|
|
207
197
|
inputToken: tokenAddress,
|
|
208
198
|
outputToken: ZERO_ADDRESS,
|
|
209
199
|
inputAmount: amountsWei[i],
|
|
210
200
|
minOutputAmount: minOuts[i],
|
|
211
201
|
permitData: '0x'
|
|
212
202
|
})));
|
|
213
|
-
// ✅ 优化:批量获取 nonces(已预加载,直接从缓存读取)
|
|
214
203
|
const nonces = await Promise.all(wallets.map(w => nonceManager.getNextNonce(w)));
|
|
215
|
-
// ✅ 优化:批量签名交易
|
|
216
204
|
const signedList = await Promise.all(unsignedList.map((unsigned, i) => wallets[i].signTransaction({
|
|
217
205
|
...unsigned,
|
|
218
206
|
from: wallets[i].address,
|
|
@@ -288,15 +276,14 @@ function findMaxIndex(values) {
|
|
|
288
276
|
return maxIndex;
|
|
289
277
|
}
|
|
290
278
|
async function populateBuyTransactions(buyers, portalAddr, tokenAddress, fundsList) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return await Promise.all(fundsList.map((funds) => portal.swapExactInput.populateTransaction({
|
|
279
|
+
const portals = buyers.map(wallet => new ethers.Contract(portalAddr, PORTAL_ABI, wallet));
|
|
280
|
+
return await Promise.all(portals.map((portal, i) => portal.swapExactInput.populateTransaction({
|
|
294
281
|
inputToken: ZERO_ADDRESS,
|
|
295
282
|
outputToken: tokenAddress,
|
|
296
|
-
inputAmount:
|
|
283
|
+
inputAmount: fundsList[i],
|
|
297
284
|
minOutputAmount: 0n,
|
|
298
285
|
permitData: '0x'
|
|
299
|
-
}, { value:
|
|
286
|
+
}, { value: fundsList[i] })));
|
|
300
287
|
}
|
|
301
288
|
function buildGasLimitList(length, config) {
|
|
302
289
|
const gasLimit = getGasLimit(config);
|
package/dist/utils/erc20.js
CHANGED
|
@@ -502,51 +502,56 @@ export async function approveTokenBatchRaw(params) {
|
|
|
502
502
|
// 验证地址
|
|
503
503
|
await validateContractAddress(provider, normalizedToken, 'Token');
|
|
504
504
|
await validateContractAddress(provider, normalizedSpender, 'Spender');
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
505
|
+
// ✅ 优化:批量创建钱包和合约实例
|
|
506
|
+
const wallets = privateKeys.map(key => new Wallet(key, provider));
|
|
507
|
+
const ownerAddresses = wallets.map(w => w.address);
|
|
508
|
+
const requiredAmounts = amounts.map(amount => amount === 'max'
|
|
509
|
+
? BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
|
|
510
|
+
: amount);
|
|
511
|
+
// ✅ 优化:并行检查所有钱包的授权额度
|
|
512
|
+
const currentAllowances = await batchCheckAllowances(provider, normalizedToken, ownerAddresses, normalizedSpender);
|
|
513
|
+
// ✅ 优化:并行发送所有需要授权的交易
|
|
514
|
+
const approvalPromises = wallets.map(async (wallet, i) => {
|
|
515
|
+
const ownerAddress = ownerAddresses[i];
|
|
516
|
+
const currentAllowance = currentAllowances[i];
|
|
517
|
+
const requiredAmount = requiredAmounts[i];
|
|
514
518
|
try {
|
|
515
|
-
|
|
516
|
-
// 检查当前授权
|
|
517
|
-
const currentAllowance = await erc20.allowance(ownerAddress, normalizedSpender);
|
|
519
|
+
// 如果已经授权足够,跳过
|
|
518
520
|
if (currentAllowance >= requiredAmount) {
|
|
519
|
-
|
|
521
|
+
return {
|
|
520
522
|
owner: ownerAddress,
|
|
521
523
|
alreadyApproved: true,
|
|
522
524
|
currentAllowance,
|
|
523
525
|
requiredAllowance: requiredAmount
|
|
524
|
-
}
|
|
525
|
-
continue;
|
|
526
|
+
};
|
|
526
527
|
}
|
|
527
528
|
// 发送授权交易
|
|
529
|
+
const erc20 = new Contract(normalizedToken, ERC20_ABI, wallet);
|
|
528
530
|
const tx = await erc20.approve(normalizedSpender, requiredAmount);
|
|
529
531
|
const receipt = await tx.wait();
|
|
530
|
-
|
|
532
|
+
return {
|
|
531
533
|
owner: ownerAddress,
|
|
532
534
|
alreadyApproved: false,
|
|
533
535
|
currentAllowance,
|
|
534
536
|
requiredAllowance: requiredAmount,
|
|
535
537
|
txHash: receipt.hash
|
|
536
|
-
}
|
|
537
|
-
approvedCount++;
|
|
538
|
+
};
|
|
538
539
|
}
|
|
539
540
|
catch (error) {
|
|
540
|
-
|
|
541
|
+
return {
|
|
541
542
|
owner: ownerAddress,
|
|
542
543
|
alreadyApproved: false,
|
|
543
|
-
currentAllowance
|
|
544
|
+
currentAllowance,
|
|
544
545
|
requiredAllowance: requiredAmount,
|
|
545
546
|
error: error.message
|
|
546
|
-
}
|
|
547
|
-
errorCount++;
|
|
547
|
+
};
|
|
548
548
|
}
|
|
549
|
-
}
|
|
549
|
+
});
|
|
550
|
+
// ✅ 优化:并行等待所有授权交易完成
|
|
551
|
+
const results = await Promise.all(approvalPromises);
|
|
552
|
+
// 统计结果
|
|
553
|
+
const approvedCount = results.filter(r => !r.alreadyApproved && !r.error).length;
|
|
554
|
+
const errorCount = results.filter(r => r.error).length;
|
|
550
555
|
// ✅ 只要没有错误,就算成功(包括所有钱包都已授权的情况)
|
|
551
556
|
return {
|
|
552
557
|
success: errorCount === 0,
|