four-flap-meme-sdk 1.6.62 → 1.6.64
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.
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { ethers } from 'ethers';
|
|
16
16
|
import { createAAAccountManager, encodeExecute, createWallet } from './aa-account.js';
|
|
17
|
-
import { encodeBuyCall, encodeSellCall } from './portal-ops.js';
|
|
17
|
+
import { encodeBuyCall, encodeSellCall, PortalQuery, lpFeeProfileToV3Fee } from './portal-ops.js';
|
|
18
18
|
import { encodeSwapExactETHForTokensSupportingFee, encodeSwapExactTokensForETHSupportingFee, encodeSwapExactETHForTokensV3, encodeSwapExactTokensForETHV3, } from './dex.js';
|
|
19
19
|
import { encodeApproveCall } from './portal-ops.js';
|
|
20
20
|
import { FLAP_PORTAL, WOKB, XLAYER_CHAIN_ID, DEFAULT_RPC_URL, ENTRYPOINT_V06, SIMPLE_ACCOUNT_FACTORY, PARTICLE_BUNDLER_URL, } from './constants.js';
|
|
@@ -71,7 +71,6 @@ function normalizeConfig(cfg) {
|
|
|
71
71
|
export async function buildBundleBuyOps(params) {
|
|
72
72
|
const poolType = params.poolType || 'flap';
|
|
73
73
|
const wokb = params.wrappedOkbAddress || WOKB;
|
|
74
|
-
const v3Fee = params.v3Fee || 2500;
|
|
75
74
|
const deadline = Math.floor(Date.now() / 1000) + 60 * Math.max(1, Number(params.deadlineMinutes ?? 20));
|
|
76
75
|
const portal = FLAP_PORTAL;
|
|
77
76
|
const routerAddress = params.routerAddress || '';
|
|
@@ -85,6 +84,22 @@ export async function buildBundleBuyOps(params) {
|
|
|
85
84
|
// ✅ 归一化配置,填充默认值(与前端 normalizeXLayerAAConfig 保持一致)
|
|
86
85
|
const config = normalizeConfig(params.config);
|
|
87
86
|
const aaManager = createAAAccountManager(config);
|
|
87
|
+
// ✅ V3 模式:直接从链上读取 lpFeeProfile 获取正确的 fee(与 bundleGraduateBuy 保持一致)
|
|
88
|
+
let v3Fee = params.v3Fee || 2500;
|
|
89
|
+
if (poolType === 'v3') {
|
|
90
|
+
try {
|
|
91
|
+
const portalQuery = new PortalQuery({ rpcUrl: config.rpcUrl, chainId: config.chainId });
|
|
92
|
+
const tokenState = await portalQuery.getTokenV7(params.tokenAddress);
|
|
93
|
+
const correctV3Fee = lpFeeProfileToV3Fee(tokenState.lpFeeProfile);
|
|
94
|
+
if (correctV3Fee !== v3Fee) {
|
|
95
|
+
console.log(`[buildBundleBuyOps] V3 Fee 校正: 前端传入 ${v3Fee}, 链上 lpFeeProfile=${tokenState.lpFeeProfile} → 正确 fee=${correctV3Fee}`);
|
|
96
|
+
}
|
|
97
|
+
v3Fee = correctV3Fee;
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
console.warn(`[buildBundleBuyOps] 读取 lpFeeProfile 失败,使用前端传入的 v3Fee=${v3Fee}:`, e);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
88
103
|
const ownerWallets = params.ownerPrivateKeys.map(pk => createWallet(pk, config));
|
|
89
104
|
const owners = ownerWallets.map(w => w.address);
|
|
90
105
|
const accounts = await aaManager.getMultipleAccountInfo(owners);
|
|
@@ -223,7 +238,6 @@ export async function buildBundleBuyOps(params) {
|
|
|
223
238
|
export async function buildBundleSellOps(params) {
|
|
224
239
|
const poolType = params.poolType || 'flap';
|
|
225
240
|
const wokb = params.wrappedOkbAddress || WOKB;
|
|
226
|
-
const v3Fee = params.v3Fee || 2500;
|
|
227
241
|
const deadline = Math.floor(Date.now() / 1000) + 60 * Math.max(1, Number(params.deadlineMinutes ?? 20));
|
|
228
242
|
const portal = FLAP_PORTAL;
|
|
229
243
|
const routerAddress = params.routerAddress || '';
|
|
@@ -238,6 +252,22 @@ export async function buildBundleSellOps(params) {
|
|
|
238
252
|
// ✅ 归一化配置,填充默认值(与前端 normalizeXLayerAAConfig 保持一致)
|
|
239
253
|
const config = normalizeConfig(params.config);
|
|
240
254
|
const aaManager = createAAAccountManager(config);
|
|
255
|
+
// ✅ V3 模式:直接从链上读取 lpFeeProfile 获取正确的 fee(与 bundleGraduateBuy 保持一致)
|
|
256
|
+
let v3Fee = params.v3Fee || 2500;
|
|
257
|
+
if (poolType === 'v3') {
|
|
258
|
+
try {
|
|
259
|
+
const portalQuery = new PortalQuery({ rpcUrl: config.rpcUrl, chainId: config.chainId });
|
|
260
|
+
const tokenState = await portalQuery.getTokenV7(params.tokenAddress);
|
|
261
|
+
const correctV3Fee = lpFeeProfileToV3Fee(tokenState.lpFeeProfile);
|
|
262
|
+
if (correctV3Fee !== v3Fee) {
|
|
263
|
+
console.log(`[buildBundleSellOps] V3 Fee 校正: 前端传入 ${v3Fee}, 链上 lpFeeProfile=${tokenState.lpFeeProfile} → 正确 fee=${correctV3Fee}`);
|
|
264
|
+
}
|
|
265
|
+
v3Fee = correctV3Fee;
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
console.warn(`[buildBundleSellOps] 读取 lpFeeProfile 失败,使用前端传入的 v3Fee=${v3Fee}:`, e);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
241
271
|
const ownerWallets = params.ownerPrivateKeys.map(pk => createWallet(pk, config));
|
|
242
272
|
const owners = ownerWallets.map(w => w.address);
|
|
243
273
|
const accounts = await aaManager.getMultipleAccountInfo(owners);
|
|
@@ -7,9 +7,10 @@ import { POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, POTATOSWAP_V3_FACTORY, WOKB
|
|
|
7
7
|
// 多跳 prefund 估算用的 gas 常量(可配置)
|
|
8
8
|
const HOP_CALL_GAS_LIMIT = 150000n; // hop 转账操作
|
|
9
9
|
const DEX_BUY_CALL_GAS_LIMIT = 650000n; // DEX V3 买入操作
|
|
10
|
-
// ✅
|
|
11
|
-
// 预充值使用
|
|
12
|
-
|
|
10
|
+
// ✅ 余额检查 buffer 必须和预充值时使用的 buffer 一致
|
|
11
|
+
// hop-wallet-manager.ts 预充值使用 DEFAULT_BUFFER_PERCENT = 200n
|
|
12
|
+
// 这里也使用 200n,确保预充值后检查能通过
|
|
13
|
+
const PREFUND_BUFFER_PERCENT = 200n; // prefund buffer 百分比 (200 = 2.0x)
|
|
13
14
|
import { AAAccountManager, encodeExecute, encodeExecuteBatch, encodeExecuteViaMulticall3 } from './aa-account.js';
|
|
14
15
|
import { encodeApproveCall, lpFeeProfileToV3Fee, } from './portal-ops.js';
|
|
15
16
|
import { DexQuery, encodeSwapExactETHForTokensSupportingFee, encodeSwapExactTokensForETHSupportingFee, encodeSwapExactETHForTokensV3, encodeSwapExactTokensForETHV3, encodeSwapExactTokensForTokensSupportingFee, encodeSwapExactOutputForTokensV3, // ✅ 新增:精确输出买入(V3 exactOutput)
|
|
@@ -7,9 +7,10 @@ import { FLAP_PORTAL, ZERO_ADDRESS, MULTICALL3, VERIFICATION_GAS_LIMIT_DEPLOY, V
|
|
|
7
7
|
// 多跳 prefund 估算用的 gas 常量(可配置)
|
|
8
8
|
const HOP_CALL_GAS_LIMIT = 150000n; // hop 转账操作
|
|
9
9
|
const PORTAL_BUY_CALL_GAS_LIMIT = 450000n; // Portal 买入操作
|
|
10
|
-
// ✅
|
|
11
|
-
// 预充值使用
|
|
12
|
-
|
|
10
|
+
// ✅ 余额检查 buffer 必须和预充值时使用的 buffer 一致
|
|
11
|
+
// hop-wallet-manager.ts 预充值使用 DEFAULT_BUFFER_PERCENT = 200n
|
|
12
|
+
// 这里也使用 200n,确保预充值后检查能通过
|
|
13
|
+
const PREFUND_BUFFER_PERCENT = 200n; // prefund buffer 百分比 (200 = 2.0x)
|
|
13
14
|
import { AAAccountManager, encodeExecute, encodeExecuteBatch, encodeExecuteViaMulticall3 } from './aa-account.js';
|
|
14
15
|
import { encodeBuyCall, encodeSellCall, encodeBuyCallWithQuote, encodeSellCallWithQuote, encodeApproveCall, PortalQuery, parseOkb, } from './portal-ops.js';
|
|
15
16
|
import { BundleExecutor } from './bundle.js';
|
package/dist/xlayer/wash-ops.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { ethers } from 'ethers';
|
|
16
16
|
import { createAAAccountManager, encodeExecute, createWallet } from './aa-account.js';
|
|
17
|
-
import { encodeBuyCall, encodeSellCall, PortalQuery } from './portal-ops.js';
|
|
17
|
+
import { encodeBuyCall, encodeSellCall, PortalQuery, lpFeeProfileToV3Fee } from './portal-ops.js';
|
|
18
18
|
import { encodeSwapExactETHForTokensSupportingFee, encodeSwapExactTokensForETHSupportingFee, encodeSwapExactETHForTokensV3, encodeSwapExactTokensForETHV3, DexQuery, } from './dex.js';
|
|
19
19
|
import { FLAP_PORTAL, WOKB, XLAYER_CHAIN_ID, DEFAULT_RPC_URL, ENTRYPOINT_V06, SIMPLE_ACCOUNT_FACTORY, PARTICLE_BUNDLER_URL, } from './constants.js';
|
|
20
20
|
import { PROFIT_CONFIG } from '../utils/constants.js';
|
|
@@ -77,7 +77,6 @@ function normalizeConfig(cfg) {
|
|
|
77
77
|
export async function buildWashOps(params) {
|
|
78
78
|
const poolType = params.poolType || 'flap';
|
|
79
79
|
const wokb = params.wrappedOkbAddress || WOKB;
|
|
80
|
-
const v3Fee = params.v3Fee || 2500;
|
|
81
80
|
const deadline = Math.floor(Date.now() / 1000) + 60 * Math.max(1, Number(params.deadlineMinutes ?? 20));
|
|
82
81
|
const portal = FLAP_PORTAL;
|
|
83
82
|
const routerAddress = params.routerAddress || '';
|
|
@@ -88,15 +87,29 @@ export async function buildWashOps(params) {
|
|
|
88
87
|
if (poolType === 'v3' && !routerAddress) {
|
|
89
88
|
throw new Error('[buildWashOps] poolType=v3 时必须提供 routerAddress');
|
|
90
89
|
}
|
|
91
|
-
if (poolType === 'v3' && !params.v3Fee) {
|
|
92
|
-
throw new Error('[buildWashOps] poolType=v3 时必须提供 v3Fee');
|
|
93
|
-
}
|
|
94
90
|
if (params.ownerPrivateKeys.length !== params.buyAmountsOkb.length) {
|
|
95
91
|
throw new Error('[buildWashOps] 私钥数量与买入金额数量不一致');
|
|
96
92
|
}
|
|
97
93
|
// ✅ 归一化配置,填充默认值(与前端 normalizeXLayerAAConfig 保持一致)
|
|
98
94
|
const config = normalizeConfig(params.config);
|
|
99
95
|
const aaManager = createAAAccountManager(config);
|
|
96
|
+
// ✅ V3 模式:直接从链上读取 lpFeeProfile 获取正确的 fee(与 bundleGraduateBuy 保持一致)
|
|
97
|
+
// 不再依赖前端传入的 v3Fee 参数,避免前端传入错误值导致交易失败
|
|
98
|
+
let v3Fee = params.v3Fee || 2500;
|
|
99
|
+
if (poolType === 'v3') {
|
|
100
|
+
try {
|
|
101
|
+
const portalQuery = new PortalQuery({ rpcUrl: config.rpcUrl, chainId: config.chainId });
|
|
102
|
+
const tokenState = await portalQuery.getTokenV7(params.tokenAddress);
|
|
103
|
+
const correctV3Fee = lpFeeProfileToV3Fee(tokenState.lpFeeProfile);
|
|
104
|
+
if (correctV3Fee !== v3Fee) {
|
|
105
|
+
console.log(`[buildWashOps] V3 Fee 校正: 前端传入 ${v3Fee}, 链上 lpFeeProfile=${tokenState.lpFeeProfile} → 正确 fee=${correctV3Fee}`);
|
|
106
|
+
}
|
|
107
|
+
v3Fee = correctV3Fee;
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
console.warn(`[buildWashOps] 读取 lpFeeProfile 失败,使用前端传入的 v3Fee=${v3Fee}:`, e);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
100
113
|
// ✅ 预先过滤无效私钥并保持索引对应
|
|
101
114
|
const validEntries = [];
|
|
102
115
|
for (let i = 0; i < params.ownerPrivateKeys.length; i++) {
|