four-flap-meme-sdk 2.2.17 → 2.2.19
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.
|
@@ -13,7 +13,7 @@ export { buildPermitPiggybackAuto } from './permit.js';
|
|
|
13
13
|
export { uploadTokenMeta, type TokenMetaInput } from './ipfs.js';
|
|
14
14
|
export { PinataClient, type PinataConfig, pinFileToIPFSWithJWT, pinImageByPath, pinFileToIPFSWithJWTWeb, pinDataURLWithJWTWeb, dataURLToBlob, type PinataPinResp } from './pinata.js';
|
|
15
15
|
export { predictVanityTokenAddressByChain, findSaltEndingByChain } from './vanity.js';
|
|
16
|
-
export { buildNewTokenV6Params, normalizeTaxV2Fields, NEW_TOKEN_V6_ABI, getTaxV3LaunchVanityOptions, getV3PermitLaunchVanityOptions, } from './launch-v6.js';
|
|
16
|
+
export { buildNewTokenV6Params, normalizeTaxV2Fields, resolveDividendTokenForQuote, NEW_TOKEN_V6_ABI, getTaxV3LaunchVanityOptions, getV3PermitLaunchVanityOptions, } from './launch-v6.js';
|
|
17
17
|
export { populateCreateTokenTransaction, normalizeTaxLaunchConfig, resolveCreateTokenLaunchFlags, MAGIC_DIVIDEND_SELF, type PopulateCreateTokenParams, type NormalizedTaxLaunchConfig, } from './portal-create-token.js';
|
|
18
18
|
export { getFlapMetaByAddress, getFlapMetasByAddresses } from './meta.js';
|
|
19
19
|
export { parseFlapError, getFlapErrorMessage, getFlapErrorMessageEn, type FlapErrorCode } from './errors.js';
|
|
@@ -13,7 +13,7 @@ export { buildPermitPiggybackAuto } from './permit.js';
|
|
|
13
13
|
export { uploadTokenMeta } from './ipfs.js';
|
|
14
14
|
export { PinataClient, pinFileToIPFSWithJWT, pinImageByPath, pinFileToIPFSWithJWTWeb, pinDataURLWithJWTWeb, dataURLToBlob } from './pinata.js';
|
|
15
15
|
export { predictVanityTokenAddressByChain, findSaltEndingByChain } from './vanity.js';
|
|
16
|
-
export { buildNewTokenV6Params, normalizeTaxV2Fields, NEW_TOKEN_V6_ABI, getTaxV3LaunchVanityOptions, getV3PermitLaunchVanityOptions, } from './launch-v6.js';
|
|
16
|
+
export { buildNewTokenV6Params, normalizeTaxV2Fields, resolveDividendTokenForQuote, NEW_TOKEN_V6_ABI, getTaxV3LaunchVanityOptions, getV3PermitLaunchVanityOptions, } from './launch-v6.js';
|
|
17
17
|
export { populateCreateTokenTransaction, normalizeTaxLaunchConfig, resolveCreateTokenLaunchFlags, MAGIC_DIVIDEND_SELF, } from './portal-create-token.js';
|
|
18
18
|
export { getFlapMetaByAddress, getFlapMetasByAddresses } from './meta.js';
|
|
19
19
|
export { parseFlapError, getFlapErrorMessage, getFlapErrorMessageEn } from './errors.js';
|
|
@@ -58,6 +58,11 @@ export type BuildNewTokenV6FromTaxV2Input = {
|
|
|
58
58
|
};
|
|
59
59
|
/** Portal.newTokenV6 ABI(ethers 简写格式,供 Contract 使用) */
|
|
60
60
|
export declare const NEW_TOKEN_V6_ABI = "function newTokenV6((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData,bytes32 extensionID,bytes extensionData,uint8 dexId,uint8 lpFeeProfile,uint16 buyTaxRate,uint16 sellTaxRate,uint64 taxDuration,uint64 antiFarmerDuration,uint16 mktBps,uint16 deflationBps,uint16 dividendBps,uint16 lpBps,uint256 minimumShareBalance,address dividendToken,address commissionReceiver,uint8 tokenVersion)) external payable returns (address)";
|
|
61
|
+
/**
|
|
62
|
+
* Portal 要求:quoteToken 为 ERC20 时 dividendToken 不能为 0。
|
|
63
|
+
* 未显式传入时默认与 quoteToken 相同(分红币种 = 报价币)。
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveDividendTokenForQuote(quoteToken?: string, dividendToken?: string): string;
|
|
61
66
|
export declare function normalizeTaxV2Fields(taxV2: TaxV2Config): (TaxV2Config & {
|
|
62
67
|
mktBps: number;
|
|
63
68
|
deflationBps: number;
|
|
@@ -7,6 +7,20 @@ import { TokenVersion } from './portal.js';
|
|
|
7
7
|
const NONE_EXTENSION_ID = '0x' + '00'.repeat(32);
|
|
8
8
|
/** Portal.newTokenV6 ABI(ethers 简写格式,供 Contract 使用) */
|
|
9
9
|
export const NEW_TOKEN_V6_ABI = 'function newTokenV6((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData,bytes32 extensionID,bytes extensionData,uint8 dexId,uint8 lpFeeProfile,uint16 buyTaxRate,uint16 sellTaxRate,uint64 taxDuration,uint64 antiFarmerDuration,uint16 mktBps,uint16 deflationBps,uint16 dividendBps,uint16 lpBps,uint256 minimumShareBalance,address dividendToken,address commissionReceiver,uint8 tokenVersion)) external payable returns (address)';
|
|
10
|
+
/**
|
|
11
|
+
* Portal 要求:quoteToken 为 ERC20 时 dividendToken 不能为 0。
|
|
12
|
+
* 未显式传入时默认与 quoteToken 相同(分红币种 = 报价币)。
|
|
13
|
+
*/
|
|
14
|
+
export function resolveDividendTokenForQuote(quoteToken, dividendToken) {
|
|
15
|
+
if (dividendToken && dividendToken !== ZeroAddress) {
|
|
16
|
+
return dividendToken;
|
|
17
|
+
}
|
|
18
|
+
const qt = quoteToken || ZeroAddress;
|
|
19
|
+
if (qt === ZeroAddress) {
|
|
20
|
+
return ZeroAddress;
|
|
21
|
+
}
|
|
22
|
+
return qt;
|
|
23
|
+
}
|
|
10
24
|
export function normalizeTaxV2Fields(taxV2) {
|
|
11
25
|
if ('distribution' in taxV2) {
|
|
12
26
|
return {
|
|
@@ -63,7 +77,7 @@ export function buildNewTokenV6Params(input) {
|
|
|
63
77
|
dividendBps: tv2.dividendBps & 0xffff,
|
|
64
78
|
lpBps: tv2.lpBps & 0xffff,
|
|
65
79
|
minimumShareBalance: BigInt(tv2.minimumShareBalance ?? 10000) * (10n ** 18n),
|
|
66
|
-
dividendToken: input.dividendToken
|
|
80
|
+
dividendToken: resolveDividendTokenForQuote(input.quoteToken, input.dividendToken),
|
|
67
81
|
commissionReceiver: input.commissionReceiver ?? ZeroAddress,
|
|
68
82
|
tokenVersion: TokenVersion.TOKEN_TAXED_V3,
|
|
69
83
|
};
|
|
@@ -94,7 +108,7 @@ export function buildNewTokenV6Params(input) {
|
|
|
94
108
|
dividendBps: (p.dividendBps ?? 0) & 0xffff,
|
|
95
109
|
lpBps: (p.lpBps ?? 0) & 0xffff,
|
|
96
110
|
minimumShareBalance: p.minimumShareBalance ?? 0n,
|
|
97
|
-
dividendToken: p.dividendToken
|
|
111
|
+
dividendToken: resolveDividendTokenForQuote(p.quoteToken, p.dividendToken),
|
|
98
112
|
commissionReceiver: isStandard ? ZeroAddress : (p.commissionReceiver ?? ZeroAddress),
|
|
99
113
|
tokenVersion: p.tokenVersion ?? TokenVersion.TOKEN_V2_PERMIT,
|
|
100
114
|
};
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
import { Contract, AbiCoder, ZeroAddress } from 'ethers';
|
|
23
23
|
import { TokenVersion } from './portal.js';
|
|
24
24
|
import { getVanitySuffix } from './constants.js';
|
|
25
|
-
import { normalizeTaxV2Fields } from './launch-v6.js';
|
|
25
|
+
import { normalizeTaxV2Fields, resolveDividendTokenForQuote } from './launch-v6.js';
|
|
26
26
|
/**
|
|
27
27
|
* 金库类型显示标签
|
|
28
28
|
*/
|
|
@@ -313,7 +313,7 @@ export function buildNewTokenV6WithVaultParams(input) {
|
|
|
313
313
|
dividendBps: tv2.dividendBps & 0xffff,
|
|
314
314
|
lpBps: tv2.lpBps & 0xffff,
|
|
315
315
|
minimumShareBalance: BigInt(tv2.minimumShareBalance ?? 10000) * (10n ** 18n),
|
|
316
|
-
dividendToken:
|
|
316
|
+
dividendToken: resolveDividendTokenForQuote(input.quoteToken),
|
|
317
317
|
commissionReceiver: ZeroAddress,
|
|
318
318
|
tokenVersion: TOKEN_TAXED_V3_VERSION,
|
|
319
319
|
vaultFactory,
|
|
@@ -15,6 +15,7 @@ const V3_PAIR_ABI = [
|
|
|
15
15
|
'function slot0() view returns (uint160 sqrtPriceX96,int24 tick,uint16 observationIndex,uint16 observationCardinality,uint16 observationCardinalityNext,uint8 feeProtocol,bool unlocked)',
|
|
16
16
|
'function token0() view returns (address)',
|
|
17
17
|
'function token1() view returns (address)',
|
|
18
|
+
'function getReserves() view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)',
|
|
18
19
|
];
|
|
19
20
|
/** BSC:lpFeeProfile → Infinity PoolKey 的 fee / parameters(与链上 Initialize 一致) */
|
|
20
21
|
const BSC_INFINITY_POOL_KEY_BY_PROFILE = {
|
|
@@ -133,6 +134,15 @@ function getCachedRpcProvider(rpcUrl) {
|
|
|
133
134
|
}
|
|
134
135
|
return p;
|
|
135
136
|
}
|
|
137
|
+
async function getTokenDecimalsSafe(provider, address) {
|
|
138
|
+
try {
|
|
139
|
+
const token = new Contract(address, ERC20_ABI, provider);
|
|
140
|
+
return Number(await token.decimals());
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return 18;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
136
146
|
/**
|
|
137
147
|
* Infinity CL 池子 WBNB:取多档卖出 quote 的最大值(贴近 GMGN「池内 WBNB」)
|
|
138
148
|
* 说明:不是 Vault 总 WBNB(全协议),也不是 L*sqrtP 虚拟储备(会高估到 ~5.8)。
|
|
@@ -208,39 +218,65 @@ async function getGraduatedV3PairMetrics(params) {
|
|
|
208
218
|
const quoteAddr = params.quoteTokenAddress.toLowerCase() === ZERO_ADDRESS
|
|
209
219
|
? params.wrappedNativeAddress
|
|
210
220
|
: params.quoteTokenAddress;
|
|
211
|
-
const [t0, t1
|
|
221
|
+
const [t0, t1] = await Promise.all([
|
|
212
222
|
pool.token0(),
|
|
213
223
|
pool.token1(),
|
|
214
|
-
pool.slot0(),
|
|
215
224
|
]);
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
225
|
+
let bal0;
|
|
226
|
+
let bal1;
|
|
227
|
+
try {
|
|
228
|
+
[bal0, bal1] = await Promise.all([
|
|
229
|
+
new Contract(t0, ERC20_ABI, provider).balanceOf(params.poolAddress),
|
|
230
|
+
new Contract(t1, ERC20_ABI, provider).balanceOf(params.poolAddress),
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
try {
|
|
235
|
+
const reserves = await pool.getReserves();
|
|
236
|
+
bal0 = BigInt(reserves.reserve0 ?? reserves[0]);
|
|
237
|
+
bal1 = BigInt(reserves.reserve1 ?? reserves[1]);
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
let sqrtPriceX96 = null;
|
|
244
|
+
try {
|
|
245
|
+
const slot0 = await pool.slot0();
|
|
246
|
+
sqrtPriceX96 = BigInt(Array.isArray(slot0) ? slot0[0] : slot0.sqrtPriceX96);
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
sqrtPriceX96 = null;
|
|
250
|
+
}
|
|
251
|
+
const [dec0, dec1] = await Promise.all([
|
|
252
|
+
getTokenDecimalsSafe(provider, t0),
|
|
253
|
+
getTokenDecimalsSafe(provider, t1),
|
|
219
254
|
]);
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
255
|
+
const spot = sqrtPriceX96 && sqrtPriceX96 > 0n
|
|
256
|
+
? v3SpotPriceQuotePerToken({
|
|
257
|
+
sqrtPriceX96,
|
|
258
|
+
tokenAddress: params.tokenAddress,
|
|
259
|
+
token0: t0,
|
|
260
|
+
token1: t1,
|
|
261
|
+
quoteTokenAddress: quoteAddr,
|
|
262
|
+
})
|
|
263
|
+
: null;
|
|
228
264
|
const tokenIs0 = t0.toLowerCase() === tokenLower;
|
|
229
|
-
const poolTokenAmount =
|
|
230
|
-
const
|
|
265
|
+
const poolTokenAmount = formatUnits(tokenIs0 ? bal0 : bal1, tokenIs0 ? dec0 : dec1);
|
|
266
|
+
const poolQuoteAmount = formatUnits(tokenIs0 ? bal1 : bal0, tokenIs0 ? dec1 : dec0);
|
|
231
267
|
let price = spot;
|
|
232
268
|
if (!price && parseFloat(poolTokenAmount) > 0) {
|
|
233
|
-
price = String(parseFloat(
|
|
269
|
+
price = String(parseFloat(poolQuoteAmount) / parseFloat(poolTokenAmount));
|
|
234
270
|
}
|
|
235
271
|
if (!price) {
|
|
236
272
|
price = await quotePortalPrice(params.portal, params.tokenAddress, params.quoteTokenAddress, params.wrappedNativeAddress);
|
|
237
273
|
}
|
|
238
|
-
if (!price && poolTokenAmount === '0' &&
|
|
274
|
+
if (!price && poolTokenAmount === '0' && poolQuoteAmount === '0')
|
|
239
275
|
return null;
|
|
240
276
|
return {
|
|
241
277
|
price: price ?? '0',
|
|
242
278
|
progress: '100',
|
|
243
|
-
poolBNBAmount,
|
|
279
|
+
poolBNBAmount: poolQuoteAmount,
|
|
244
280
|
poolTokenAmount,
|
|
245
281
|
dexKind: 'PANCAKE_V3',
|
|
246
282
|
};
|