four-flap-meme-sdk 2.2.5 → 2.2.7

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.
@@ -24,6 +24,21 @@ function resolveCreateTokenLaunchFlags(params) {
24
24
  params.migratorType === MigratorType.PCS_INFINITY_CL_MIGRATOR;
25
25
  return { normalizedTax, isTaxLaunch, hasVault, useV4Portal, useClInfinityLaunch };
26
26
  }
27
+ /**
28
+ * 无捆绑钱包、仅 Dev 自跟买、原生报价 → Flap 文档方式 A(create 内 quoteAmt + msg.value)
29
+ */
30
+ function canUseLaunchMethodA(privateKeys, buyAmounts, devAddress, useNativeToken) {
31
+ if (!useNativeToken || buyAmounts.length !== 1 || privateKeys.length !== 2) {
32
+ return false;
33
+ }
34
+ try {
35
+ const buyerAddr = new Wallet(privateKeys[1]).address;
36
+ return buyerAddr.toLowerCase() === devAddress.toLowerCase();
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
27
42
  export async function createTokenWithBundleBuyMerkle(params) {
28
43
  const { chain, privateKeys, buyAmounts, tokenInfo, tokenAddress, config } = params;
29
44
  if (privateKeys.length === 0) {
@@ -40,6 +55,16 @@ export async function createTokenWithBundleBuyMerkle(params) {
40
55
  const originalPortalAddr = FLAP_ORIGINAL_PORTAL_ADDRESSES[chain];
41
56
  const portal = new ethers.Contract(originalPortalAddr, PORTAL_ABI, devWallet);
42
57
  const { normalizedTax, useV4Portal, useClInfinityLaunch } = resolveCreateTokenLaunchFlags(params);
58
+ const inputToken = params.quoteToken && params.quoteToken !== ZERO_ADDRESS ? params.quoteToken : ZERO_ADDRESS;
59
+ const useNativeToken = inputToken === ZERO_ADDRESS;
60
+ const extractProfit = config.extractProfitOnLaunch === false ? false : shouldExtractProfit(config);
61
+ const useMethodA = canUseLaunchMethodA(privateKeys, buyAmounts, devWallet.address, useNativeToken);
62
+ let methodAQuoteAmt = 0n;
63
+ let methodABuyMeta;
64
+ if (useMethodA) {
65
+ methodABuyMeta = analyzeBuyFunds(buyAmounts, config, extractProfit);
66
+ methodAQuoteAmt = methodABuyMeta.fundsList[0] ?? 0n;
67
+ }
43
68
  const createTxPromise = populateCreateTokenTransaction({
44
69
  chain,
45
70
  devWallet,
@@ -58,6 +83,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
58
83
  useV4Portal,
59
84
  useClInfinityLaunch,
60
85
  taxConfig: normalizedTax,
86
+ initialQuoteAmt: useMethodA ? methodAQuoteAmt : 0n,
61
87
  });
62
88
  const [gasPrice, createTxUnsigned, devNonce] = await Promise.all([
63
89
  resolveGasPrice(provider, config),
@@ -72,19 +98,60 @@ export async function createTokenWithBundleBuyMerkle(params) {
72
98
  gasPrice,
73
99
  chainId,
74
100
  type: getTxType(config),
101
+ value: useMethodA ? methodAQuoteAmt : 0n,
75
102
  };
76
103
  const signedCreateTx = await devWallet.signTransaction(createTxRequest);
77
104
  signedTxs.push(signedCreateTx);
105
+ if (useMethodA && methodABuyMeta) {
106
+ const { totalBuyAmount, totalProfit } = methodABuyMeta;
107
+ const bribeAmount = getBribeAmount(config);
108
+ const bribeTxs = [];
109
+ let nextDevNonce = devNonce + 1;
110
+ if (bribeAmount > 0n) {
111
+ const bribeTx = await devWallet.signTransaction({
112
+ to: BLOCKRAZOR_BUILDER_EOA,
113
+ value: bribeAmount,
114
+ nonce: nextDevNonce,
115
+ gasPrice,
116
+ gasLimit: GAS_LIMITS.BRIBE,
117
+ chainId,
118
+ type: getTxType(config),
119
+ });
120
+ bribeTxs.push(bribeTx);
121
+ nextDevNonce += 1;
122
+ }
123
+ const profitTxs = [];
124
+ let profitHopWallets;
125
+ if (extractProfit && totalProfit > 0n) {
126
+ const profitHopResult = await buildProfitHopTransactions({
127
+ provider,
128
+ payerWallet: devWallet,
129
+ profitAmount: totalProfit,
130
+ profitRecipient: getProfitRecipient(),
131
+ hopCount: PROFIT_HOP_COUNT,
132
+ gasPrice,
133
+ chainId,
134
+ txType: getTxType(config),
135
+ startNonce: nextDevNonce,
136
+ });
137
+ profitTxs.push(...profitHopResult.signedTransactions);
138
+ profitHopWallets = profitHopResult.hopWallets;
139
+ }
140
+ nonceManager.clearTemp();
141
+ return {
142
+ signedTransactions: [...bribeTxs, ...signedTxs, ...profitTxs],
143
+ tokenAddress,
144
+ profitHopWallets,
145
+ metadata: {
146
+ ...buildProfitMetadata(extractProfit, totalBuyAmount, totalProfit, 0),
147
+ launchMethod: 'quoteAmt',
148
+ },
149
+ };
150
+ }
78
151
  const buyers = createWallets(privateKeys.slice(1), provider);
79
- // 发币+捆绑买:默认刮利润(与 emitservice isAddressRevenue 末笔校验、BSC 白名单 slice(-3) 对齐)
80
- // 仅当显式 extractProfitOnLaunch: false 时关闭(需后端同步放宽校验)
81
- const extractProfit = config.extractProfitOnLaunch === false ? false : shouldExtractProfit(config);
82
152
  const { fundsList, originalAmounts, totalBuyAmount, totalProfit } = analyzeBuyFunds(buyAmounts, config, extractProfit);
83
153
  const maxFundsIndex = findMaxIndex(originalAmounts);
84
154
  const gasLimits = buildGasLimitList(buyers.length, config);
85
- // ✅ 支持 quoteToken:如果传入了 quoteToken 且非零地址,则使用它
86
- const inputToken = params.quoteToken && params.quoteToken !== ZERO_ADDRESS ? params.quoteToken : ZERO_ADDRESS;
87
- const useNativeToken = inputToken === ZERO_ADDRESS;
88
155
  // ✅ 如果使用非原生代币(如 USDC),需要根据精度转换金额
89
156
  let adjustedFundsList = fundsList;
90
157
  let profitTokenAmount = totalProfit;
@@ -160,7 +227,10 @@ export async function createTokenWithBundleBuyMerkle(params) {
160
227
  signedTransactions: [...bribeTxs, ...signedTxs, ...signedBuys, ...profitTxs],
161
228
  tokenAddress,
162
229
  profitHopWallets, // ✅ 返回利润多跳钱包
163
- metadata: buildProfitMetadata(extractProfit, totalBuyAmount, totalProfit, buyers.length),
230
+ metadata: {
231
+ ...buildProfitMetadata(extractProfit, totalBuyAmount, totalProfit, buyers.length),
232
+ launchMethod: 'swapExactInput',
233
+ },
164
234
  };
165
235
  }
166
236
  /**
@@ -51,6 +51,8 @@ export type PopulateCreateTokenParams = {
51
51
  useClInfinityLaunch?: boolean;
52
52
  /** 高级税币 / 税币 V3 配置 */
53
53
  taxConfig?: NormalizedTaxLaunchConfig;
54
+ /** 创建时内嵌买入(Flap 文档方式 A:quoteAmt + msg.value) */
55
+ initialQuoteAmt?: bigint;
54
56
  };
55
57
  /** 将 TaxV2Config(含 distribution 嵌套)或 flat 结构归一化 */
56
58
  export declare function normalizeTaxLaunchConfig(input?: {
@@ -74,7 +76,4 @@ export declare function normalizeTaxLaunchConfig(input?: {
74
76
  minimumShareBalance?: number;
75
77
  };
76
78
  }, fallbackTaxRate?: number): NormalizedTaxLaunchConfig | undefined;
77
- /**
78
- * 构建发币 populateTransaction(优先 V6/V7,Vault 走 VaultPortal)
79
- */
80
79
  export declare function populateCreateTokenTransaction(params: PopulateCreateTokenParams): Promise<import("ethers").ContractTransaction>;
@@ -38,7 +38,7 @@ function buildV6TaxParams(params, taxConfig, dist) {
38
38
  salt: params.salt ?? zeroBytes32(),
39
39
  migratorType: (params.migratorType ?? MigratorType.V2_MIGRATOR) & 0xff,
40
40
  quoteToken: params.quoteToken || ZERO_ADDRESS,
41
- quoteAmt: 0n,
41
+ quoteAmt: resolveCreateQuoteAmt(params),
42
42
  beneficiary: params.beneficiary,
43
43
  permitData: '0x',
44
44
  extensionID: params.extensionID ?? zeroBytes32(),
@@ -91,10 +91,14 @@ export function normalizeTaxLaunchConfig(input, fallbackTaxRate) {
91
91
  /**
92
92
  * 构建发币 populateTransaction(优先 V6/V7,Vault 走 VaultPortal)
93
93
  */
94
+ function resolveCreateQuoteAmt(params) {
95
+ return params.initialQuoteAmt ?? 0n;
96
+ }
94
97
  export async function populateCreateTokenTransaction(params) {
95
98
  const taxConfig = params.taxConfig;
96
99
  const { buyTaxRate, sellTaxRate } = resolveTaxRates(taxConfig, params.taxRate);
97
100
  const isTaxLaunch = buyTaxRate > 0 || sellTaxRate > 0;
101
+ const quoteAmt = resolveCreateQuoteAmt(params);
98
102
  // 1) Vault 金库税币
99
103
  if (taxConfig?.vaultConfig && taxConfig.vaultConfig.vaultType !== 'none') {
100
104
  validateTaxDistribution(taxConfig.mktBps, taxConfig.deflationBps, taxConfig.dividendBps, taxConfig.lpBps);
@@ -114,7 +118,7 @@ export async function populateCreateTokenTransaction(params) {
114
118
  taxRate: Math.max(buyTaxRate, sellTaxRate) & 0xffff,
115
119
  migratorType: (params.migratorType ?? MigratorType.V2_MIGRATOR) & 0xff,
116
120
  quoteToken: params.quoteToken || ZERO_ADDRESS,
117
- quoteAmt: 0n,
121
+ quoteAmt,
118
122
  permitData: '0x',
119
123
  extensionID: zeroBytes32(),
120
124
  extensionData: '0x',
@@ -163,7 +167,7 @@ export async function populateCreateTokenTransaction(params) {
163
167
  taxRate: (params.taxRate ?? 0) & 0xffff,
164
168
  migratorType: (params.migratorType ?? MigratorType.V3_MIGRATOR) & 0xff,
165
169
  quoteToken: params.quoteToken || ZERO_ADDRESS,
166
- quoteAmt: 0n,
170
+ quoteAmt,
167
171
  beneficiary: params.beneficiary,
168
172
  permitData: '0x',
169
173
  extensionID: params.extensionID ?? zeroBytes32(),
@@ -189,7 +193,7 @@ export async function populateCreateTokenTransaction(params) {
189
193
  salt: params.salt ?? zeroBytes32(),
190
194
  migratorType: MigratorType.PCS_INFINITY_CL_MIGRATOR,
191
195
  quoteToken: params.quoteToken || ZERO_ADDRESS,
192
- quoteAmt: 0n,
196
+ quoteAmt,
193
197
  permitData: '0x',
194
198
  extensionID: params.extensionID ?? zeroBytes32(),
195
199
  extensionData: params.extensionData ?? '0x',
@@ -218,7 +222,7 @@ export async function populateCreateTokenTransaction(params) {
218
222
  taxRate: (params.taxRate ?? 0) & 0xffff,
219
223
  migratorType: (params.migratorType ?? MigratorType.V3_MIGRATOR) & 0xff,
220
224
  quoteToken: params.quoteToken || ZERO_ADDRESS,
221
- quoteAmt: 0n,
225
+ quoteAmt,
222
226
  beneficiary: params.beneficiary,
223
227
  permitData: '0x',
224
228
  extensionID: params.extensionID,
@@ -234,7 +238,7 @@ export async function populateCreateTokenTransaction(params) {
234
238
  salt: params.salt ?? zeroBytes32(),
235
239
  migratorType: (params.migratorType ?? MigratorType.V2_MIGRATOR) & 0xff,
236
240
  quoteToken: params.quoteToken || ZERO_ADDRESS,
237
- quoteAmt: 0n,
241
+ quoteAmt,
238
242
  beneficiary: params.beneficiary,
239
243
  permitData: '0x',
240
244
  extensionID: params.extensionID ?? zeroBytes32(),
@@ -10,7 +10,8 @@ export declare function predictVanityTokenAddress(salt: string, portal: string,
10
10
  * BSC/MONAD 默认使用 NORMAL 实现(非税版)
11
11
  * @param taxedV5 - 是否使用 V5 高级税代币实现 (mkt/deflation/dividend/lp)
12
12
  */
13
- export declare function predictVanityTokenAddressByChain(chain: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH' | 'MONAD', salt: string, taxed?: boolean, taxedV5?: boolean): string;
13
+ export declare function predictVanityTokenAddressByChain(chain: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH' | 'MONAD', salt: string, taxed?: boolean, taxedV5?: boolean, // ✅ V5 高级税代币标识 (mkt/deflation/dividend/lp)
14
+ taxedV3?: boolean): string;
14
15
  /**
15
16
  * 寻找满足后缀的 salt(默认 8888)
16
17
  * 注意:该方法为同步 CPU 搜索,谨慎设置迭代限制
@@ -41,6 +42,7 @@ export declare function findSaltEndingByChain(opts: {
41
42
  seed?: string;
42
43
  taxed?: boolean;
43
44
  taxedV5?: boolean;
45
+ taxedV3?: boolean;
44
46
  }): Promise<{
45
47
  salt: string;
46
48
  address: string;
@@ -19,13 +19,14 @@ export function predictVanityTokenAddress(salt, portal, tokenImpl) {
19
19
  * BSC/MONAD 默认使用 NORMAL 实现(非税版)
20
20
  * @param taxedV5 - 是否使用 V5 高级税代币实现 (mkt/deflation/dividend/lp)
21
21
  */
22
- export function predictVanityTokenAddressByChain(chain, salt, taxed = false, taxedV5 = false) {
22
+ export function predictVanityTokenAddressByChain(chain, salt, taxed = false, taxedV5 = false, // ✅ V5 高级税代币标识 (mkt/deflation/dividend/lp)
23
+ taxedV3 = false) {
23
24
  // 使用 Flap 平台的原始 Portal 地址(用于 CREATE2)
24
25
  const portal = FLAP_ORIGINAL_PORTAL_ADDRESSES[chain];
25
26
  let tokenImpl;
26
27
  if (chain === 'BSC') {
27
- if (taxedV5) {
28
- // ✅ V5 高级税代币使用新的实现地址
28
+ if (taxedV5 || taxedV3) {
29
+ // ✅ V5 高级税代币(含 vault)使用新的实现地址
29
30
  tokenImpl = FLAP_TOKEN_IMPL_ADDRESSES.BSC_TAXED_V5;
30
31
  }
31
32
  else {
@@ -77,8 +78,8 @@ export async function findSaltEndingByChain(opts) {
77
78
  const portal = FLAP_ORIGINAL_PORTAL_ADDRESSES[opts.chain];
78
79
  let tokenImpl;
79
80
  if (opts.chain === 'BSC') {
80
- if (opts.taxedV5) {
81
- // ✅ V5 高级税代币使用新的实现地址
81
+ if (opts.taxedV5 || opts.taxedV3) {
82
+ // ✅ V5 高级税代币(含 vault)使用新的实现地址
82
83
  tokenImpl = FLAP_TOKEN_IMPL_ADDRESSES.BSC_TAXED_V5;
83
84
  }
84
85
  else {
@@ -95,8 +96,8 @@ export async function findSaltEndingByChain(opts) {
95
96
  if (!portal || !tokenImpl) {
96
97
  throw new Error(`Flap Protocol not fully deployed on ${opts.chain}`);
97
98
  }
98
- // ✅ 如果未指定后缀,根据链自动选择正确的后缀
99
- const suffix = opts.suffix ?? getVanitySuffix(opts.chain, opts.taxed);
99
+ // ✅ 如果未指定后缀,根据链自动选择正确的后缀(税代币 / V5 / V3 vault 均使用 tax 后缀)
100
+ const suffix = opts.suffix ?? getVanitySuffix(opts.chain, opts.taxed || opts.taxedV5 || opts.taxedV3);
100
101
  return findSaltEnding({
101
102
  portal,
102
103
  tokenImpl,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "2.2.5",
3
+ "version": "2.2.7",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",