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
- // ✅ 增加余额检查 buffer 180% 到 250%,确保 gasPrice 波动时也有足够余额
11
- // 预充值使用 200% buffer,这里使用 250% 作为安全阈值(覆盖更大的 gasPrice 波动)
12
- const PREFUND_BUFFER_PERCENT = 250n; // prefund buffer 百分比 (250 = 2.5x)
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
- // ✅ 增加余额检查 buffer 180% 到 250%,确保 gasPrice 波动时也有足够余额
11
- // 预充值使用 200% buffer,这里使用 250% 作为安全阈值(覆盖更大的 gasPrice 波动)
12
- const PREFUND_BUFFER_PERCENT = 250n; // prefund buffer 百分比 (250 = 2.5x)
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';
@@ -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++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.6.62",
3
+ "version": "1.6.64",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",