four-flap-meme-sdk 1.7.47 → 1.7.49
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.
|
@@ -165,27 +165,29 @@ function buildSellAndTransferCall(sellerWallet, sellAmount, tokenAddress, recipi
|
|
|
165
165
|
// ========================================
|
|
166
166
|
// 构建买入调用
|
|
167
167
|
// ========================================
|
|
168
|
-
function buildBuyCall(buyerWallet, tokenAddress, tradeType, routerAddress, fee
|
|
168
|
+
function buildBuyCall(buyerWallet, tokenAddress, tradeType, routerAddress, fee, buyAmount // ✅ 新增:买入金额(防止使用全部余额导致问题)
|
|
169
|
+
) {
|
|
169
170
|
const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
|
|
170
171
|
const portalInterface = new ethers.Interface(FLAP_PORTAL_ABI);
|
|
171
172
|
switch (tradeType) {
|
|
172
173
|
case 'FLAP': {
|
|
173
|
-
// FLAP:
|
|
174
|
-
const
|
|
174
|
+
// ✅ FLAP: 使用 executeBatch 调用 Portal 买入(指定金额)
|
|
175
|
+
const portalCallData = portalInterface.encodeFunctionData('buy', [tokenAddress]);
|
|
176
|
+
const batchCalls = [{ target: FLAP_PORTAL_ADDRESS, value: buyAmount, data: portalCallData }];
|
|
175
177
|
return {
|
|
176
|
-
target:
|
|
178
|
+
target: buyerWallet.address,
|
|
177
179
|
allowFailure: false,
|
|
178
|
-
value: 0n,
|
|
179
|
-
callData,
|
|
180
|
+
value: 0n,
|
|
181
|
+
callData: delegateInterface.encodeFunctionData('executeBatch', [batchCalls]),
|
|
180
182
|
};
|
|
181
183
|
}
|
|
182
184
|
case 'V2': {
|
|
183
|
-
// V2: 使用 executeBuyV2
|
|
185
|
+
// ✅ V2: 使用 executeBuyV2,传入指定金额
|
|
184
186
|
const path = [WOKB_ADDRESS, tokenAddress];
|
|
185
187
|
const callData = delegateInterface.encodeFunctionData('executeBuyV2', [
|
|
186
188
|
routerAddress,
|
|
187
189
|
path,
|
|
188
|
-
|
|
190
|
+
buyAmount, // ✅ 使用指定金额,不是 0
|
|
189
191
|
]);
|
|
190
192
|
return {
|
|
191
193
|
target: buyerWallet.address,
|
|
@@ -195,13 +197,13 @@ function buildBuyCall(buyerWallet, tokenAddress, tradeType, routerAddress, fee)
|
|
|
195
197
|
};
|
|
196
198
|
}
|
|
197
199
|
case 'V3': {
|
|
198
|
-
// V3: 使用 executeBuy
|
|
200
|
+
// ✅ V3: 使用 executeBuy,传入指定金额
|
|
199
201
|
const callData = delegateInterface.encodeFunctionData('executeBuy', [
|
|
200
202
|
routerAddress,
|
|
201
203
|
WOKB_ADDRESS,
|
|
202
204
|
tokenAddress,
|
|
203
205
|
fee,
|
|
204
|
-
|
|
206
|
+
buyAmount, // ✅ 使用指定金额,不是 0
|
|
205
207
|
]);
|
|
206
208
|
return {
|
|
207
209
|
target: buyerWallet.address,
|
|
@@ -215,7 +217,8 @@ function buildBuyCall(buyerWallet, tokenAddress, tradeType, routerAddress, fee)
|
|
|
215
217
|
/**
|
|
216
218
|
* 构建捆绑换手交易
|
|
217
219
|
*/
|
|
218
|
-
async function buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmount,
|
|
220
|
+
async function buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmount, buyAmount, // ✅ 新增:买入金额(防止使用全部余额)
|
|
221
|
+
tokenAddress, tradeType, routerAddress, fee) {
|
|
219
222
|
const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
|
|
220
223
|
const calls = [];
|
|
221
224
|
// 第一步:卖家卖币并转账给第一个中间钱包
|
|
@@ -243,8 +246,8 @@ async function buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmount,
|
|
|
243
246
|
callData: transferData,
|
|
244
247
|
});
|
|
245
248
|
}
|
|
246
|
-
//
|
|
247
|
-
const buyCall = buildBuyCall(buyerWallet, tokenAddress, tradeType, routerAddress, fee);
|
|
249
|
+
// ✅ 最后一步:买家买币(使用指定金额)
|
|
250
|
+
const buyCall = buildBuyCall(buyerWallet, tokenAddress, tradeType, routerAddress, fee, buyAmount);
|
|
248
251
|
calls.push(buyCall);
|
|
249
252
|
return calls;
|
|
250
253
|
}
|
|
@@ -320,7 +323,11 @@ export async function bundleSwap(params) {
|
|
|
320
323
|
// ========================================
|
|
321
324
|
// 同步构建调用
|
|
322
325
|
// ========================================
|
|
323
|
-
|
|
326
|
+
// ✅ 计算买入金额:卖出所得 OKB 扣除利润
|
|
327
|
+
const buyAmount = estimatedOkbOut - profitAmount;
|
|
328
|
+
console.log(`[Bundle Swap] 买入金额: ${ethers.formatEther(buyAmount)} OKB`);
|
|
329
|
+
const swapCalls = await buildSwapCalls(sellerWallet, buyerWallet, hopWallets, sellAmountWei, buyAmount, // ✅ 传入计算得到的买入金额
|
|
330
|
+
tokenAddress, tradeType, actualRouter, fee);
|
|
324
331
|
// ✅ 构建完整调用列表(利润刮取 + 换手调用)
|
|
325
332
|
const calls = [];
|
|
326
333
|
// 利润刮取(从卖家钱包)
|
|
@@ -94,11 +94,12 @@ export async function washVolume(params) {
|
|
|
94
94
|
// 并行获取数据
|
|
95
95
|
// ========================================
|
|
96
96
|
const allAddresses = allWallets.map(w => w.address);
|
|
97
|
-
// ✅
|
|
97
|
+
// ✅ 对所有模式,使用【总金额报价 + 按比例分配】
|
|
98
98
|
// 因为所有钱包在同一笔交易中执行,会累积影响价格
|
|
99
|
+
// 这确保了「买多少就卖多少」,避免清空钱包预存代币
|
|
99
100
|
let estimatedTokenAmounts = [];
|
|
101
|
+
const totalBuyWei = buyAmountWei * BigInt(wallets.length);
|
|
100
102
|
if (poolType === 'FLAP') {
|
|
101
|
-
const totalBuyWei = buyAmountWei * BigInt(wallets.length);
|
|
102
103
|
console.log(`[washVolume] FLAP 总金额报价: ${wallets.length} 个钱包, 每个 ${buyAmountWei} wei, 总计 ${totalBuyWei} wei`);
|
|
103
104
|
try {
|
|
104
105
|
const portalContract = new Contract(FLAP_PORTAL_ADDRESS, FLAP_PORTAL_ABI, provider);
|
|
@@ -141,7 +142,41 @@ export async function washVolume(params) {
|
|
|
141
142
|
console.log(`[washVolume] FLAP 代币分配:`, estimatedTokenAmounts.map(a => a.toString()));
|
|
142
143
|
}
|
|
143
144
|
catch (e) {
|
|
144
|
-
console.warn(`[washVolume] 报价失败:`, e);
|
|
145
|
+
console.warn(`[washVolume] FLAP 报价失败:`, e);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if (poolType === 'V2' || poolType === 'V3') {
|
|
149
|
+
// ✅ V2/V3 外盘模式:通过报价获取预估代币数量,确保买卖对等
|
|
150
|
+
console.log(`[washVolume] ${poolType} 总金额报价: ${wallets.length} 个钱包, 每个 ${buyAmountWei} wei, 总计 ${totalBuyWei} wei`);
|
|
151
|
+
try {
|
|
152
|
+
const { quoteV2, quoteV3 } = await import('../../utils/quote-helpers.js');
|
|
153
|
+
let totalTokenAmount = 0n;
|
|
154
|
+
if (poolType === 'V3') {
|
|
155
|
+
const result = await quoteV3(provider, WOKB_ADDRESS, tokenAddress, totalBuyWei, 'XLAYER', fee);
|
|
156
|
+
totalTokenAmount = result.amountOut;
|
|
157
|
+
console.log(`[washVolume] V3 报价成功: ${totalBuyWei} wei OKB -> ${totalTokenAmount} wei 代币 (fee: ${fee})`);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
const result = await quoteV2(provider, WOKB_ADDRESS, tokenAddress, totalBuyWei, 'XLAYER');
|
|
161
|
+
totalTokenAmount = result.amountOut;
|
|
162
|
+
console.log(`[washVolume] V2 报价成功: ${totalBuyWei} wei OKB -> ${totalTokenAmount} wei 代币`);
|
|
163
|
+
}
|
|
164
|
+
// 均分到每个钱包
|
|
165
|
+
if (totalBuyWei > 0n && totalTokenAmount > 0n) {
|
|
166
|
+
const sharePerWallet = totalTokenAmount / BigInt(wallets.length);
|
|
167
|
+
let allocated = 0n;
|
|
168
|
+
estimatedTokenAmounts = wallets.map((_, i) => {
|
|
169
|
+
if (i === wallets.length - 1) {
|
|
170
|
+
return totalTokenAmount - allocated;
|
|
171
|
+
}
|
|
172
|
+
allocated += sharePerWallet;
|
|
173
|
+
return sharePerWallet;
|
|
174
|
+
});
|
|
175
|
+
console.log(`[washVolume] ${poolType} 代币分配:`, estimatedTokenAmounts.map(a => a.toString()));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
console.warn(`[washVolume] ${poolType} 报价失败,将使用 sellPercent 模式:`, e);
|
|
145
180
|
}
|
|
146
181
|
}
|
|
147
182
|
const [nonces, feeData] = await Promise.all([
|
|
@@ -165,9 +200,9 @@ export async function washVolume(params) {
|
|
|
165
200
|
const buyCall = buildBuyCall(wallet, buyAmountWei, tokenAddress, poolType, actualRouter, fee, delegateInterface, portalInterface);
|
|
166
201
|
calls.push(buyCall);
|
|
167
202
|
// 卖出调用(使用预估的代币数量)
|
|
168
|
-
// ✅
|
|
203
|
+
// ✅ 统一所有模式:当有预估数量时使用精确卖出,确保买卖对等
|
|
169
204
|
const estimatedAmount = estimatedTokenAmounts[i] || 0n;
|
|
170
|
-
const sellCall =
|
|
205
|
+
const sellCall = estimatedAmount > 0n
|
|
171
206
|
? buildSellCallWithAmount(wallet, estimatedAmount, tokenAddress, poolType, actualRouter, fee, delegateInterface, portalInterface)
|
|
172
207
|
: buildSellCall(wallet, tokenAddress, sellPercent, tokenDecimals, poolType, actualRouter, fee, delegateInterface, portalInterface);
|
|
173
208
|
calls.push(sellCall);
|