four-flap-meme-sdk 1.6.99 → 1.7.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.
|
@@ -79,6 +79,8 @@ export interface XLayerCrossSwapParams {
|
|
|
79
79
|
quoteTokenDecimals?: number;
|
|
80
80
|
buyersPerSell?: number;
|
|
81
81
|
disperseHopCount?: number;
|
|
82
|
+
/** ✅ 预获取的 nonce(地址 -> nonce),避免 nonce 不同步 */
|
|
83
|
+
startNonces?: Map<string, number>;
|
|
82
84
|
}
|
|
83
85
|
export interface XLayerCrossSwapResult {
|
|
84
86
|
signedTransactions: string[];
|
|
@@ -9,16 +9,19 @@
|
|
|
9
9
|
import { ethers, Contract, Wallet } from 'ethers';
|
|
10
10
|
import { calculateSellAmount } from '../utils/swap-helpers.js';
|
|
11
11
|
import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../utils/bundle-helpers.js';
|
|
12
|
-
import {
|
|
12
|
+
import { PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../utils/constants.js';
|
|
13
13
|
import { quoteV2, quoteV3 } from '../utils/quote-helpers.js';
|
|
14
14
|
import { V2_ROUTER_ABI, V3_ROUTER02_ABI } from '../abis/common.js';
|
|
15
15
|
import { generateWallets } from '../utils/wallet.js';
|
|
16
|
+
// ✅ 从 XLayer 常量导入正确的路由地址
|
|
17
|
+
import { POTATOSWAP_V2_ROUTER, POTATOSWAP_SWAP_ROUTER02, WOKB as WOKB_CONST } from './constants.js';
|
|
16
18
|
// ==================== XLayer 专用常量 ====================
|
|
17
19
|
const XLAYER_CHAIN_ID = 196;
|
|
18
20
|
const XLAYER_CHAIN_NAME = 'XLAYER';
|
|
19
|
-
const WOKB_ADDRESS =
|
|
20
|
-
|
|
21
|
-
const
|
|
21
|
+
const WOKB_ADDRESS = ethers.getAddress(WOKB_CONST);
|
|
22
|
+
// ✅ 强制校验和,避免大小写错误导致的 bad address checksum
|
|
23
|
+
const POTATO_V2_ROUTER = ethers.getAddress(POTATOSWAP_V2_ROUTER);
|
|
24
|
+
const POTATO_V3_ROUTER = ethers.getAddress(POTATOSWAP_SWAP_ROUTER02); // ✅ SwapRouter02 用于 V3 交易
|
|
22
25
|
const NATIVE_TRANSFER_GAS_LIMIT = 21055n;
|
|
23
26
|
const ERC20_TRANSFER_GAS_LIMIT = 65000n;
|
|
24
27
|
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
@@ -87,6 +90,17 @@ async function quoteSellOutput(provider, routeParams, sellAmountWei) {
|
|
|
87
90
|
console.log(`[XLayer quoteSellOutput] V3 报价成功: ${ethers.formatEther(result.amountOut)} OKB`);
|
|
88
91
|
return result.amountOut;
|
|
89
92
|
}
|
|
93
|
+
// ❗️兜底:如果 V3 报价失败且提供了 v2Path,则尝试 V2 报价(避免因为无对应费率池导致失败)
|
|
94
|
+
if (params.v2Path && params.v2Path.length >= 2) {
|
|
95
|
+
console.warn('[XLayer quoteSellOutput] V3 报价失败,尝试 V2 兜底');
|
|
96
|
+
const tokenIn = params.v2Path[0];
|
|
97
|
+
const tokenOut = params.v2Path[params.v2Path.length - 1];
|
|
98
|
+
const v2Result = await quoteV2(provider, tokenIn, tokenOut, sellAmountWei, XLAYER_CHAIN_NAME);
|
|
99
|
+
if (v2Result.amountOut > 0n) {
|
|
100
|
+
console.log(`[XLayer quoteSellOutput] V2 兜底报价成功: ${ethers.formatEther(v2Result.amountOut)} OKB`);
|
|
101
|
+
return v2Result.amountOut;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
90
104
|
throw new Error(`V3 单跳报价失败: tokenIn=${params.v3TokenIn}, tokenOut=${params.v3TokenOut}, fee=${params.v3Fee}`);
|
|
91
105
|
}
|
|
92
106
|
if (routeParams.routeType === 'v3-multi') {
|
|
@@ -97,6 +111,17 @@ async function quoteSellOutput(provider, routeParams, sellAmountWei) {
|
|
|
97
111
|
console.log(`[XLayer quoteSellOutput] V3 多跳报价成功: ${ethers.formatEther(result.amountOut)} OKB`);
|
|
98
112
|
return result.amountOut;
|
|
99
113
|
}
|
|
114
|
+
// ❗️兜底:如果 V3 多跳失败且提供 v2Path,则尝试 V2 报价
|
|
115
|
+
if (params.v2Path && params.v2Path.length >= 2) {
|
|
116
|
+
console.warn('[XLayer quoteSellOutput] V3 多跳报价失败,尝试 V2 兜底');
|
|
117
|
+
const tokenInV2 = params.v2Path[0];
|
|
118
|
+
const tokenOutV2 = params.v2Path[params.v2Path.length - 1];
|
|
119
|
+
const v2Result = await quoteV2(provider, tokenInV2, tokenOutV2, sellAmountWei, XLAYER_CHAIN_NAME);
|
|
120
|
+
if (v2Result.amountOut > 0n) {
|
|
121
|
+
console.log(`[XLayer quoteSellOutput] V2 多跳兜底成功: ${ethers.formatEther(v2Result.amountOut)} OKB`);
|
|
122
|
+
return v2Result.amountOut;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
100
125
|
throw new Error(`V3 多跳报价失败`);
|
|
101
126
|
}
|
|
102
127
|
throw new Error(`不支持的路由类型: ${routeParams.routeType}`);
|
|
@@ -458,7 +483,7 @@ export async function xlayerQuickBatchSwapMerkle(params) {
|
|
|
458
483
|
}
|
|
459
484
|
// ==================== XLayer 交叉换手 ====================
|
|
460
485
|
export async function xlayerCrossSwapMerkle(params) {
|
|
461
|
-
const { sellerPrivateKeys, sellAmounts, buyerPrivateKeys, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, buyersPerSell, disperseHopCount = 0 } = params;
|
|
486
|
+
const { sellerPrivateKeys, sellAmounts, buyerPrivateKeys, tokenAddress, routeParams, config, quoteToken, quoteTokenDecimals = 18, buyersPerSell, disperseHopCount = 0, startNonces: inputNonces } = params;
|
|
462
487
|
if (sellerPrivateKeys.length === 0)
|
|
463
488
|
throw new Error('至少需要一个卖方');
|
|
464
489
|
if (sellerPrivateKeys.length !== sellAmounts.length)
|
|
@@ -469,16 +494,28 @@ export async function xlayerCrossSwapMerkle(params) {
|
|
|
469
494
|
const nonceManager = new NonceManager(context.provider);
|
|
470
495
|
const allSellerWallets = sellerPrivateKeys.map(pk => new Wallet(pk, context.provider));
|
|
471
496
|
const allBuyerWallets = buyerPrivateKeys.map(pk => new Wallet(pk, context.provider));
|
|
472
|
-
//
|
|
497
|
+
// ✅ 优先使用前端传入的 nonce,避免 nonce 不同步
|
|
473
498
|
const addressToNonce = new Map();
|
|
474
499
|
for (const wallet of allSellerWallets) {
|
|
475
500
|
if (!addressToNonce.has(wallet.address)) {
|
|
476
|
-
|
|
501
|
+
const inputNonce = inputNonces?.get(wallet.address.toLowerCase()) ?? inputNonces?.get(wallet.address);
|
|
502
|
+
if (inputNonce !== undefined) {
|
|
503
|
+
addressToNonce.set(wallet.address, inputNonce);
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
addressToNonce.set(wallet.address, await nonceManager.getNextNonce(wallet));
|
|
507
|
+
}
|
|
477
508
|
}
|
|
478
509
|
}
|
|
479
510
|
for (const wallet of allBuyerWallets) {
|
|
480
511
|
if (!addressToNonce.has(wallet.address)) {
|
|
481
|
-
|
|
512
|
+
const inputNonce = inputNonces?.get(wallet.address.toLowerCase()) ?? inputNonces?.get(wallet.address);
|
|
513
|
+
if (inputNonce !== undefined) {
|
|
514
|
+
addressToNonce.set(wallet.address, inputNonce);
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
addressToNonce.set(wallet.address, await nonceManager.getNextNonce(wallet));
|
|
518
|
+
}
|
|
482
519
|
}
|
|
483
520
|
}
|
|
484
521
|
console.log(`[xlayerCrossSwapMerkle] 初始化: ${sellerPrivateKeys.length} 卖方, ${buyerPrivateKeys.length} 买方`);
|