four-flap-meme-sdk 1.4.84 → 1.4.86
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/swap-buy-first.d.ts +2 -1
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +14 -7
- package/dist/contracts/tm-bundle-merkle/swap.d.ts +2 -0
- package/dist/contracts/tm-bundle-merkle/swap.js +16 -4
- package/dist/contracts/tm-bundle-merkle/types.d.ts +10 -0
- package/dist/contracts/tm-bundle-merkle/utils.js +24 -14
- package/dist/flap/constants.d.ts +1 -1
- package/dist/flap/constants.js +1 -1
- package/dist/flap/portal-bundle-merkle/core.js +36 -5
- package/dist/flap/portal-bundle-merkle/create-to-dex.d.ts +8 -0
- package/dist/flap/portal-bundle-merkle/create-to-dex.js +61 -13
- package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +2 -0
- package/dist/flap/portal-bundle-merkle/swap-buy-first.js +25 -9
- package/dist/flap/portal-bundle-merkle/swap.d.ts +2 -0
- package/dist/flap/portal-bundle-merkle/swap.js +21 -8
- package/dist/flap/portal-bundle-merkle/types.d.ts +4 -0
- package/dist/flap/portal.d.ts +78 -0
- package/dist/flap/portal.js +77 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pancake/bundle-buy-first.d.ts +2 -0
- package/dist/pancake/bundle-buy-first.js +37 -212
- package/dist/pancake/bundle-swap.d.ts +2 -0
- package/dist/pancake/bundle-swap.js +22 -9
- package/dist/utils/constants.d.ts +4 -2
- package/dist/utils/constants.js +4 -2
- package/dist/utils/holders-maker.js +1 -1
- package/package.json +1 -1
package/dist/flap/portal.d.ts
CHANGED
|
@@ -25,6 +25,30 @@ export declare enum MigratorType {
|
|
|
25
25
|
V3_MIGRATOR = 0,
|
|
26
26
|
V2_MIGRATOR = 1
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* V3 LP 费率档位
|
|
30
|
+
* 决定代币迁移到 Uniswap V3 或 PancakeSwap V3 时使用的费率
|
|
31
|
+
*/
|
|
32
|
+
export declare enum V3LPFeeProfile {
|
|
33
|
+
/** 标准费率: PancakeSwap 0.25%, Uniswap 0.3% */
|
|
34
|
+
LP_FEE_PROFILE_STANDARD = 0,
|
|
35
|
+
/** 低费率: PancakeSwap 0.01%, Uniswap 0.05% (BNB 链需要白名单) */
|
|
36
|
+
LP_FEE_PROFILE_LOW = 1,
|
|
37
|
+
/** 高费率: 1% (适用于特殊交易对) */
|
|
38
|
+
LP_FEE_PROFILE_HIGH = 2
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* DEX ID
|
|
42
|
+
* 决定代币迁移到哪个 DEX
|
|
43
|
+
* - BSC: DEX0 = PancakeSwap
|
|
44
|
+
* - xLayer: DEX0 = PotatoSwap
|
|
45
|
+
* - Monad: DEX0 = Uniswap, DEX1 = PancakeSwap, DEX2 = Monday
|
|
46
|
+
*/
|
|
47
|
+
export declare enum DEXId {
|
|
48
|
+
DEX0 = 0,
|
|
49
|
+
DEX1 = 1,
|
|
50
|
+
DEX2 = 2
|
|
51
|
+
}
|
|
28
52
|
export type TokenStateV2 = {
|
|
29
53
|
status: number;
|
|
30
54
|
reserve: bigint;
|
|
@@ -120,6 +144,27 @@ export type NewTokenV3Params = {
|
|
|
120
144
|
extensionID: string;
|
|
121
145
|
extensionData?: string;
|
|
122
146
|
};
|
|
147
|
+
/**
|
|
148
|
+
* newTokenV4 参数
|
|
149
|
+
* 相比 V3 新增了 DEX 选择和 LP 费率配置
|
|
150
|
+
*/
|
|
151
|
+
export type NewTokenV4Params = {
|
|
152
|
+
name: string;
|
|
153
|
+
symbol: string;
|
|
154
|
+
meta: string;
|
|
155
|
+
dexThresh: number;
|
|
156
|
+
salt: string;
|
|
157
|
+
taxRate: number;
|
|
158
|
+
migratorType: number;
|
|
159
|
+
quoteToken: string;
|
|
160
|
+
quoteAmt: bigint;
|
|
161
|
+
beneficiary: string;
|
|
162
|
+
permitData?: string;
|
|
163
|
+
extensionID: string;
|
|
164
|
+
extensionData?: string;
|
|
165
|
+
dexId: number;
|
|
166
|
+
lpFeeProfile: number;
|
|
167
|
+
};
|
|
123
168
|
export declare class FlapPortal {
|
|
124
169
|
private rpcUrl;
|
|
125
170
|
protected portal: string;
|
|
@@ -174,6 +219,39 @@ export declare class FlapPortalWriter extends FlapPortal {
|
|
|
174
219
|
newTokenV3(args: NewTokenV3Params & {
|
|
175
220
|
msgValue?: bigint;
|
|
176
221
|
}): Promise<any>;
|
|
222
|
+
/**
|
|
223
|
+
* 创建代币 V4 版本
|
|
224
|
+
* 相比 V3 新增了 DEX 选择和 LP 费率配置
|
|
225
|
+
*
|
|
226
|
+
* @param args 创建代币参数
|
|
227
|
+
* @param args.dexId DEX ID,选择迁移到哪个 DEX(使用 DEXId 枚举)
|
|
228
|
+
* @param args.lpFeeProfile LP 费率档位(使用 V3LPFeeProfile 枚举)
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```typescript
|
|
232
|
+
* await portal.newTokenV4({
|
|
233
|
+
* name: 'My Token',
|
|
234
|
+
* symbol: 'MTK',
|
|
235
|
+
* meta: 'bafkreicwlkpvrcqg4bbhyp2fnhdwbqos5ghka6gdjra3tdkgxxs74hqsze',
|
|
236
|
+
* dexThresh: DexThreshType.FOUR_FIFTHS,
|
|
237
|
+
* salt: '0x...',
|
|
238
|
+
* taxRate: 0,
|
|
239
|
+
* migratorType: MigratorType.V3_MIGRATOR,
|
|
240
|
+
* quoteToken: '0x0000000000000000000000000000000000000000',
|
|
241
|
+
* quoteAmt: 0n,
|
|
242
|
+
* beneficiary: '0x...',
|
|
243
|
+
* extensionID: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
244
|
+
* dexId: DEXId.DEX0,
|
|
245
|
+
* lpFeeProfile: V3LPFeeProfile.LP_FEE_PROFILE_STANDARD,
|
|
246
|
+
* msgValue: parseEther('0.01'),
|
|
247
|
+
* });
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @note BNB 链上使用 LP_FEE_PROFILE_LOW (0.01%) 需要白名单地址
|
|
251
|
+
*/
|
|
252
|
+
newTokenV4(args: NewTokenV4Params & {
|
|
253
|
+
msgValue?: bigint;
|
|
254
|
+
}): Promise<any>;
|
|
177
255
|
claim(token: string): Promise<{
|
|
178
256
|
txHash: string;
|
|
179
257
|
tokenAmount: bigint;
|
package/dist/flap/portal.js
CHANGED
|
@@ -31,6 +31,32 @@ export var MigratorType;
|
|
|
31
31
|
MigratorType[MigratorType["V3_MIGRATOR"] = 0] = "V3_MIGRATOR";
|
|
32
32
|
MigratorType[MigratorType["V2_MIGRATOR"] = 1] = "V2_MIGRATOR";
|
|
33
33
|
})(MigratorType || (MigratorType = {}));
|
|
34
|
+
/**
|
|
35
|
+
* V3 LP 费率档位
|
|
36
|
+
* 决定代币迁移到 Uniswap V3 或 PancakeSwap V3 时使用的费率
|
|
37
|
+
*/
|
|
38
|
+
export var V3LPFeeProfile;
|
|
39
|
+
(function (V3LPFeeProfile) {
|
|
40
|
+
/** 标准费率: PancakeSwap 0.25%, Uniswap 0.3% */
|
|
41
|
+
V3LPFeeProfile[V3LPFeeProfile["LP_FEE_PROFILE_STANDARD"] = 0] = "LP_FEE_PROFILE_STANDARD";
|
|
42
|
+
/** 低费率: PancakeSwap 0.01%, Uniswap 0.05% (BNB 链需要白名单) */
|
|
43
|
+
V3LPFeeProfile[V3LPFeeProfile["LP_FEE_PROFILE_LOW"] = 1] = "LP_FEE_PROFILE_LOW";
|
|
44
|
+
/** 高费率: 1% (适用于特殊交易对) */
|
|
45
|
+
V3LPFeeProfile[V3LPFeeProfile["LP_FEE_PROFILE_HIGH"] = 2] = "LP_FEE_PROFILE_HIGH";
|
|
46
|
+
})(V3LPFeeProfile || (V3LPFeeProfile = {}));
|
|
47
|
+
/**
|
|
48
|
+
* DEX ID
|
|
49
|
+
* 决定代币迁移到哪个 DEX
|
|
50
|
+
* - BSC: DEX0 = PancakeSwap
|
|
51
|
+
* - xLayer: DEX0 = PotatoSwap
|
|
52
|
+
* - Monad: DEX0 = Uniswap, DEX1 = PancakeSwap, DEX2 = Monday
|
|
53
|
+
*/
|
|
54
|
+
export var DEXId;
|
|
55
|
+
(function (DEXId) {
|
|
56
|
+
DEXId[DEXId["DEX0"] = 0] = "DEX0";
|
|
57
|
+
DEXId[DEXId["DEX1"] = 1] = "DEX1";
|
|
58
|
+
DEXId[DEXId["DEX2"] = 2] = "DEX2";
|
|
59
|
+
})(DEXId || (DEXId = {}));
|
|
34
60
|
// Portal ABI (使用 ethers 标准格式)
|
|
35
61
|
const PORTAL_ABI = [
|
|
36
62
|
// Token 状态查询
|
|
@@ -52,6 +78,7 @@ const PORTAL_ABI = [
|
|
|
52
78
|
// 创建代币
|
|
53
79
|
'function newTokenV2((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint16 taxRate,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData)) external payable returns (address)',
|
|
54
80
|
'function newTokenV3((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint16 taxRate,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData,bytes32 extensionID,bytes extensionData)) external payable returns (address)',
|
|
81
|
+
'function newTokenV4((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint16 taxRate,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData,bytes32 extensionID,bytes extensionData,uint8 dexId,uint8 lpFeeProfile)) external payable returns (address)',
|
|
55
82
|
// 受益人领取
|
|
56
83
|
'function claim(address token) external returns (uint256,uint256)',
|
|
57
84
|
'function delegateClaim(address token) external returns (uint256,uint256)',
|
|
@@ -315,6 +342,56 @@ export class FlapPortalWriter extends FlapPortal {
|
|
|
315
342
|
}, { value: args.msgValue });
|
|
316
343
|
return await tx.wait();
|
|
317
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* 创建代币 V4 版本
|
|
347
|
+
* 相比 V3 新增了 DEX 选择和 LP 费率配置
|
|
348
|
+
*
|
|
349
|
+
* @param args 创建代币参数
|
|
350
|
+
* @param args.dexId DEX ID,选择迁移到哪个 DEX(使用 DEXId 枚举)
|
|
351
|
+
* @param args.lpFeeProfile LP 费率档位(使用 V3LPFeeProfile 枚举)
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```typescript
|
|
355
|
+
* await portal.newTokenV4({
|
|
356
|
+
* name: 'My Token',
|
|
357
|
+
* symbol: 'MTK',
|
|
358
|
+
* meta: 'bafkreicwlkpvrcqg4bbhyp2fnhdwbqos5ghka6gdjra3tdkgxxs74hqsze',
|
|
359
|
+
* dexThresh: DexThreshType.FOUR_FIFTHS,
|
|
360
|
+
* salt: '0x...',
|
|
361
|
+
* taxRate: 0,
|
|
362
|
+
* migratorType: MigratorType.V3_MIGRATOR,
|
|
363
|
+
* quoteToken: '0x0000000000000000000000000000000000000000',
|
|
364
|
+
* quoteAmt: 0n,
|
|
365
|
+
* beneficiary: '0x...',
|
|
366
|
+
* extensionID: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
367
|
+
* dexId: DEXId.DEX0,
|
|
368
|
+
* lpFeeProfile: V3LPFeeProfile.LP_FEE_PROFILE_STANDARD,
|
|
369
|
+
* msgValue: parseEther('0.01'),
|
|
370
|
+
* });
|
|
371
|
+
* ```
|
|
372
|
+
*
|
|
373
|
+
* @note BNB 链上使用 LP_FEE_PROFILE_LOW (0.01%) 需要白名单地址
|
|
374
|
+
*/
|
|
375
|
+
async newTokenV4(args) {
|
|
376
|
+
const tx = await this.contract.newTokenV4({
|
|
377
|
+
name: args.name,
|
|
378
|
+
symbol: args.symbol,
|
|
379
|
+
meta: args.meta,
|
|
380
|
+
dexThresh: args.dexThresh,
|
|
381
|
+
salt: args.salt,
|
|
382
|
+
taxRate: args.taxRate,
|
|
383
|
+
migratorType: args.migratorType,
|
|
384
|
+
quoteToken: args.quoteToken,
|
|
385
|
+
quoteAmt: args.quoteAmt,
|
|
386
|
+
beneficiary: args.beneficiary,
|
|
387
|
+
permitData: args.permitData ?? '0x',
|
|
388
|
+
extensionID: args.extensionID,
|
|
389
|
+
extensionData: args.extensionData ?? '0x',
|
|
390
|
+
dexId: args.dexId,
|
|
391
|
+
lpFeeProfile: args.lpFeeProfile,
|
|
392
|
+
}, { value: args.msgValue });
|
|
393
|
+
return await tx.wait();
|
|
394
|
+
}
|
|
318
395
|
// 受益人领取收益
|
|
319
396
|
async claim(token) {
|
|
320
397
|
const tx = await this.contract.claim(token);
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { TM1, type FourChainV1 } from './contracts/tm1.js';
|
|
|
11
11
|
export { TM2, type FourChainV2 } from './contracts/tm2.js';
|
|
12
12
|
export { Helper3, Helper3Writer } from './contracts/helper3.js';
|
|
13
13
|
export { CDPV2 } from './flap/curve.js';
|
|
14
|
-
export { FlapPortal, FlapPortalWriter, type FlapChain, type PortalConfig, type TokenStateV2, type TokenStateV3, type TokenStateV4, type TokenStateV5, type QuoteExactInputParams, type ExactInputParams, type ExactInputV3Params, type NewTokenV3Params, TokenStatus, TokenVersion, DexThreshType, MigratorType } from './flap/portal.js';
|
|
14
|
+
export { FlapPortal, FlapPortalWriter, type FlapChain, type PortalConfig, type TokenStateV2, type TokenStateV3, type TokenStateV4, type TokenStateV5, type QuoteExactInputParams, type ExactInputParams, type ExactInputV3Params, type NewTokenV3Params, type NewTokenV4Params, TokenStatus, TokenVersion, DexThreshType, MigratorType, V3LPFeeProfile, DEXId } from './flap/portal.js';
|
|
15
15
|
export { uploadTokenMeta, type TokenMetaInput } from './flap/ipfs.js';
|
|
16
16
|
export { buildPermitPiggybackAuto } from './flap/permit.js';
|
|
17
17
|
export { predictVanityTokenAddressByChain, findSaltEndingByChain } from './flap/vanity.js';
|
package/dist/index.js
CHANGED
|
@@ -29,7 +29,7 @@ export { TM1 } from './contracts/tm1.js';
|
|
|
29
29
|
export { TM2 } from './contracts/tm2.js';
|
|
30
30
|
export { Helper3, Helper3Writer } from './contracts/helper3.js';
|
|
31
31
|
export { CDPV2 } from './flap/curve.js';
|
|
32
|
-
export { FlapPortal, FlapPortalWriter, TokenStatus, TokenVersion, DexThreshType, MigratorType } from './flap/portal.js';
|
|
32
|
+
export { FlapPortal, FlapPortalWriter, TokenStatus, TokenVersion, DexThreshType, MigratorType, V3LPFeeProfile, DEXId } from './flap/portal.js';
|
|
33
33
|
export { uploadTokenMeta } from './flap/ipfs.js';
|
|
34
34
|
export { buildPermitPiggybackAuto } from './flap/permit.js';
|
|
35
35
|
export { predictVanityTokenAddressByChain, findSaltEndingByChain } from './flap/vanity.js';
|
|
@@ -15,8 +15,10 @@ export interface PancakeBuyFirstSignConfig {
|
|
|
15
15
|
chainId?: number;
|
|
16
16
|
reserveGasBNB?: number;
|
|
17
17
|
skipQuoteOnError?: boolean;
|
|
18
|
+
userType?: UserType;
|
|
18
19
|
bribeAmount?: number;
|
|
19
20
|
}
|
|
21
|
+
export type UserType = 'v0' | 'v1';
|
|
20
22
|
export type SwapRouteType = 'v2' | 'v3-single' | 'v3-multi';
|
|
21
23
|
export interface V2RouteParams {
|
|
22
24
|
routeType: 'v2';
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { ethers, Contract, Wallet } from 'ethers';
|
|
7
7
|
import { NonceManager, getDeadline, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../utils/bundle-helpers.js';
|
|
8
8
|
import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA, ZERO_ADDRESS } from '../utils/constants.js';
|
|
9
|
-
import { quoteV2, quoteV3, getTokenToNativeQuote
|
|
9
|
+
import { quoteV2, quoteV3, getTokenToNativeQuote } from '../utils/quote-helpers.js';
|
|
10
10
|
import { V2_ROUTER_ABI, V3_ROUTER02_ABI, ERC20_BALANCE_ABI } from '../abis/common.js';
|
|
11
11
|
/**
|
|
12
12
|
* 获取 Gas Limit
|
|
@@ -52,8 +52,15 @@ const BRIBE_TX_COUNT = 1;
|
|
|
52
52
|
const PROFIT_TX_COUNT = PROFIT_HOP_COUNT + 2; // 2 + 2 = 4
|
|
53
53
|
/** 最大买卖交易数 */
|
|
54
54
|
const MAX_SWAP_TX_COUNT = MAX_BUNDLE_SIGNATURES - BRIBE_TX_COUNT - PROFIT_TX_COUNT; // 50 - 1 - 4 = 45
|
|
55
|
-
/**
|
|
56
|
-
|
|
55
|
+
/**
|
|
56
|
+
* 根据 userType 获取每笔交易的利润率
|
|
57
|
+
*/
|
|
58
|
+
function getProfitRatePerTxBps(userType) {
|
|
59
|
+
if (userType === 'v1') {
|
|
60
|
+
return PROFIT_CONFIG.RATE_BPS_V1;
|
|
61
|
+
}
|
|
62
|
+
return PROFIT_CONFIG.RATE_BPS_V0; // v0 或默认
|
|
63
|
+
}
|
|
57
64
|
/**
|
|
58
65
|
* 验证买卖笔数
|
|
59
66
|
*/
|
|
@@ -136,9 +143,9 @@ export async function pancakeBundleBuyFirstMerkle(params) {
|
|
|
136
143
|
throw new Error('单钱包模式需要提供 buyerPrivateKey 和 sellerPrivateKey');
|
|
137
144
|
}
|
|
138
145
|
validateSwapCounts(buyCount, sellCount);
|
|
139
|
-
// ✅
|
|
146
|
+
// ✅ 计算利润比例(根据 userType 动态调整)
|
|
140
147
|
const totalTxCount = buyCount + sellCount;
|
|
141
|
-
const profitRateBps =
|
|
148
|
+
const profitRateBps = getProfitRatePerTxBps(config.userType) * totalTxCount;
|
|
142
149
|
// ✅ 判断是否使用原生代币(BNB)或 ERC20 代币(如 USDT)
|
|
143
150
|
const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
|
|
144
151
|
const context = createPancakeContext(config);
|
|
@@ -173,31 +180,22 @@ export async function pancakeBundleBuyFirstMerkle(params) {
|
|
|
173
180
|
tokenAddress,
|
|
174
181
|
useNativeToken
|
|
175
182
|
});
|
|
176
|
-
const quotedNative = await quoteSellerNative({
|
|
177
|
-
provider: context.provider,
|
|
178
|
-
tokenAddress,
|
|
179
|
-
sellAmountToken: quoteResult.quotedTokenOut,
|
|
180
|
-
routeParams // ✅ 传递路由参数
|
|
181
|
-
});
|
|
182
|
-
const buyerNeed = calculateBuyerNeed({
|
|
183
|
-
quotedNative,
|
|
184
|
-
buyerBalance: buyerFundsInfo.buyerBalance,
|
|
185
|
-
reserveGas: buyerFundsInfo.reserveGas
|
|
186
|
-
});
|
|
187
183
|
const finalGasLimit = getGasLimit(config);
|
|
188
184
|
const gasPrice = await getGasPrice(context.provider, config);
|
|
189
185
|
const txType = config.txType ?? 0;
|
|
190
186
|
const nonceManager = new NonceManager(context.provider);
|
|
191
|
-
// ✅
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
187
|
+
// ✅ 直接使用买入金额作为利润基础(先买后卖模式)
|
|
188
|
+
// profitRateBps = 每笔交易利润率(bps) * 交易笔数
|
|
189
|
+
// 例如:v1用户,1买1卖 → 5 * 2 = 10 bps = 0.1%
|
|
190
|
+
const tokenProfitAmount = (buyerFundsInfo.buyerFundsWei * BigInt(profitRateBps)) / 10000n;
|
|
191
|
+
// ✅ ERC20 购买:将代币利润转换为等值 BNB(因为利润是用 BNB 转账的)
|
|
192
|
+
let profitAmount = tokenProfitAmount;
|
|
193
|
+
if (!useNativeToken && tokenProfitAmount > 0n && quoteToken) {
|
|
194
|
+
const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
|
|
195
|
+
const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
|
|
196
|
+
profitAmount = await getTokenToNativeQuote(context.provider, quoteToken, tokenProfitAmount, 'BSC', version, fee);
|
|
197
|
+
console.log(`[pancakeBundleBuyFirstMerkle] ERC20→BNB 利润转换: ${ethers.formatUnits(tokenProfitAmount, quoteTokenDecimals)} → ${ethers.formatEther(profitAmount)} BNB`);
|
|
198
|
+
}
|
|
201
199
|
// ✅ 获取贿赂金额
|
|
202
200
|
const bribeAmount = config.bribeAmount && config.bribeAmount > 0
|
|
203
201
|
? ethers.parseEther(String(config.bribeAmount))
|
|
@@ -399,100 +397,6 @@ async function quoteTokenOutput({ routeParams, buyerFundsWei, provider }) {
|
|
|
399
397
|
}
|
|
400
398
|
return { quotedTokenOut: result.amountOut };
|
|
401
399
|
}
|
|
402
|
-
/**
|
|
403
|
-
* ✅ 使用 quote-helpers 统一报价(卖出 → 原生代币)
|
|
404
|
-
*/
|
|
405
|
-
async function quoteSellerNative({ provider, tokenAddress, sellAmountToken, routeParams }) {
|
|
406
|
-
const wbnb = getWrappedNativeAddress('BSC');
|
|
407
|
-
const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
|
|
408
|
-
const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
|
|
409
|
-
return await getTokenToNativeQuote(provider, tokenAddress, sellAmountToken, 'BSC', version, fee);
|
|
410
|
-
}
|
|
411
|
-
function calculateBuyerNeed({ quotedNative, buyerBalance, reserveGas }) {
|
|
412
|
-
const estimatedBuyerNeed = quotedNative;
|
|
413
|
-
const buyerNeedTotal = estimatedBuyerNeed + reserveGas;
|
|
414
|
-
if (buyerBalance < buyerNeedTotal) {
|
|
415
|
-
throw new Error(`买方余额不足:\n - 需要: ${ethers.formatEther(buyerNeedTotal)} BNB\n - 实际: ${ethers.formatEther(buyerBalance)} BNB`);
|
|
416
|
-
}
|
|
417
|
-
const maxBuyerValue = estimatedBuyerNeed > 0n
|
|
418
|
-
? estimatedBuyerNeed
|
|
419
|
-
: buyerBalance - reserveGas;
|
|
420
|
-
return { buyerNeedTotal, maxBuyerValue };
|
|
421
|
-
}
|
|
422
|
-
async function buildRouteTransactions({ routeParams, buyerFundsWei, sellAmountToken, buyer, seller, tokenAddress, useNativeToken = true }) {
|
|
423
|
-
const deadline = getDeadline();
|
|
424
|
-
if (routeParams.routeType === 'v2') {
|
|
425
|
-
const { v2Path } = routeParams;
|
|
426
|
-
const reversePath = [...v2Path].reverse();
|
|
427
|
-
// ✅ 使用官方 V2 Router
|
|
428
|
-
const v2RouterBuyer = new Contract(PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V2_ROUTER_ABI, buyer);
|
|
429
|
-
const v2RouterSeller = new Contract(PANCAKE_V2_ROUTER_ADDRESS, PANCAKE_V2_ROUTER_ABI, seller);
|
|
430
|
-
if (useNativeToken) {
|
|
431
|
-
// ✅ BNB 池子:使用 swapExactETHForTokens / swapExactTokensForETH
|
|
432
|
-
const buyValue = buyerFundsWei + FLAT_FEE;
|
|
433
|
-
const buyUnsigned = await v2RouterBuyer.swapExactETHForTokensSupportingFeeOnTransferTokens.populateTransaction(0n, v2Path, buyer.address, deadline, { value: buyValue });
|
|
434
|
-
const sellUnsigned = await v2RouterSeller.swapExactTokensForETHSupportingFeeOnTransferTokens.populateTransaction(sellAmountToken, 0n, reversePath, seller.address, deadline);
|
|
435
|
-
return { buyUnsigned, sellUnsigned };
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
// ✅ ERC20 池子(如 USDT):使用 swapExactTokensForTokens
|
|
439
|
-
const buyUnsigned = await v2RouterBuyer.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(buyerFundsWei, 0n, v2Path, buyer.address, deadline);
|
|
440
|
-
const sellUnsigned = await v2RouterSeller.swapExactTokensForTokensSupportingFeeOnTransferTokens.populateTransaction(sellAmountToken, 0n, reversePath, seller.address, deadline);
|
|
441
|
-
return { buyUnsigned, sellUnsigned };
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
if (routeParams.routeType === 'v3-single') {
|
|
445
|
-
const { v3TokenIn, v3TokenOut, v3Fee } = routeParams;
|
|
446
|
-
const v3RouterIface = new ethers.Interface(PANCAKE_V3_ROUTER_ABI);
|
|
447
|
-
const v3RouterBuyer = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, buyer);
|
|
448
|
-
const v3RouterSeller = new Contract(PANCAKE_V3_ROUTER_ADDRESS, PANCAKE_V3_ROUTER_ABI, seller);
|
|
449
|
-
// ✅ V3 池子的处理(ERC20 模式 value = 0,因为通过代币授权支付)
|
|
450
|
-
const buyValue = useNativeToken ? buyerFundsWei + FLAT_FEE : 0n;
|
|
451
|
-
// 买入交易
|
|
452
|
-
const buySwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
|
|
453
|
-
tokenIn: v3TokenIn,
|
|
454
|
-
tokenOut: v3TokenOut,
|
|
455
|
-
fee: v3Fee,
|
|
456
|
-
recipient: buyer.address,
|
|
457
|
-
amountIn: buyerFundsWei,
|
|
458
|
-
amountOutMinimum: 0n,
|
|
459
|
-
sqrtPriceLimitX96: 0n
|
|
460
|
-
}]);
|
|
461
|
-
const buyUnsigned = await v3RouterBuyer.multicall.populateTransaction(deadline, [buySwapData], { value: buyValue });
|
|
462
|
-
// 卖出交易
|
|
463
|
-
if (useNativeToken) {
|
|
464
|
-
// ✅ BNB 池子:卖出后 unwrap WBNB 为 BNB
|
|
465
|
-
const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
|
|
466
|
-
tokenIn: v3TokenOut,
|
|
467
|
-
tokenOut: v3TokenIn,
|
|
468
|
-
fee: v3Fee,
|
|
469
|
-
recipient: PANCAKE_V3_ROUTER_ADDRESS,
|
|
470
|
-
amountIn: sellAmountToken,
|
|
471
|
-
amountOutMinimum: 0n,
|
|
472
|
-
sqrtPriceLimitX96: 0n
|
|
473
|
-
}]);
|
|
474
|
-
const sellUnwrapData = v3RouterIface.encodeFunctionData('unwrapWETH9', [0n, seller.address]);
|
|
475
|
-
const sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData, sellUnwrapData]);
|
|
476
|
-
return { buyUnsigned, sellUnsigned };
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
// ✅ ERC20 池子:卖出后直接获得 ERC20
|
|
480
|
-
const sellSwapData = v3RouterIface.encodeFunctionData('exactInputSingle', [{
|
|
481
|
-
tokenIn: v3TokenOut,
|
|
482
|
-
tokenOut: v3TokenIn,
|
|
483
|
-
fee: v3Fee,
|
|
484
|
-
recipient: seller.address, // 直接发送到卖方地址
|
|
485
|
-
amountIn: sellAmountToken,
|
|
486
|
-
amountOutMinimum: 0n,
|
|
487
|
-
sqrtPriceLimitX96: 0n
|
|
488
|
-
}]);
|
|
489
|
-
const sellUnsigned = await v3RouterSeller.multicall.populateTransaction(deadline, [sellSwapData]);
|
|
490
|
-
return { buyUnsigned, sellUnsigned };
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
// V3 多跳暂不支持官方合约
|
|
494
|
-
throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
|
|
495
|
-
}
|
|
496
400
|
/**
|
|
497
401
|
* ✅ 构建多笔买入和卖出交易
|
|
498
402
|
*/
|
|
@@ -576,60 +480,6 @@ async function buildMultiRouteTransactions({ routeParams, buyAmountsWei, sellAmo
|
|
|
576
480
|
}
|
|
577
481
|
throw new Error('V3 多跳路由暂不支持官方合约,请使用 V2 路由或 V3 单跳');
|
|
578
482
|
}
|
|
579
|
-
/**
|
|
580
|
-
* ✅ 使用 quote-helpers 统一报价(估算利润)
|
|
581
|
-
*/
|
|
582
|
-
async function estimateProfitAmount({ provider, tokenAddress, sellAmountToken, routeParams }) {
|
|
583
|
-
try {
|
|
584
|
-
const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
|
|
585
|
-
const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
|
|
586
|
-
const estimatedSellFunds = await getTokenToNativeQuote(provider, tokenAddress, sellAmountToken, 'BSC', version, fee);
|
|
587
|
-
if (estimatedSellFunds <= 0n) {
|
|
588
|
-
return 0n;
|
|
589
|
-
}
|
|
590
|
-
// 万分之六
|
|
591
|
-
return (estimatedSellFunds * BigInt(PROFIT_CONFIG.RATE_BPS_SWAP)) / 10000n;
|
|
592
|
-
}
|
|
593
|
-
catch {
|
|
594
|
-
return 0n;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* ✅ 规划 nonce
|
|
599
|
-
* 交易顺序:贿赂 → 买入 → 卖出 → 利润
|
|
600
|
-
*/
|
|
601
|
-
async function planNonces({ buyer, seller, sameAddress, extractProfit, needBribeTx, nonceManager }) {
|
|
602
|
-
if (sameAddress) {
|
|
603
|
-
// 同一地址:贿赂(可选) + 买入 + 卖出 + 利润(可选)
|
|
604
|
-
const txCount = countTruthy([needBribeTx, true, true, extractProfit]);
|
|
605
|
-
const nonces = await nonceManager.getNextNonceBatch(buyer, txCount);
|
|
606
|
-
let idx = 0;
|
|
607
|
-
const bribeNonce = needBribeTx ? nonces[idx++] : undefined;
|
|
608
|
-
const buyerNonce = nonces[idx++];
|
|
609
|
-
const sellerNonce = nonces[idx++];
|
|
610
|
-
const profitNonce = extractProfit ? nonces[idx] : undefined;
|
|
611
|
-
return { buyerNonce, sellerNonce, bribeNonce, profitNonce };
|
|
612
|
-
}
|
|
613
|
-
if (needBribeTx || extractProfit) {
|
|
614
|
-
// 卖方需要多个 nonce:贿赂(可选) + 卖出 + 利润(可选)
|
|
615
|
-
const sellerTxCount = countTruthy([needBribeTx, true, extractProfit]);
|
|
616
|
-
// ✅ 并行获取 seller 和 buyer 的 nonce
|
|
617
|
-
const [sellerNonces, buyerNonce] = await Promise.all([
|
|
618
|
-
nonceManager.getNextNonceBatch(seller, sellerTxCount),
|
|
619
|
-
nonceManager.getNextNonce(buyer)
|
|
620
|
-
]);
|
|
621
|
-
let idx = 0;
|
|
622
|
-
const bribeNonce = needBribeTx ? sellerNonces[idx++] : undefined;
|
|
623
|
-
const sellerNonce = sellerNonces[idx++];
|
|
624
|
-
const profitNonce = extractProfit ? sellerNonces[idx] : undefined;
|
|
625
|
-
return { buyerNonce, sellerNonce, bribeNonce, profitNonce };
|
|
626
|
-
}
|
|
627
|
-
const [buyerNonce, sellerNonce] = await Promise.all([
|
|
628
|
-
nonceManager.getNextNonce(buyer),
|
|
629
|
-
nonceManager.getNextNonce(seller)
|
|
630
|
-
]);
|
|
631
|
-
return { buyerNonce, sellerNonce };
|
|
632
|
-
}
|
|
633
483
|
/**
|
|
634
484
|
* ✅ 规划多笔交易 nonce(与 Flap 一致)
|
|
635
485
|
* 交易顺序:贿赂 → 买入(多笔) → 卖出(多笔) → 利润
|
|
@@ -722,33 +572,6 @@ async function validateFinalBalances({ sameAddress, buyerFundsWei, buyerBalance,
|
|
|
722
572
|
}
|
|
723
573
|
// ERC20 余额已在 calculateBuyerFunds 中检查过
|
|
724
574
|
}
|
|
725
|
-
function countTruthy(values) {
|
|
726
|
-
return values.filter(Boolean).length;
|
|
727
|
-
}
|
|
728
|
-
/**
|
|
729
|
-
* ✅ 从前端传入的 startNonces 构建 NoncePlan(用于性能优化,避免 nonce 冲突)
|
|
730
|
-
* 顺序:同地址时 [baseNonce],不同地址时 [sellerNonce, buyerNonce]
|
|
731
|
-
*/
|
|
732
|
-
function buildNoncePlanFromStartNonces(startNonces, sameAddress, profitNeeded, needBribeTx) {
|
|
733
|
-
if (sameAddress) {
|
|
734
|
-
// 同一地址:贿赂(可选) + 买入 + 卖出 + 利润(可选)
|
|
735
|
-
let idx = 0;
|
|
736
|
-
const baseNonce = startNonces[0];
|
|
737
|
-
const bribeNonce = needBribeTx ? baseNonce + idx++ : undefined;
|
|
738
|
-
const buyerNonce = baseNonce + idx++;
|
|
739
|
-
const sellerNonce = baseNonce + idx++;
|
|
740
|
-
const profitNonce = profitNeeded ? baseNonce + idx : undefined;
|
|
741
|
-
return { buyerNonce, sellerNonce, bribeNonce, profitNonce };
|
|
742
|
-
}
|
|
743
|
-
// 不同地址
|
|
744
|
-
let sellerIdx = 0;
|
|
745
|
-
const sellerBaseNonce = startNonces[0];
|
|
746
|
-
const bribeNonce = needBribeTx ? sellerBaseNonce + sellerIdx++ : undefined;
|
|
747
|
-
const sellerNonce = sellerBaseNonce + sellerIdx++;
|
|
748
|
-
const profitNonce = profitNeeded ? sellerBaseNonce + sellerIdx : undefined;
|
|
749
|
-
const buyerNonce = startNonces[1];
|
|
750
|
-
return { buyerNonce, sellerNonce, bribeNonce, profitNonce };
|
|
751
|
-
}
|
|
752
575
|
/**
|
|
753
576
|
* ✅ 多钱包捆绑换手
|
|
754
577
|
* - 多个买方钱包执行买入(每个钱包1笔)
|
|
@@ -766,9 +589,9 @@ async function pancakeBundleBuyFirstMultiWallet(params) {
|
|
|
766
589
|
throw new Error('卖方钱包数量不能为0');
|
|
767
590
|
// 验证总交易数不超过限制
|
|
768
591
|
validateSwapCounts(buyCount, sellCount);
|
|
769
|
-
// ✅
|
|
592
|
+
// ✅ 计算利润比例(根据 userType 动态调整)
|
|
770
593
|
const totalTxCount = buyCount + sellCount;
|
|
771
|
-
const profitRateBps =
|
|
594
|
+
const profitRateBps = getProfitRatePerTxBps(config.userType) * totalTxCount;
|
|
772
595
|
// ✅ 判断是否使用原生代币
|
|
773
596
|
const useNativeToken = !quoteToken || quoteToken === ZERO_ADDRESS;
|
|
774
597
|
const context = createPancakeContext(config);
|
|
@@ -824,15 +647,17 @@ async function pancakeBundleBuyFirstMultiWallet(params) {
|
|
|
824
647
|
const buyAmountsWei = splitAmount(totalFundsWei, buyCount);
|
|
825
648
|
// ✅ 将代币平均分配给卖方
|
|
826
649
|
const sellAmountsWei = splitAmount(quoteResult.quotedTokenOut, sellCount);
|
|
827
|
-
// ✅
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
650
|
+
// ✅ 直接使用总交易金额作为利润基础(多钱包模式)
|
|
651
|
+
// profitRateBps = 每笔交易利润率(bps) * 交易笔数
|
|
652
|
+
const tokenProfitAmount = (totalFundsWei * BigInt(profitRateBps)) / 10000n;
|
|
653
|
+
// ✅ ERC20 购买:将代币利润转换为等值 BNB(因为利润是用 BNB 转账的)
|
|
654
|
+
let profitAmount = tokenProfitAmount;
|
|
655
|
+
if (!useNativeToken && tokenProfitAmount > 0n && quoteToken) {
|
|
656
|
+
const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
|
|
657
|
+
const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
|
|
658
|
+
profitAmount = await getTokenToNativeQuote(context.provider, quoteToken, tokenProfitAmount, 'BSC', version, fee);
|
|
659
|
+
console.log(`[pancakeBundleBuyFirstMultiWallet] ERC20→BNB 利润转换: ${ethers.formatUnits(tokenProfitAmount, quoteTokenDecimals)} → ${ethers.formatEther(profitAmount)} BNB`);
|
|
660
|
+
}
|
|
836
661
|
// ✅ 第三批并行:构建并签名所有交易
|
|
837
662
|
const allTransactions = [];
|
|
838
663
|
// 1. 贿赂交易(由主卖方支付)- 先处理以确定 nonce 偏移
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommonBundleConfig } from '../utils/bundle-helpers.js';
|
|
2
2
|
import { type GeneratedWallet } from '../utils/wallet.js';
|
|
3
|
+
export type UserType = 'v0' | 'v1';
|
|
3
4
|
export interface PancakeSwapSignConfig {
|
|
4
5
|
rpcUrl: string;
|
|
5
6
|
gasLimit?: number | bigint;
|
|
@@ -9,6 +10,7 @@ export interface PancakeSwapSignConfig {
|
|
|
9
10
|
txType?: 0 | 2;
|
|
10
11
|
chainId?: number;
|
|
11
12
|
reserveGasBNB?: number;
|
|
13
|
+
userType?: UserType;
|
|
12
14
|
bribeAmount?: number;
|
|
13
15
|
}
|
|
14
16
|
export type SwapRouteType = 'v2' | 'v3-single' | 'v3-multi';
|
|
@@ -439,11 +439,24 @@ async function planNonces({ seller, buyer, sameAddress, approvalExists, profitNe
|
|
|
439
439
|
]);
|
|
440
440
|
return { sellerNonce, buyerNonce };
|
|
441
441
|
}
|
|
442
|
-
|
|
442
|
+
/**
|
|
443
|
+
* 根据 userType 计算利润率
|
|
444
|
+
*/
|
|
445
|
+
function getProfitRateBps(userType) {
|
|
446
|
+
if (userType === 'v0') {
|
|
447
|
+
return PROFIT_CONFIG.RATE_BPS_V0; // 0.06%
|
|
448
|
+
}
|
|
449
|
+
else if (userType === 'v1') {
|
|
450
|
+
return PROFIT_CONFIG.RATE_BPS_V1; // 0.05%
|
|
451
|
+
}
|
|
452
|
+
return PROFIT_CONFIG.RATE_BPS_V0; // 默认 0.06%
|
|
453
|
+
}
|
|
454
|
+
function calculateProfitAmount(estimatedBNBOut, userType) {
|
|
443
455
|
if (estimatedBNBOut <= 0n) {
|
|
444
456
|
return 0n;
|
|
445
457
|
}
|
|
446
|
-
|
|
458
|
+
const rateBps = getProfitRateBps(userType);
|
|
459
|
+
return (estimatedBNBOut * BigInt(rateBps)) / 10000n;
|
|
447
460
|
}
|
|
448
461
|
/**
|
|
449
462
|
* ✅ 获取 ERC20 代币 → 原生代币(BNB)的报价
|
|
@@ -619,8 +632,8 @@ export async function pancakeBundleSwapMerkle(params) {
|
|
|
619
632
|
// 如果输出是 ERC20(如 USDT),需要先转换为 BNB 等值
|
|
620
633
|
let profitAmount;
|
|
621
634
|
if (useNativeToken) {
|
|
622
|
-
// 输出是 BNB
|
|
623
|
-
profitAmount = calculateProfitAmount(quoteResult.estimatedBNBOut);
|
|
635
|
+
// 输出是 BNB,直接计算利润(根据 userType 动态调整)
|
|
636
|
+
profitAmount = calculateProfitAmount(quoteResult.estimatedBNBOut, config.userType);
|
|
624
637
|
console.log(`[pancakeBundleSwapMerkle] 原生代币利润: ${ethers.formatEther(profitAmount)} BNB`);
|
|
625
638
|
}
|
|
626
639
|
else {
|
|
@@ -629,7 +642,7 @@ export async function pancakeBundleSwapMerkle(params) {
|
|
|
629
642
|
const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
|
|
630
643
|
const estimatedBNBValue = await getERC20ToNativeQuote(context.provider, quoteToken, quoteResult.estimatedBNBOut, // 这实际上是 ERC20 数量
|
|
631
644
|
version, fee);
|
|
632
|
-
profitAmount = calculateProfitAmount(estimatedBNBValue);
|
|
645
|
+
profitAmount = calculateProfitAmount(estimatedBNBValue, config.userType);
|
|
633
646
|
console.log(`[pancakeBundleSwapMerkle] ERC20→BNB 报价: ${ethers.formatUnits(quoteResult.estimatedBNBOut, quoteTokenDecimals)} ${quoteToken?.slice(0, 10)}... → ${ethers.formatEther(estimatedBNBValue)} BNB, 利润: ${ethers.formatEther(profitAmount)} BNB`);
|
|
634
647
|
}
|
|
635
648
|
// ✅ 获取贿赂金额
|
|
@@ -940,14 +953,14 @@ export async function pancakeBatchSwapMerkle(params) {
|
|
|
940
953
|
// ✅ 修复:利润计算应基于 BNB 数量,不是 ERC20 数量
|
|
941
954
|
let profitAmount;
|
|
942
955
|
if (useNativeToken) {
|
|
943
|
-
profitAmount = calculateProfitAmount(estimatedBNBOut);
|
|
956
|
+
profitAmount = calculateProfitAmount(estimatedBNBOut, config.userType);
|
|
944
957
|
console.log(`[pancakeBatchSwapMerkle] 原生代币利润: ${ethers.formatEther(profitAmount)} BNB`);
|
|
945
958
|
}
|
|
946
959
|
else {
|
|
947
960
|
const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
|
|
948
961
|
const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
|
|
949
962
|
const estimatedBNBValue = await getERC20ToNativeQuote(context.provider, quoteToken, estimatedBNBOut, version, fee);
|
|
950
|
-
profitAmount = calculateProfitAmount(estimatedBNBValue);
|
|
963
|
+
profitAmount = calculateProfitAmount(estimatedBNBValue, config.userType);
|
|
951
964
|
console.log(`[pancakeBatchSwapMerkle] ERC20→BNB 报价: ${ethers.formatUnits(estimatedBNBOut, quoteTokenDecimals)} → ${ethers.formatEther(estimatedBNBValue)} BNB, 利润: ${ethers.formatEther(profitAmount)} BNB`);
|
|
952
965
|
}
|
|
953
966
|
// 计算利润 nonce
|
|
@@ -1143,14 +1156,14 @@ export async function pancakeQuickBatchSwapMerkle(params) {
|
|
|
1143
1156
|
// ✅ 计算利润(万分之六)
|
|
1144
1157
|
let profitAmount;
|
|
1145
1158
|
if (useNativeToken) {
|
|
1146
|
-
profitAmount = calculateProfitAmount(estimatedOutput);
|
|
1159
|
+
profitAmount = calculateProfitAmount(estimatedOutput, config.userType);
|
|
1147
1160
|
}
|
|
1148
1161
|
else {
|
|
1149
1162
|
// ERC20 模式:需要将 ERC20 价值转换为 BNB
|
|
1150
1163
|
const version = routeParams.routeType === 'v2' ? 'v2' : 'v3';
|
|
1151
1164
|
const fee = routeParams.routeType === 'v3-single' ? routeParams.v3Fee : undefined;
|
|
1152
1165
|
const estimatedBNBValue = await getERC20ToNativeQuote(context.provider, quoteToken, estimatedOutput, version, fee);
|
|
1153
|
-
profitAmount = calculateProfitAmount(estimatedBNBValue);
|
|
1166
|
+
profitAmount = calculateProfitAmount(estimatedBNBValue, config.userType);
|
|
1154
1167
|
console.log(`[pancakeQuickBatchSwapMerkle] ERC20→BNB 报价: ${outputFormatted} → ${ethers.formatEther(estimatedBNBValue)} BNB`);
|
|
1155
1168
|
}
|
|
1156
1169
|
const distributableAmount = estimatedOutput - (useNativeToken ? profitAmount : 0n);
|
|
@@ -17,10 +17,12 @@ export declare const PROFIT_CONFIG: {
|
|
|
17
17
|
readonly RECIPIENT: "0xe8D0334fAf713884133640CAEe4ECdd2106AF103";
|
|
18
18
|
/** 利润比例(基点):30 bps = 0.3% = 千分之三(普通模式) */
|
|
19
19
|
readonly RATE_BPS: 30;
|
|
20
|
-
/** 利润比例(基点):6 bps = 0.06% = 万分之六(资金利用率模式) */
|
|
21
|
-
readonly RATE_BPS_CAPITAL: 6;
|
|
22
20
|
/** 利润比例(基点):6 bps = 0.06% = 万分之六(捆绑换手模式) */
|
|
23
21
|
readonly RATE_BPS_SWAP: 6;
|
|
22
|
+
/** 利润比例(基点):6 bps = 0.06% = 万分之六(用户类型 v0) */
|
|
23
|
+
readonly RATE_BPS_V0: 6;
|
|
24
|
+
/** 利润比例(基点):5 bps = 0.05% = 万分之五(用户类型 v1) */
|
|
25
|
+
readonly RATE_BPS_V1: 5;
|
|
24
26
|
};
|
|
25
27
|
export declare const CHAIN: {
|
|
26
28
|
BSC: {
|