four-flap-meme-sdk 4.0.2 → 4.0.4
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/abis/openfour.d.ts +94 -0
- package/dist/abis/openfour.js +63 -0
- package/dist/bundle/four-meme/core/constants.js +1 -0
- package/dist/bundle/four-meme/core/create-openfour.d.ts +23 -0
- package/dist/bundle/four-meme/core/create-openfour.js +118 -0
- package/dist/bundle/four-meme/core/create-token-quote.d.ts +24 -0
- package/dist/bundle/four-meme/core/create-token-quote.js +53 -0
- package/dist/bundle/four-meme/core/create-token.js +28 -39
- package/dist/bundle/four-meme/core/index.d.ts +2 -0
- package/dist/bundle/four-meme/core/index.js +1 -0
- package/dist/bundle/four-meme/private/buy-quote.d.ts +35 -0
- package/dist/bundle/four-meme/private/buy-quote.js +70 -0
- package/dist/bundle/four-meme/private/buy.js +82 -87
- package/dist/bundle/four-meme/private/index.d.ts +2 -0
- package/dist/bundle/four-meme/private/index.js +1 -0
- package/dist/bundle/four-meme/private/openfour-buy.d.ts +10 -0
- package/dist/bundle/four-meme/private/openfour-buy.js +65 -0
- package/dist/bundle/four-meme/types/index.d.ts +13 -0
- package/dist/chains/bsc/constants.d.ts +1 -0
- package/dist/core/clients/four.d.ts +25 -17
- package/dist/core/clients/four.js +128 -3
- package/dist/core/clients/index.d.ts +1 -1
- package/dist/core/clients/index.js +1 -1
- package/dist/core/constants/addresses.d.ts +2 -0
- package/dist/core/constants/addresses.js +2 -0
- package/dist/domains/flows/create.d.ts +1 -0
- package/dist/domains/flows/create.js +13 -12
- package/dist/domains/four/contracts/tm-bundle-create.js +42 -11
- package/dist/domains/four/contracts/tm-bundle-helpers.d.ts +6 -0
- package/dist/domains/four/index.d.ts +1 -0
- package/dist/domains/four/index.js +1 -0
- package/dist/domains/four/raised-token.d.ts +38 -0
- package/dist/domains/four/raised-token.js +75 -0
- package/dist/domains/four/raised-token.test.d.ts +1 -0
- package/dist/domains/four/raised-token.test.js +43 -0
- package/dist/domains/four/tax-token.d.ts +2 -0
- package/dist/domains/four/tax-token.js +13 -4
- package/dist/domains/four/tax-token.test.d.ts +1 -0
- package/dist/domains/four/tax-token.test.js +89 -0
- package/dist/domains/openfour/create-arg.d.ts +13 -0
- package/dist/domains/openfour/create-arg.js +78 -0
- package/dist/domains/openfour/index.d.ts +4 -0
- package/dist/domains/openfour/index.js +3 -0
- package/dist/domains/openfour/registry.d.ts +4 -0
- package/dist/domains/openfour/registry.js +44 -0
- package/dist/domains/openfour/schema.d.ts +20 -0
- package/dist/domains/openfour/schema.js +88 -0
- package/dist/domains/openfour/types.d.ts +76 -0
- package/dist/domains/openfour/types.js +1 -0
- package/dist/exports/root-bundle-and-tooling.d.ts +4 -2
- package/dist/exports/root-bundle-and-tooling.js +2 -2
- package/dist/exports/root-foundations.d.ts +3 -1
- package/dist/exports/root-foundations.js +3 -1
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ import { ADDRESSES, BLOCKRAZOR_BUILDER_EOA, CHAINS } from '../../../core/constan
|
|
|
8
8
|
import { TM2_ABI } from '../../../abis/common.js';
|
|
9
9
|
import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount, } from '../../config-helpers.js';
|
|
10
10
|
import { createSignProvider } from '../../../core/sign-context-helpers.js';
|
|
11
|
+
import { isFourErc20BuyQuote, resolveFourBuyPayment, signQuoteApproveTxs } from './buy-quote.js';
|
|
11
12
|
const CHAIN_ID = CHAINS.BSC.chainId;
|
|
12
13
|
/**
|
|
13
14
|
* 私有购买(单笔)(仅签名版本 - 不依赖 Merkle)
|
|
@@ -15,46 +16,45 @@ const CHAIN_ID = CHAINS.BSC.chainId;
|
|
|
15
16
|
* ✅ 优化:并行获取 gasPrice 和 nonce
|
|
16
17
|
*/
|
|
17
18
|
export async function fourPrivateBuyMerkle(params) {
|
|
18
|
-
const { privateKey, tokenAddress, funds, to, config } = params;
|
|
19
|
-
// ✅ 直接使用传入的 RPC URL 创建 provider(不依赖 Merkle)
|
|
19
|
+
const { privateKey, tokenAddress, funds, to, config, quoteTokenAddress, quoteDecimals } = params;
|
|
20
20
|
const provider = createSignProvider(config.rpcUrl, CHAIN_ID, 'BSC');
|
|
21
21
|
const wallet = new Wallet(privateKey, provider);
|
|
22
22
|
const tmAddr = ADDRESSES.BSC.TokenManagerOriginal;
|
|
23
23
|
const txType = getTxType(config);
|
|
24
24
|
const gasLimit = getGasLimit(config, 800000);
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const payment = await resolveFourBuyPayment({
|
|
26
|
+
provider,
|
|
27
|
+
tokenAddress,
|
|
28
|
+
funds,
|
|
29
|
+
quote: { quoteTokenAddress, quoteDecimals },
|
|
30
|
+
});
|
|
31
|
+
const originalFundsWei = payment.fundsWei;
|
|
32
|
+
const erc20Quote = isFourErc20BuyQuote(quoteTokenAddress);
|
|
33
|
+
const extractProfit = shouldExtractProfit() && !erc20Quote;
|
|
28
34
|
let profitWei = 0n;
|
|
29
35
|
let actualFundsWei = originalFundsWei;
|
|
36
|
+
let actualValueWei = payment.valueWei;
|
|
30
37
|
if (extractProfit) {
|
|
31
38
|
const { profit, remaining } = calculateProfit(originalFundsWei);
|
|
32
39
|
profitWei = profit;
|
|
33
40
|
actualFundsWei = remaining;
|
|
41
|
+
actualValueWei = remaining;
|
|
34
42
|
}
|
|
35
43
|
const tm2 = new ethers.Contract(tmAddr, TM2_ABI, wallet);
|
|
36
|
-
// ✅ 获取贿赂金额
|
|
37
44
|
const bribeAmount = getBribeAmount(config);
|
|
38
45
|
const needBribeTx = bribeAmount > 0n;
|
|
39
46
|
const needProfitTx = extractProfit && profitWei > 0n;
|
|
40
|
-
|
|
41
|
-
const [gasPrice,
|
|
47
|
+
const nonceManager = new NonceManager(provider);
|
|
48
|
+
const [gasPrice, unsigned] = await Promise.all([
|
|
42
49
|
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
43
|
-
wallet.getNonce(),
|
|
44
50
|
tm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, to ?? wallet.address, actualFundsWei, 0n, {
|
|
45
|
-
value:
|
|
51
|
+
value: actualValueWei,
|
|
46
52
|
}),
|
|
47
53
|
]);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const profitNonce = needProfitTx ? baseNonce + nonceIdx : undefined;
|
|
53
|
-
// ✅ 并行签名所有交易(贿赂、买入、利润)
|
|
54
|
-
const signPromises = [];
|
|
55
|
-
// 贿赂交易
|
|
56
|
-
if (needBribeTx && bribeNonce !== undefined) {
|
|
57
|
-
signPromises.push(wallet.signTransaction({
|
|
54
|
+
const signedTxs = [];
|
|
55
|
+
if (needBribeTx) {
|
|
56
|
+
const bribeNonce = await nonceManager.getNextNonce(wallet);
|
|
57
|
+
signedTxs.push(await wallet.signTransaction({
|
|
58
58
|
to: BLOCKRAZOR_BUILDER_EOA,
|
|
59
59
|
value: bribeAmount,
|
|
60
60
|
nonce: bribeNonce,
|
|
@@ -64,22 +64,32 @@ export async function fourPrivateBuyMerkle(params) {
|
|
|
64
64
|
type: txType,
|
|
65
65
|
}));
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
if (erc20Quote && payment.quoteAddress && payment.approvalWei > 0n) {
|
|
68
|
+
const approves = await signQuoteApproveTxs({
|
|
69
|
+
wallets: [wallet],
|
|
70
|
+
quoteAddress: payment.quoteAddress,
|
|
71
|
+
spender: tmAddr,
|
|
72
|
+
amounts: [actualFundsWei],
|
|
73
|
+
nonceManager,
|
|
74
|
+
gasPrice,
|
|
75
|
+
chainId: CHAIN_ID,
|
|
76
|
+
txType,
|
|
77
|
+
provider,
|
|
78
|
+
});
|
|
79
|
+
signedTxs.push(...approves);
|
|
80
|
+
}
|
|
81
|
+
signedTxs.push(await wallet.signTransaction({
|
|
69
82
|
...unsigned,
|
|
70
83
|
from: wallet.address,
|
|
71
|
-
nonce:
|
|
84
|
+
nonce: await nonceManager.getNextNonce(wallet),
|
|
72
85
|
gasLimit,
|
|
73
86
|
gasPrice,
|
|
74
87
|
chainId: CHAIN_ID,
|
|
75
88
|
type: txType,
|
|
76
|
-
value:
|
|
89
|
+
value: actualValueWei,
|
|
77
90
|
}));
|
|
78
|
-
// ✅ 并行签名完成后按顺序返回
|
|
79
|
-
const signedTxs = await Promise.all(signPromises);
|
|
80
|
-
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
81
91
|
let profitHopWallets;
|
|
82
|
-
if (needProfitTx
|
|
92
|
+
if (needProfitTx) {
|
|
83
93
|
const profitHopResult = await buildProfitHopTransactions({
|
|
84
94
|
provider,
|
|
85
95
|
payerWallet: wallet,
|
|
@@ -89,14 +99,15 @@ export async function fourPrivateBuyMerkle(params) {
|
|
|
89
99
|
gasPrice,
|
|
90
100
|
chainId: CHAIN_ID,
|
|
91
101
|
txType,
|
|
92
|
-
startNonce:
|
|
102
|
+
startNonce: await nonceManager.getNextNonce(wallet),
|
|
93
103
|
});
|
|
94
104
|
signedTxs.push(...profitHopResult.signedTransactions);
|
|
95
|
-
profitHopWallets = profitHopResult.hopWallets;
|
|
105
|
+
profitHopWallets = profitHopResult.hopWallets;
|
|
96
106
|
}
|
|
107
|
+
nonceManager.clearTemp();
|
|
97
108
|
return {
|
|
98
109
|
signedTransactions: signedTxs,
|
|
99
|
-
profitHopWallets,
|
|
110
|
+
profitHopWallets,
|
|
100
111
|
};
|
|
101
112
|
}
|
|
102
113
|
/**
|
|
@@ -105,25 +116,30 @@ export async function fourPrivateBuyMerkle(params) {
|
|
|
105
116
|
* ✅ 优化:并行获取 gasPrice 和 nonces,批量构建交易
|
|
106
117
|
*/
|
|
107
118
|
export async function fourBatchPrivateBuyMerkle(params) {
|
|
108
|
-
const { privateKeys, fundsList, tokenAddress, config } = params;
|
|
119
|
+
const { privateKeys, fundsList, tokenAddress, config, quoteTokenAddress, quoteDecimals } = params;
|
|
109
120
|
if (privateKeys.length !== fundsList.length) {
|
|
110
121
|
throw new Error('privateKeys and fundsList length mismatch');
|
|
111
122
|
}
|
|
112
|
-
// ✅ 直接使用传入的 RPC URL 创建 provider(不依赖 Merkle)
|
|
113
123
|
const provider = createSignProvider(config.rpcUrl, CHAIN_ID, 'BSC');
|
|
114
124
|
const tmAddr = ADDRESSES.BSC.TokenManagerOriginal;
|
|
115
125
|
const txType = getTxType(config);
|
|
116
126
|
const finalGasLimit = getGasLimit(config, 800000);
|
|
127
|
+
const erc20Quote = isFourErc20BuyQuote(quoteTokenAddress);
|
|
117
128
|
const wallets = privateKeys.map((k) => new Wallet(k, provider));
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
const payments = await Promise.all(fundsList.map((funds) => resolveFourBuyPayment({
|
|
130
|
+
provider,
|
|
131
|
+
tokenAddress,
|
|
132
|
+
funds,
|
|
133
|
+
quote: { quoteTokenAddress, quoteDecimals },
|
|
134
|
+
})));
|
|
135
|
+
const originalAmountsWei = payments.map((p) => p.fundsWei);
|
|
136
|
+
const valueWeiList = payments.map((p) => p.valueWei);
|
|
137
|
+
const extractProfit = shouldExtractProfit() && !erc20Quote;
|
|
121
138
|
const { totalProfit, remainingAmounts } = calculateBatchProfit(originalAmountsWei);
|
|
122
|
-
const actualAmountsWei = remainingAmounts;
|
|
123
|
-
|
|
139
|
+
const actualAmountsWei = extractProfit ? remainingAmounts : originalAmountsWei;
|
|
140
|
+
const actualValueWei = extractProfit ? remainingAmounts : valueWeiList;
|
|
124
141
|
const bribeAmount = getBribeAmount(config);
|
|
125
142
|
const needBribeTx = bribeAmount > 0n;
|
|
126
|
-
// ✅ 找出投入金额最多的钱包(作为贿赂和利润支付者)- 同步计算
|
|
127
143
|
let maxFundsIndex = 0;
|
|
128
144
|
let maxFunds = originalAmountsWei[0];
|
|
129
145
|
for (let i = 1; i < originalAmountsWei.length; i++) {
|
|
@@ -135,74 +151,53 @@ export async function fourBatchPrivateBuyMerkle(params) {
|
|
|
135
151
|
const tm2Contracts = wallets.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
|
|
136
152
|
const nonceManager = new NonceManager(provider);
|
|
137
153
|
const needProfitTx = extractProfit && totalProfit > 0n;
|
|
138
|
-
|
|
139
|
-
const payerNonceCount = 1 + (needBribeTx ? 1 : 0) + (needProfitTx ? 1 : 0);
|
|
140
|
-
// ✅ 优化:并行获取 gasPrice、nonces 和构建未签名交易
|
|
141
|
-
const [gasPrice, unsignedList, noncesResult] = await Promise.all([
|
|
154
|
+
const [gasPrice, unsignedList] = await Promise.all([
|
|
142
155
|
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
143
156
|
Promise.all(tm2Contracts.map((c, i) => c.buyTokenAMAP.populateTransaction(0n, tokenAddress, wallets[i].address, actualAmountsWei[i], 0n, {
|
|
144
|
-
value:
|
|
157
|
+
value: actualValueWei[i],
|
|
145
158
|
}))),
|
|
146
|
-
(async () => {
|
|
147
|
-
if (payerNonceCount > 1) {
|
|
148
|
-
// payer 需要多个连续 nonce
|
|
149
|
-
const payerNonces = await nonceManager.getNextNonceBatch(wallets[maxFundsIndex], payerNonceCount);
|
|
150
|
-
// 其他钱包各需要 1 个 nonce
|
|
151
|
-
const otherWallets = wallets.filter((_, i) => i !== maxFundsIndex);
|
|
152
|
-
const otherNonces = otherWallets.length > 0 ? await nonceManager.getNextNoncesForWallets(otherWallets) : [];
|
|
153
|
-
// 组装最终的 nonces 数组(保持原顺序)
|
|
154
|
-
const nonces = [];
|
|
155
|
-
let otherIdx = 0;
|
|
156
|
-
let nonceIdx = 0;
|
|
157
|
-
const bribeNonce = needBribeTx ? payerNonces[nonceIdx++] : undefined;
|
|
158
|
-
for (let i = 0; i < wallets.length; i++) {
|
|
159
|
-
if (i === maxFundsIndex) {
|
|
160
|
-
nonces.push(payerNonces[nonceIdx++]); // 买入交易
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
nonces.push(otherNonces[otherIdx++]);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
const profitNonce = needProfitTx ? payerNonces[nonceIdx] : undefined;
|
|
167
|
-
return { nonces, bribeNonce, profitNonce };
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
// 所有钱包各 1 个 nonce
|
|
171
|
-
const nonces = await nonceManager.getNextNoncesForWallets(wallets);
|
|
172
|
-
return { nonces, bribeNonce: undefined, profitNonce: undefined };
|
|
173
|
-
}
|
|
174
|
-
})(),
|
|
175
159
|
]);
|
|
176
|
-
const { nonces, bribeNonce, profitNonce } = noncesResult;
|
|
177
|
-
// ✅ 贿赂交易放在首位(提高 BlockRazor 打包优先级)
|
|
178
160
|
const signedTxs = [];
|
|
179
|
-
if (needBribeTx
|
|
180
|
-
|
|
161
|
+
if (needBribeTx) {
|
|
162
|
+
signedTxs.push(await wallets[maxFundsIndex].signTransaction({
|
|
181
163
|
to: BLOCKRAZOR_BUILDER_EOA,
|
|
182
164
|
value: bribeAmount,
|
|
183
|
-
nonce:
|
|
165
|
+
nonce: await nonceManager.getNextNonce(wallets[maxFundsIndex]),
|
|
184
166
|
gasPrice,
|
|
185
167
|
gasLimit: 21000n,
|
|
186
168
|
chainId: CHAIN_ID,
|
|
187
169
|
type: txType,
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
const quoteAddress = payments[0]?.quoteAddress;
|
|
173
|
+
if (erc20Quote && quoteAddress) {
|
|
174
|
+
const approves = await signQuoteApproveTxs({
|
|
175
|
+
wallets,
|
|
176
|
+
quoteAddress,
|
|
177
|
+
spender: tmAddr,
|
|
178
|
+
amounts: actualAmountsWei,
|
|
179
|
+
nonceManager,
|
|
180
|
+
gasPrice,
|
|
181
|
+
chainId: CHAIN_ID,
|
|
182
|
+
txType,
|
|
183
|
+
provider,
|
|
188
184
|
});
|
|
189
|
-
signedTxs.push(
|
|
185
|
+
signedTxs.push(...approves);
|
|
190
186
|
}
|
|
191
|
-
|
|
187
|
+
const buyNonces = await nonceManager.getNextNoncesForWallets(wallets);
|
|
192
188
|
const signedList = await Promise.all(unsignedList.map((unsigned, i) => wallets[i].signTransaction({
|
|
193
189
|
...unsigned,
|
|
194
190
|
from: wallets[i].address,
|
|
195
|
-
nonce:
|
|
191
|
+
nonce: buyNonces[i],
|
|
196
192
|
gasLimit: finalGasLimit,
|
|
197
193
|
gasPrice,
|
|
198
194
|
chainId: CHAIN_ID,
|
|
199
195
|
type: txType,
|
|
200
|
-
value:
|
|
196
|
+
value: actualValueWei[i],
|
|
201
197
|
})));
|
|
202
198
|
signedTxs.push(...signedList);
|
|
203
|
-
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
204
199
|
let profitHopWallets;
|
|
205
|
-
if (needProfitTx
|
|
200
|
+
if (needProfitTx) {
|
|
206
201
|
const profitHopResult = await buildProfitHopTransactions({
|
|
207
202
|
provider,
|
|
208
203
|
payerWallet: wallets[maxFundsIndex],
|
|
@@ -212,14 +207,14 @@ export async function fourBatchPrivateBuyMerkle(params) {
|
|
|
212
207
|
gasPrice,
|
|
213
208
|
chainId: CHAIN_ID,
|
|
214
209
|
txType,
|
|
215
|
-
startNonce:
|
|
210
|
+
startNonce: await nonceManager.getNextNonce(wallets[maxFundsIndex]),
|
|
216
211
|
});
|
|
217
212
|
signedTxs.push(...profitHopResult.signedTransactions);
|
|
218
|
-
profitHopWallets = profitHopResult.hopWallets;
|
|
213
|
+
profitHopWallets = profitHopResult.hopWallets;
|
|
219
214
|
}
|
|
220
215
|
nonceManager.clearTemp();
|
|
221
216
|
return {
|
|
222
217
|
signedTransactions: signedTxs,
|
|
223
|
-
profitHopWallets,
|
|
218
|
+
profitHopWallets,
|
|
224
219
|
};
|
|
225
220
|
}
|
|
@@ -8,4 +8,6 @@
|
|
|
8
8
|
* 对外 export 符号与路径保持不变。
|
|
9
9
|
*/
|
|
10
10
|
export { fourPrivateBuyMerkle, fourBatchPrivateBuyMerkle } from './buy.js';
|
|
11
|
+
export { openFourBatchBuyByBudgetMerkle } from './openfour-buy.js';
|
|
12
|
+
export type { OpenFourBatchBuySignParams } from './openfour-buy.js';
|
|
11
13
|
export { fourPrivateSellMerkle, fourBatchPrivateSellMerkle } from './sell.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FourBatchPrivateMerkleResult, FourSignConfig } from '../types/index.js';
|
|
2
|
+
export type OpenFourBatchBuySignParams = {
|
|
3
|
+
privateKeys: string[];
|
|
4
|
+
fundsList: string[];
|
|
5
|
+
tokenAddress: string;
|
|
6
|
+
quoteTokenAddress?: string;
|
|
7
|
+
quoteDecimals?: number;
|
|
8
|
+
config: FourSignConfig;
|
|
9
|
+
};
|
|
10
|
+
export declare function openFourBatchBuyByBudgetMerkle(params: OpenFourBatchBuySignParams): Promise<FourBatchPrivateMerkleResult>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenFour 发币后跟买:buyByBudget
|
|
3
|
+
* - quote = WBNB:msg.value 付 BNB
|
|
4
|
+
* - 其它 ERC20:approve Core + value=0
|
|
5
|
+
*/
|
|
6
|
+
import { Contract, Wallet, parseEther, parseUnits } from 'ethers';
|
|
7
|
+
import { getGasLimit } from '../../../core/gas/bundle-gas.js';
|
|
8
|
+
import { NonceManager, getOptimizedGasPrice } from '../../../utils/bundle-helpers.js';
|
|
9
|
+
import { CHAINS } from '../../../core/constants/index.js';
|
|
10
|
+
import { getTxType, getGasPriceConfig } from '../../config-helpers.js';
|
|
11
|
+
import { createSignProvider } from '../../../core/sign-context-helpers.js';
|
|
12
|
+
import { OPENFOUR_CORE_ABI } from '../../../abis/openfour.js';
|
|
13
|
+
import { loadOpenFourAddresses } from '../../../domains/openfour/index.js';
|
|
14
|
+
import { isFourErc20BuyQuote, resolveQuoteDecimals, signQuoteApproveTxs } from './buy-quote.js';
|
|
15
|
+
const CHAIN_ID = CHAINS.BSC.chainId;
|
|
16
|
+
export async function openFourBatchBuyByBudgetMerkle(params) {
|
|
17
|
+
const { privateKeys, fundsList, tokenAddress, config, quoteTokenAddress, quoteDecimals } = params;
|
|
18
|
+
if (privateKeys.length !== fundsList.length) {
|
|
19
|
+
throw new Error('privateKeys and fundsList length mismatch');
|
|
20
|
+
}
|
|
21
|
+
const provider = createSignProvider(config.rpcUrl, CHAIN_ID, 'BSC');
|
|
22
|
+
const wallets = privateKeys.map((k) => new Wallet(k, provider));
|
|
23
|
+
const txType = getTxType(config);
|
|
24
|
+
const gasLimit = getGasLimit(config, 900000);
|
|
25
|
+
const addrs = await loadOpenFourAddresses(provider);
|
|
26
|
+
const erc20Quote = isFourErc20BuyQuote(quoteTokenAddress);
|
|
27
|
+
const decimals = erc20Quote
|
|
28
|
+
? await resolveQuoteDecimals(provider, { quoteTokenAddress, quoteDecimals })
|
|
29
|
+
: 18;
|
|
30
|
+
const amountsWei = fundsList.map((a) => (erc20Quote ? parseUnits(a, decimals) : parseEther(a)));
|
|
31
|
+
const cores = wallets.map((w) => new Contract(addrs.core, OPENFOUR_CORE_ABI, w));
|
|
32
|
+
const nonceManager = new NonceManager(provider);
|
|
33
|
+
const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
|
|
34
|
+
const signedTxs = [];
|
|
35
|
+
if (erc20Quote && quoteTokenAddress) {
|
|
36
|
+
signedTxs.push(...(await signQuoteApproveTxs({
|
|
37
|
+
wallets,
|
|
38
|
+
quoteAddress: quoteTokenAddress,
|
|
39
|
+
spender: addrs.core,
|
|
40
|
+
amounts: amountsWei,
|
|
41
|
+
nonceManager,
|
|
42
|
+
gasPrice,
|
|
43
|
+
chainId: CHAIN_ID,
|
|
44
|
+
txType,
|
|
45
|
+
provider,
|
|
46
|
+
})));
|
|
47
|
+
}
|
|
48
|
+
const unsignedList = await Promise.all(cores.map((c, i) => c.buyByBudget.populateTransaction(tokenAddress, amountsWei[i], 0n, 0n, '0x', {
|
|
49
|
+
value: erc20Quote ? 0n : amountsWei[i],
|
|
50
|
+
})));
|
|
51
|
+
const nonces = await nonceManager.getNextNoncesForWallets(wallets);
|
|
52
|
+
const buys = await Promise.all(unsignedList.map((unsigned, i) => wallets[i].signTransaction({
|
|
53
|
+
...unsigned,
|
|
54
|
+
from: wallets[i].address,
|
|
55
|
+
nonce: nonces[i],
|
|
56
|
+
gasLimit,
|
|
57
|
+
gasPrice,
|
|
58
|
+
chainId: CHAIN_ID,
|
|
59
|
+
type: txType,
|
|
60
|
+
value: erc20Quote ? 0n : amountsWei[i],
|
|
61
|
+
})));
|
|
62
|
+
signedTxs.push(...buys);
|
|
63
|
+
nonceManager.clearTemp();
|
|
64
|
+
return { signedTransactions: signedTxs };
|
|
65
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GeneratedWallet } from '../../../utils/wallet.js';
|
|
2
2
|
import type { FourTokenTaxInfo } from '../../../core/clients/four.js';
|
|
3
|
+
import type { FourRaisedToken } from '../../../domains/four/raised-token.js';
|
|
3
4
|
import type { AmountLike } from '../../types/index.js';
|
|
4
5
|
import type { CommonBundleConfig } from '../../../utils/bundle-helpers.js';
|
|
5
6
|
export type { AmountLike };
|
|
@@ -105,6 +106,9 @@ export type FourCreateWithBundleBuyMerkleParams = {
|
|
|
105
106
|
feePlan?: boolean;
|
|
106
107
|
/** ✅ 税币配置(Tax Token, creatorType=5) */
|
|
107
108
|
tokenTaxInfo?: FourTokenTaxInfo;
|
|
109
|
+
/** 官网计价币 symbol,如 BNB / USDT / USD1 */
|
|
110
|
+
quoteSymbol?: string;
|
|
111
|
+
raisedToken?: FourRaisedToken;
|
|
108
112
|
};
|
|
109
113
|
config: FourBundleMerkleConfig;
|
|
110
114
|
};
|
|
@@ -128,6 +132,8 @@ export type FourCreateWithBundleBuySignParams = {
|
|
|
128
132
|
feePlan?: boolean;
|
|
129
133
|
/** ✅ 税币配置(Tax Token, creatorType=5) */
|
|
130
134
|
tokenTaxInfo?: FourTokenTaxInfo;
|
|
135
|
+
quoteSymbol?: string;
|
|
136
|
+
raisedToken?: FourRaisedToken;
|
|
131
137
|
};
|
|
132
138
|
config: FourSignConfig;
|
|
133
139
|
};
|
|
@@ -191,6 +197,9 @@ export type FourPrivateBuySignParams = FourPrivateSignBase & {
|
|
|
191
197
|
tokenAddress: string;
|
|
192
198
|
funds: string;
|
|
193
199
|
to?: string;
|
|
200
|
+
/** ERC20 计价跟买;不传则按 BNB `msg.value` */
|
|
201
|
+
quoteTokenAddress?: string;
|
|
202
|
+
quoteDecimals?: number;
|
|
194
203
|
};
|
|
195
204
|
/** ✅ 私有卖出参数(Merkle 版本 - 完整) */
|
|
196
205
|
export type FourPrivateSellMerkleParams = FourPrivateMerkleBase & {
|
|
@@ -213,12 +222,16 @@ export type FourBatchPrivateBuyMerkleParams = FourPrivateMerkleBase & {
|
|
|
213
222
|
privateKeys: string[];
|
|
214
223
|
fundsList: string[];
|
|
215
224
|
tokenAddress: string;
|
|
225
|
+
quoteTokenAddress?: string;
|
|
226
|
+
quoteDecimals?: number;
|
|
216
227
|
};
|
|
217
228
|
/** ✅ 批量私有购买参数(仅签名版本 - 精简) */
|
|
218
229
|
export type FourBatchPrivateBuySignParams = FourPrivateSignBase & {
|
|
219
230
|
privateKeys: string[];
|
|
220
231
|
fundsList: string[];
|
|
221
232
|
tokenAddress: string;
|
|
233
|
+
quoteTokenAddress?: string;
|
|
234
|
+
quoteDecimals?: number;
|
|
222
235
|
};
|
|
223
236
|
/** ✅ 批量私有卖出参数(Merkle 版本 - 完整) */
|
|
224
237
|
export type FourBatchPrivateSellMerkleParams = FourPrivateMerkleBase & {
|
|
@@ -16,6 +16,7 @@ export declare const BSC_ADDRESSES: {
|
|
|
16
16
|
readonly TokenManagerV1: "0xf7F823d0E790219dBf727bDb971837574655fCB0";
|
|
17
17
|
readonly TokenManagerV2: "0x342399a59943B5815849657Aa0e06D7058D9d5C6";
|
|
18
18
|
readonly TokenManagerHelper3: "0xF251F83e40a78868FcfA3FA4599Dad6494E46034";
|
|
19
|
+
readonly OpenFourRegistry: "0x912CEf0C3aE9Ab6eB3Ec87cab69371cFb317Ab94";
|
|
19
20
|
readonly FlapPortal: "0xe2cE6ab80874Fa9Fa2aAE65D277Dd6B8e65C9De0";
|
|
20
21
|
readonly PancakeV2Router: "0x10ED43C718714eb63d5aA57B78B54704E256024E";
|
|
21
22
|
readonly PancakeV2Factory: "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73";
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type FourRaisedToken, type FourTokenLabel } from '../../domains/four/raised-token.js';
|
|
2
|
+
import type { OpenFourCreateReq, OpenFourTemplate, OpenFourTemplateConfig } from '../../domains/openfour/types.js';
|
|
3
|
+
export type { FourRaisedToken, FourTokenLabel };
|
|
1
4
|
export type NetworkCode = 'BSC';
|
|
2
5
|
export type FourConfig = {
|
|
3
6
|
/**
|
|
@@ -43,7 +46,9 @@ export type LoginReq = {
|
|
|
43
46
|
* - recipientAddress: 接收者地址(不使用时传空字符串 "")
|
|
44
47
|
* - minSharing: 最低持仓分红门槛(ether 单位,须满足 d × 10^n, n≥5, 1≤d≤9)
|
|
45
48
|
*
|
|
46
|
-
* 约束:burnRate + divideRate + liquidityRate + recipientRate
|
|
49
|
+
* 约束:burnRate + divideRate + liquidityRate + recipientRate
|
|
50
|
+
* + giggleCharityRate + binanceCharityRate = 100
|
|
51
|
+
* 带 giggleCharityRate / binanceCharityRate 即为 TaxToken9(即使都是 0)
|
|
47
52
|
*/
|
|
48
53
|
export type FourTokenTaxInfo = {
|
|
49
54
|
feeRate: 1 | 3 | 5 | 10;
|
|
@@ -53,40 +58,37 @@ export type FourTokenTaxInfo = {
|
|
|
53
58
|
recipientRate: number;
|
|
54
59
|
recipientAddress: string;
|
|
55
60
|
minSharing: number;
|
|
61
|
+
giggleCharityRate?: number;
|
|
62
|
+
binanceCharityRate?: number;
|
|
56
63
|
};
|
|
57
|
-
export type
|
|
64
|
+
export type CreateTokenCustom = {
|
|
58
65
|
name: string;
|
|
59
66
|
shortName: string;
|
|
60
67
|
desc: string;
|
|
61
68
|
imgUrl: string;
|
|
62
69
|
launchTime: number;
|
|
63
|
-
label:
|
|
70
|
+
label: FourTokenLabel;
|
|
64
71
|
webUrl?: string;
|
|
65
72
|
twitterUrl?: string;
|
|
66
73
|
telegramUrl?: string;
|
|
67
74
|
preSale: string;
|
|
68
75
|
onlyMPC?: boolean;
|
|
69
|
-
/**
|
|
70
|
-
* AntiSniperFeeMode(开盘高税模式)
|
|
71
|
-
* - true: 启用动态手续费系统(开盘时高税,逐区块自动降低)
|
|
72
|
-
* - false: 不启用(默认)
|
|
73
|
-
*/
|
|
74
76
|
feePlan?: boolean;
|
|
75
|
-
/**
|
|
76
|
-
* 税币配置(Tax Token)
|
|
77
|
-
* - 提供此字段时创建税币(creatorType = 5)
|
|
78
|
-
* - 不提供或为 undefined 时创建普通代币
|
|
79
|
-
*/
|
|
80
77
|
tokenTaxInfo?: FourTokenTaxInfo;
|
|
78
|
+
};
|
|
79
|
+
export type CreateTokenReq = CreateTokenCustom & {
|
|
81
80
|
lpTradingFee: 0.0025;
|
|
82
|
-
symbol:
|
|
83
|
-
totalSupply:
|
|
84
|
-
raisedAmount:
|
|
85
|
-
saleRate:
|
|
81
|
+
symbol: string;
|
|
82
|
+
totalSupply: number;
|
|
83
|
+
raisedAmount: number;
|
|
84
|
+
saleRate: number;
|
|
86
85
|
reserveRate: 0;
|
|
87
86
|
funGroup: false;
|
|
88
87
|
clickFun: false;
|
|
88
|
+
/** 官网 /v1/public/config 条目,须原样提交,禁止自造内部字段 */
|
|
89
|
+
raisedToken?: FourRaisedToken;
|
|
89
90
|
};
|
|
91
|
+
export declare function buildCreateTokenReq(custom: CreateTokenCustom, raisedToken: FourRaisedToken): CreateTokenReq;
|
|
90
92
|
export type FourJsonValue = string | number | boolean | null | FourJsonValue[] | {
|
|
91
93
|
[key: string]: FourJsonValue;
|
|
92
94
|
};
|
|
@@ -137,11 +139,17 @@ export declare class FourClient {
|
|
|
137
139
|
private getFilenameFromBlob;
|
|
138
140
|
createToken(accessToken: string, req: CreateTokenReq): Promise<CreateTokenResp>;
|
|
139
141
|
getPublicConfig(): Promise<FourPublicConfig>;
|
|
142
|
+
listPublishedRaisedTokens(): Promise<FourRaisedToken[]>;
|
|
143
|
+
resolveRaisedToken(symbol?: string): Promise<FourRaisedToken>;
|
|
140
144
|
getTokenByAddress(address: string, accessToken?: string): Promise<FourTokenDetail>;
|
|
141
145
|
getTokensByAddresses(addresses: string[], accessToken?: string): Promise<(FourTokenDetail | {
|
|
142
146
|
address: string;
|
|
143
147
|
error: string;
|
|
144
148
|
})[]>;
|
|
145
149
|
getTokenById(id: string | number, accessToken?: string): Promise<FourTokenDetail>;
|
|
150
|
+
searchTokenTemplates(): Promise<OpenFourTemplate[]>;
|
|
151
|
+
listPublishedTokenTemplates(): Promise<OpenFourTemplate[]>;
|
|
152
|
+
getTokenTemplateConfig(templateId: number | string): Promise<OpenFourTemplateConfig[]>;
|
|
153
|
+
createOpenFourToken(accessToken: string, req: OpenFourCreateReq): Promise<CreateTokenResp>;
|
|
146
154
|
}
|
|
147
155
|
export declare function buildLoginMessage(nonce: string): string;
|