four-flap-meme-sdk 1.2.99 → 1.3.2
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.
- package/dist/contracts/tm-bundle-merkle/index.d.ts +2 -1
- package/dist/contracts/tm-bundle-merkle/index.js +2 -1
- package/dist/contracts/tm-bundle-merkle/submit.d.ts +10 -0
- package/dist/contracts/tm-bundle-merkle/submit.js +104 -0
- package/dist/flap/portal-bundle-merkle/core.js +18 -4
- package/dist/flap/portal-bundle-merkle/types.d.ts +2 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +1 -1
|
@@ -9,5 +9,6 @@ export { fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle,
|
|
|
9
9
|
export { disperseWithBundleMerkle, sweepWithBundleMerkle } from './utils.js';
|
|
10
10
|
export { fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch } from './pancake-proxy.js';
|
|
11
11
|
export { approveFourTokenManagerBatch, type ApproveFourTokenManagerBatchParams, type ApproveFourTokenManagerBatchResult } from './approve-tokenmanager.js';
|
|
12
|
-
export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, type MerkleSubmitConfig, type SubmitBundleResult, submitDirectToRpc,
|
|
12
|
+
export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, type MerkleSubmitConfig, type SubmitBundleResult, submitDirectToRpc, submitDirectToRpcSequential, // ✅ 新增:顺序广播并等待确认(用于多跳)
|
|
13
|
+
submitDirectToRpcParallel, type DirectSubmitConfig, type DirectSubmitResult, type DirectTxResult } from './submit.js';
|
|
13
14
|
export { fourBundleBuyFirstMerkle, type FourBundleBuyFirstSignParams, type FourBuyFirstSignConfig, type FourBuyFirstResult } from './swap-buy-first.js';
|
|
@@ -18,6 +18,7 @@ export { approveFourTokenManagerBatch } from './approve-tokenmanager.js';
|
|
|
18
18
|
// Bundle提交方法(服务器端使用)
|
|
19
19
|
export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel,
|
|
20
20
|
// ✅ Monad 等链的逐笔广播方法
|
|
21
|
-
submitDirectToRpc,
|
|
21
|
+
submitDirectToRpc, submitDirectToRpcSequential, // ✅ 新增:顺序广播并等待确认(用于多跳)
|
|
22
|
+
submitDirectToRpcParallel } from './submit.js';
|
|
22
23
|
// 先买后卖换手方法
|
|
23
24
|
export { fourBundleBuyFirstMerkle } from './swap-buy-first.js';
|
|
@@ -163,6 +163,16 @@ export interface DirectSubmitResult {
|
|
|
163
163
|
* ```
|
|
164
164
|
*/
|
|
165
165
|
export declare function submitDirectToRpc(signedTransactions: string[], config: DirectSubmitConfig): Promise<DirectSubmitResult>;
|
|
166
|
+
/**
|
|
167
|
+
* ✅ 顺序广播并等待确认(用于多跳交易等需要顺序执行的场景)
|
|
168
|
+
*
|
|
169
|
+
* 每笔交易广播后会等待上链确认,确保后续交易能正确执行
|
|
170
|
+
*
|
|
171
|
+
* @param signedTransactions 签名后的交易数组
|
|
172
|
+
* @param config 直接广播配置
|
|
173
|
+
* @returns 广播结果
|
|
174
|
+
*/
|
|
175
|
+
export declare function submitDirectToRpcSequential(signedTransactions: string[], config: DirectSubmitConfig): Promise<DirectSubmitResult>;
|
|
166
176
|
/**
|
|
167
177
|
* 并行逐笔广播到 RPC(速度更快,但可能有 nonce 冲突)
|
|
168
178
|
*
|
|
@@ -223,6 +223,110 @@ export async function submitDirectToRpc(signedTransactions, config) {
|
|
|
223
223
|
errorSummary: errors.length > 0 ? errors.join('; ') : undefined
|
|
224
224
|
};
|
|
225
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* ✅ 顺序广播并等待确认(用于多跳交易等需要顺序执行的场景)
|
|
228
|
+
*
|
|
229
|
+
* 每笔交易广播后会等待上链确认,确保后续交易能正确执行
|
|
230
|
+
*
|
|
231
|
+
* @param signedTransactions 签名后的交易数组
|
|
232
|
+
* @param config 直接广播配置
|
|
233
|
+
* @returns 广播结果
|
|
234
|
+
*/
|
|
235
|
+
export async function submitDirectToRpcSequential(signedTransactions, config) {
|
|
236
|
+
const totalTransactions = signedTransactions?.length ?? 0;
|
|
237
|
+
if (!signedTransactions || signedTransactions.length === 0) {
|
|
238
|
+
return {
|
|
239
|
+
code: false,
|
|
240
|
+
totalTransactions: 0,
|
|
241
|
+
successCount: 0,
|
|
242
|
+
failedCount: 0,
|
|
243
|
+
txHashes: [],
|
|
244
|
+
results: [],
|
|
245
|
+
errorSummary: 'signedTransactions cannot be empty'
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (!config.rpcUrl) {
|
|
249
|
+
return {
|
|
250
|
+
code: false,
|
|
251
|
+
totalTransactions,
|
|
252
|
+
successCount: 0,
|
|
253
|
+
failedCount: totalTransactions,
|
|
254
|
+
txHashes: [],
|
|
255
|
+
results: [],
|
|
256
|
+
errorSummary: 'rpcUrl is required in config'
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const chainId = config.chainId ?? 143;
|
|
260
|
+
const chainName = config.chainName ?? 'MONAD';
|
|
261
|
+
const confirmationTimeout = config.confirmationTimeout ?? 60000; // 默认60秒超时
|
|
262
|
+
const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
|
|
263
|
+
chainId,
|
|
264
|
+
name: chainName
|
|
265
|
+
});
|
|
266
|
+
const results = [];
|
|
267
|
+
const txHashes = [];
|
|
268
|
+
const errors = [];
|
|
269
|
+
// 顺序广播并等待确认
|
|
270
|
+
for (let i = 0; i < signedTransactions.length; i++) {
|
|
271
|
+
const signedTx = signedTransactions[i];
|
|
272
|
+
try {
|
|
273
|
+
console.log(`📤 [${chainName}] 广播交易 ${i + 1}/${totalTransactions}...`);
|
|
274
|
+
// 广播交易
|
|
275
|
+
const txResponse = await provider.broadcastTransaction(signedTx);
|
|
276
|
+
console.log(`✅ [${chainName}] 交易 ${i + 1} 已广播: ${txResponse.hash}`);
|
|
277
|
+
// ✅ 等待交易确认
|
|
278
|
+
console.log(`⏳ [${chainName}] 等待交易 ${i + 1} 确认...`);
|
|
279
|
+
const receipt = await provider.waitForTransaction(txResponse.hash, 1, // 等待1个确认
|
|
280
|
+
confirmationTimeout);
|
|
281
|
+
if (receipt && receipt.status === 1) {
|
|
282
|
+
results.push({
|
|
283
|
+
index: i,
|
|
284
|
+
success: true,
|
|
285
|
+
txHash: txResponse.hash
|
|
286
|
+
});
|
|
287
|
+
txHashes.push(txResponse.hash);
|
|
288
|
+
console.log(`✅ [${chainName}] 交易 ${i + 1} 已确认: ${txResponse.hash}`);
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
const errorMsg = `交易执行失败(status=${receipt?.status})`;
|
|
292
|
+
results.push({
|
|
293
|
+
index: i,
|
|
294
|
+
success: false,
|
|
295
|
+
txHash: txResponse.hash,
|
|
296
|
+
error: errorMsg
|
|
297
|
+
});
|
|
298
|
+
errors.push(`交易 ${i + 1}: ${errorMsg}`);
|
|
299
|
+
console.error(`❌ [${chainName}] 交易 ${i + 1} 失败: ${errorMsg}`);
|
|
300
|
+
// ✅ 多跳场景:如果某笔失败,后续交易可能也会失败,继续尝试但标记
|
|
301
|
+
console.warn(`⚠️ [${chainName}] 交易 ${i + 1} 失败,继续尝试后续交易...`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
const errorMessage = error?.message || String(error);
|
|
306
|
+
results.push({
|
|
307
|
+
index: i,
|
|
308
|
+
success: false,
|
|
309
|
+
error: errorMessage
|
|
310
|
+
});
|
|
311
|
+
errors.push(`交易 ${i + 1}: ${errorMessage}`);
|
|
312
|
+
console.error(`❌ [${chainName}] 交易 ${i + 1}/${totalTransactions} 失败:`, errorMessage);
|
|
313
|
+
// ✅ 多跳场景:如果某笔失败,后续交易可能也会失败,继续尝试
|
|
314
|
+
console.warn(`⚠️ [${chainName}] 继续尝试后续交易...`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
const successCount = txHashes.length;
|
|
318
|
+
const failedCount = totalTransactions - successCount;
|
|
319
|
+
console.log(`📊 [${chainName}] 顺序广播完成: ${successCount}/${totalTransactions} 成功`);
|
|
320
|
+
return {
|
|
321
|
+
code: successCount > 0,
|
|
322
|
+
totalTransactions,
|
|
323
|
+
successCount,
|
|
324
|
+
failedCount,
|
|
325
|
+
txHashes,
|
|
326
|
+
results,
|
|
327
|
+
errorSummary: errors.length > 0 ? errors.join('; ') : undefined
|
|
328
|
+
};
|
|
329
|
+
}
|
|
226
330
|
/**
|
|
227
331
|
* 并行逐笔广播到 RPC(速度更快,但可能有 nonce 冲突)
|
|
228
332
|
*
|
|
@@ -86,8 +86,20 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
86
86
|
const extractProfit = shouldExtractProfit(config);
|
|
87
87
|
const { fundsList, originalAmounts, totalBuyAmount, totalProfit } = analyzeBuyFunds(buyAmounts, config, extractProfit);
|
|
88
88
|
const maxFundsIndex = findMaxIndex(originalAmounts);
|
|
89
|
-
const unsignedBuys = await populateBuyTransactions(buyers, portalAddr, tokenAddress, fundsList);
|
|
90
89
|
const gasLimits = buildGasLimitList(buyers.length, config);
|
|
90
|
+
// ✅ 支持 quoteToken:如果传入了 quoteToken 且非零地址,则使用它
|
|
91
|
+
const inputToken = params.quoteToken && params.quoteToken !== ZERO_ADDRESS ? params.quoteToken : ZERO_ADDRESS;
|
|
92
|
+
const useNativeToken = inputToken === ZERO_ADDRESS;
|
|
93
|
+
// ✅ 如果使用非原生代币(如 USDC),需要根据精度转换金额
|
|
94
|
+
let adjustedFundsList = fundsList;
|
|
95
|
+
if (!useNativeToken && params.quoteTokenDecimals !== undefined && params.quoteTokenDecimals !== 18) {
|
|
96
|
+
const decimalsDiff = 18 - params.quoteTokenDecimals;
|
|
97
|
+
const divisor = BigInt(10 ** decimalsDiff);
|
|
98
|
+
adjustedFundsList = fundsList.map(amount => amount / divisor);
|
|
99
|
+
console.log('🔍 createToken SDK 精度转换: 18 -> ', params.quoteTokenDecimals, ', 原始:', fundsList, ', 转换后:', adjustedFundsList);
|
|
100
|
+
}
|
|
101
|
+
console.log('🔍 createToken SDK - quoteToken:', params.quoteToken, 'inputToken:', inputToken, 'useNativeToken:', useNativeToken);
|
|
102
|
+
const unsignedBuys = await populateBuyTransactionsWithQuote(buyers, portalAddr, tokenAddress, adjustedFundsList, inputToken, useNativeToken);
|
|
91
103
|
const buyerNonces = await allocateBuyerNonces(buyers, extractProfit, maxFundsIndex, totalProfit, nonceManager);
|
|
92
104
|
const signedBuys = await signBuyTransactions({
|
|
93
105
|
unsignedBuys,
|
|
@@ -97,7 +109,8 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
97
109
|
gasPrice,
|
|
98
110
|
chainId,
|
|
99
111
|
config,
|
|
100
|
-
fundsList
|
|
112
|
+
fundsList: adjustedFundsList, // ✅ 使用调整后的金额
|
|
113
|
+
useNativeToken // ✅ 传递是否使用原生代币
|
|
101
114
|
});
|
|
102
115
|
signedTxs.push(...signedBuys);
|
|
103
116
|
await appendProfitTransaction({
|
|
@@ -344,7 +357,8 @@ async function allocateBuyerNonces(buyers, extractProfit, maxIndex, totalProfit,
|
|
|
344
357
|
}
|
|
345
358
|
return nonces;
|
|
346
359
|
}
|
|
347
|
-
async function signBuyTransactions({ unsignedBuys, buyers, nonces, gasLimits, gasPrice, chainId, config, fundsList
|
|
360
|
+
async function signBuyTransactions({ unsignedBuys, buyers, nonces, gasLimits, gasPrice, chainId, config, fundsList, useNativeToken = true // ✅ 默认使用原生代币
|
|
361
|
+
}) {
|
|
348
362
|
return await Promise.all(unsignedBuys.map((unsigned, i) => buyers[i].signTransaction({
|
|
349
363
|
...unsigned,
|
|
350
364
|
from: buyers[i].address,
|
|
@@ -353,7 +367,7 @@ async function signBuyTransactions({ unsignedBuys, buyers, nonces, gasLimits, ga
|
|
|
353
367
|
gasPrice,
|
|
354
368
|
chainId,
|
|
355
369
|
type: getTxType(config),
|
|
356
|
-
value: fundsList[i]
|
|
370
|
+
value: useNativeToken ? fundsList[i] : 0n // ✅ 非原生代币时 value 为 0
|
|
357
371
|
})));
|
|
358
372
|
}
|
|
359
373
|
async function appendProfitTransaction({ extractProfit, totalProfit, buyers, maxIndex, nonces, gasPrice, chainId, config, signedTxs }) {
|
|
@@ -89,6 +89,8 @@ export type FlapCreateWithBundleBuySignParams = {
|
|
|
89
89
|
meta: string;
|
|
90
90
|
};
|
|
91
91
|
quoteToken?: string;
|
|
92
|
+
/** ✅ 报价代币精度(如 USDC 为 6),不传默认 18 */
|
|
93
|
+
quoteTokenDecimals?: number;
|
|
92
94
|
tokenAddress: string;
|
|
93
95
|
minOutputAmounts?: (string | bigint)[];
|
|
94
96
|
config: FlapSignConfig;
|
package/dist/index.d.ts
CHANGED
|
@@ -42,4 +42,5 @@ export { fourBundleBuyFirstMerkle, type FourBuyFirstConfig, type FourBundleBuyFi
|
|
|
42
42
|
export { flapBundleBuyFirstMerkle, type FlapBuyFirstSignConfig, type FlapBuyFirstConfig, type FlapBundleBuyFirstSignParams, type FlapBundleBuyFirstParams, type FlapBuyFirstResult } from './flap/portal-bundle-merkle/swap-buy-first.js';
|
|
43
43
|
export { pancakeBundleBuyFirstMerkle, type PancakeBuyFirstSignConfig, type PancakeBuyFirstConfig, type PancakeBundleBuyFirstSignParams, type PancakeBundleBuyFirstParams, type PancakeBuyFirstResult } from './pancake/bundle-buy-first.js';
|
|
44
44
|
export { PROFIT_CONFIG } from './utils/constants.js';
|
|
45
|
-
export { submitDirectToRpc,
|
|
45
|
+
export { submitDirectToRpc, submitDirectToRpcSequential, // ✅ 新增:顺序广播并等待确认(用于多跳)
|
|
46
|
+
submitDirectToRpcParallel, type DirectSubmitConfig, type DirectSubmitResult, type DirectTxResult } from './contracts/tm-bundle-merkle/submit.js';
|
package/dist/index.js
CHANGED
|
@@ -63,4 +63,5 @@ export { pancakeBundleBuyFirstMerkle } from './pancake/bundle-buy-first.js';
|
|
|
63
63
|
// ✅ 硬编码利润配置(统一管理)
|
|
64
64
|
export { PROFIT_CONFIG } from './utils/constants.js';
|
|
65
65
|
// ✅ Monad 等不支持 Bundle 的链:逐笔 RPC 广播方法(服务器端使用)
|
|
66
|
-
export { submitDirectToRpc,
|
|
66
|
+
export { submitDirectToRpc, submitDirectToRpcSequential, // ✅ 新增:顺序广播并等待确认(用于多跳)
|
|
67
|
+
submitDirectToRpcParallel } from './contracts/tm-bundle-merkle/submit.js';
|