@clonegod/ttd-sol-common 2.0.49 → 2.0.50
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/trade/tx_builder.d.ts +1 -0
- package/dist/trade/tx_builder.js +54 -3
- package/package.json +1 -1
- package/src/trade/tx_builder.ts +96 -13
|
@@ -13,6 +13,7 @@ export declare class SolTransactionBuilder {
|
|
|
13
13
|
init(): Promise<void>;
|
|
14
14
|
private handleBlockUpdateEvent;
|
|
15
15
|
private getPreInstructions;
|
|
16
|
+
private createComputeUnitLimitWithJitoDontFront;
|
|
16
17
|
private getPostInstructions;
|
|
17
18
|
buildTransactionForSwap(context: TradeContext, swapInstructions: TransactionInstruction[]): Transaction;
|
|
18
19
|
buildTransactionForTipJito(context: TradeContext): Transaction;
|
package/dist/trade/tx_builder.js
CHANGED
|
@@ -7,6 +7,46 @@ const common_1 = require("../common");
|
|
|
7
7
|
const helius_1 = require("./send/helius");
|
|
8
8
|
const jito_1 = require("./send/jito");
|
|
9
9
|
const jito_tip_wallets_1 = require("./jito_tip_wallets");
|
|
10
|
+
const jitodontfrontAccounts = [
|
|
11
|
+
'jitodontfront111111111111111111111111111111',
|
|
12
|
+
'jitodontfront111111111111111111111111111123',
|
|
13
|
+
'jitodontfront111111111111234565432123456782',
|
|
14
|
+
'jitodontfront111111111111111111111111111118',
|
|
15
|
+
'jitodontfront111111111111111111111111111183',
|
|
16
|
+
'jitodontfront11111111111111111111111111111o',
|
|
17
|
+
'jitodontfront1111111111111111111111111111of',
|
|
18
|
+
'jitodontfront111111111111111111111111111116',
|
|
19
|
+
'jitodontfront11111111111111111111111111116b',
|
|
20
|
+
'jitodontfront11111111111111111111111111111a',
|
|
21
|
+
'jitodontfront1111111111111111111111111111aJ',
|
|
22
|
+
'jitodontfront11111111111111111111111111111J',
|
|
23
|
+
'jitodontfront1111111111111111111111111111JR',
|
|
24
|
+
'jitodontfront11111111111111111111111111111U',
|
|
25
|
+
'jitodontfront1111111111111111111111111111UU',
|
|
26
|
+
'jitodontfront11111111111111111111111111111g',
|
|
27
|
+
'jitodontfront1111111111111111111111111111gt',
|
|
28
|
+
'jitodontfront11111111111111111111111111111F',
|
|
29
|
+
'jitodontfront1111111111111111111111111111Ff',
|
|
30
|
+
'jitodontfront11111111111111111111111111111v',
|
|
31
|
+
'jitodontfront1111111111111111111111111111vw',
|
|
32
|
+
'jitodontfront1111111111111111111111111111UA',
|
|
33
|
+
'jitodontfront111111111111111111111111111bcv',
|
|
34
|
+
'jitodontfront111111111111111111111111111Svm',
|
|
35
|
+
'jitodontfront111111111111111111111111111Zj2',
|
|
36
|
+
'jitodontfront111111111111111111111111111wja',
|
|
37
|
+
'jitodontfront111111111111111111111111111r3j',
|
|
38
|
+
'jitodontfront111111111111111111111111111LAG',
|
|
39
|
+
'jitodontfront111111111111111111111111111iej',
|
|
40
|
+
'jitodontfront111111111111111111111111111mxb',
|
|
41
|
+
'jitodontfront111111111111111111111111111m9D',
|
|
42
|
+
'jitodontfront111111111111111111111111111rjQ',
|
|
43
|
+
'jitodontfront1111111111111111111111111111wP',
|
|
44
|
+
'jitodontfront111111111111234565432123456RX5',
|
|
45
|
+
];
|
|
46
|
+
function getJitoDontFrontAccount() {
|
|
47
|
+
const randomIndex = Math.floor(Math.random() * jitodontfrontAccounts.length);
|
|
48
|
+
return new web3_js_1.PublicKey(jitodontfrontAccounts[randomIndex]);
|
|
49
|
+
}
|
|
10
50
|
class SolTransactionBuilder {
|
|
11
51
|
constructor(appConfig) {
|
|
12
52
|
this.appConfig = appConfig;
|
|
@@ -28,14 +68,25 @@ class SolTransactionBuilder {
|
|
|
28
68
|
const cu_limit = context.pool_info.cu_limit || 600000;
|
|
29
69
|
const sol_priority_fee_lamports = context.trade_runtime.settings.strategy.sol_priority_fee;
|
|
30
70
|
const priorityFeeMicroLamports = Math.floor((sol_priority_fee_lamports * common_1.LAMPORTS_PER_MICRO_LAMPORTS) / cu_limit);
|
|
31
|
-
const computeBudgetInstruction =
|
|
32
|
-
units: cu_limit,
|
|
33
|
-
});
|
|
71
|
+
const computeBudgetInstruction = this.createComputeUnitLimitWithJitoDontFront(cu_limit);
|
|
34
72
|
const priorityFeeInstruction = web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
35
73
|
microLamports: priorityFeeMicroLamports,
|
|
36
74
|
});
|
|
37
75
|
return [computeBudgetInstruction, priorityFeeInstruction];
|
|
38
76
|
}
|
|
77
|
+
createComputeUnitLimitWithJitoDontFront(units) {
|
|
78
|
+
const jitoDontFrontAccount = getJitoDontFrontAccount();
|
|
79
|
+
const data = Buffer.alloc(5);
|
|
80
|
+
data.writeUInt8(2, 0);
|
|
81
|
+
data.writeUInt32LE(units, 1);
|
|
82
|
+
return new web3_js_1.TransactionInstruction({
|
|
83
|
+
keys: [
|
|
84
|
+
{ pubkey: jitoDontFrontAccount, isSigner: false, isWritable: false },
|
|
85
|
+
],
|
|
86
|
+
programId: web3_js_1.ComputeBudgetProgram.programId,
|
|
87
|
+
data: data,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
39
90
|
getPostInstructions(context) {
|
|
40
91
|
return [];
|
|
41
92
|
}
|
package/package.json
CHANGED
package/src/trade/tx_builder.ts
CHANGED
|
@@ -7,6 +7,61 @@ import { HELIUS_TIP_ACCOUNTS } from "./send/helius";
|
|
|
7
7
|
import { getJitoTipAccount } from "./send/jito";
|
|
8
8
|
import { JitoTipWalletManager } from "./jito_tip_wallets";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Jito Sandwich Mitigation: jitodontfront 账户
|
|
12
|
+
* 用于防止三明治攻击,包含此账户的交易必须在 bundle 的第一个位置(索引 0)
|
|
13
|
+
* 参考: https://docs.jito.wtf/lowlatencytxnsend/#sandwich-mitigation
|
|
14
|
+
*
|
|
15
|
+
* 重要说明:
|
|
16
|
+
* 1. 账户不需要在链上存在,但必须是有效的 pubkey
|
|
17
|
+
* 2. 账户应标记为只读(isWritable: false)以优化落地速度
|
|
18
|
+
* 3. (可选)可以使用唯一的 jitodontfront 变体用于应用程序
|
|
19
|
+
*
|
|
20
|
+
* 可以通过环境变量 JITO_DONT_FRONT_ACCOUNT 自定义账户,否则从默认列表中随机选择
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const jitodontfrontAccounts = [
|
|
24
|
+
'jitodontfront111111111111111111111111111111',
|
|
25
|
+
'jitodontfront111111111111111111111111111123',
|
|
26
|
+
'jitodontfront111111111111234565432123456782',
|
|
27
|
+
'jitodontfront111111111111111111111111111118',
|
|
28
|
+
'jitodontfront111111111111111111111111111183',
|
|
29
|
+
'jitodontfront11111111111111111111111111111o',
|
|
30
|
+
'jitodontfront1111111111111111111111111111of',
|
|
31
|
+
'jitodontfront111111111111111111111111111116',
|
|
32
|
+
'jitodontfront11111111111111111111111111116b',
|
|
33
|
+
'jitodontfront11111111111111111111111111111a',
|
|
34
|
+
'jitodontfront1111111111111111111111111111aJ',
|
|
35
|
+
'jitodontfront11111111111111111111111111111J',
|
|
36
|
+
'jitodontfront1111111111111111111111111111JR',
|
|
37
|
+
'jitodontfront11111111111111111111111111111U',
|
|
38
|
+
'jitodontfront1111111111111111111111111111UU',
|
|
39
|
+
'jitodontfront11111111111111111111111111111g',
|
|
40
|
+
'jitodontfront1111111111111111111111111111gt',
|
|
41
|
+
'jitodontfront11111111111111111111111111111F',
|
|
42
|
+
'jitodontfront1111111111111111111111111111Ff',
|
|
43
|
+
'jitodontfront11111111111111111111111111111v',
|
|
44
|
+
'jitodontfront1111111111111111111111111111vw',
|
|
45
|
+
'jitodontfront1111111111111111111111111111UA',
|
|
46
|
+
'jitodontfront111111111111111111111111111bcv',
|
|
47
|
+
'jitodontfront111111111111111111111111111Svm',
|
|
48
|
+
'jitodontfront111111111111111111111111111Zj2',
|
|
49
|
+
'jitodontfront111111111111111111111111111wja',
|
|
50
|
+
'jitodontfront111111111111111111111111111r3j',
|
|
51
|
+
'jitodontfront111111111111111111111111111LAG',
|
|
52
|
+
'jitodontfront111111111111111111111111111iej',
|
|
53
|
+
'jitodontfront111111111111111111111111111mxb',
|
|
54
|
+
'jitodontfront111111111111111111111111111m9D',
|
|
55
|
+
'jitodontfront111111111111111111111111111rjQ',
|
|
56
|
+
'jitodontfront1111111111111111111111111111wP',
|
|
57
|
+
'jitodontfront111111111111234565432123456RX5',
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
function getJitoDontFrontAccount(): PublicKey {
|
|
61
|
+
const randomIndex = Math.floor(Math.random() * jitodontfrontAccounts.length);
|
|
62
|
+
return new PublicKey(jitodontfrontAccounts[randomIndex]);
|
|
63
|
+
}
|
|
64
|
+
|
|
10
65
|
|
|
11
66
|
export class SolTransactionBuilder {
|
|
12
67
|
appConfig: SolanaTradeAppConfig
|
|
@@ -47,10 +102,8 @@ export class SolTransactionBuilder {
|
|
|
47
102
|
const priorityFeeMicroLamports = Math.floor((sol_priority_fee_lamports * LAMPORTS_PER_MICRO_LAMPORTS) / cu_limit)
|
|
48
103
|
// console.log('getPreInstructions', { cu_limit, sol_priority_fee_lamports, priorityFeeMicroLamports, })
|
|
49
104
|
|
|
50
|
-
// set compute budget instruction
|
|
51
|
-
const computeBudgetInstruction =
|
|
52
|
-
units: cu_limit,
|
|
53
|
-
})
|
|
105
|
+
// set compute budget instruction with jitodontfront
|
|
106
|
+
const computeBudgetInstruction = this.createComputeUnitLimitWithJitoDontFront(cu_limit)
|
|
54
107
|
|
|
55
108
|
// set priority fee instruction
|
|
56
109
|
const priorityFeeInstruction = ComputeBudgetProgram.setComputeUnitPrice({
|
|
@@ -60,7 +113,37 @@ export class SolTransactionBuilder {
|
|
|
60
113
|
return [computeBudgetInstruction, priorityFeeInstruction]
|
|
61
114
|
}
|
|
62
115
|
|
|
63
|
-
|
|
116
|
+
/**
|
|
117
|
+
* 创建带有 jitodontfront 账户的 SetComputeUnitLimit 指令
|
|
118
|
+
* 将 jitodontfront 账户直接添加到 Compute Budget 指令中,用于防止三明治攻击
|
|
119
|
+
* 参考:
|
|
120
|
+
* - https://docs.jito.wtf/lowlatencytxnsend/#sandwich-mitigation
|
|
121
|
+
*
|
|
122
|
+
* 重要说明:
|
|
123
|
+
* 1. 包含 jitodontfront 账户的交易必须在 bundle 的第一个位置(索引 0)
|
|
124
|
+
* 2. 账户标记为只读(isWritable: false)以优化落地速度
|
|
125
|
+
* 3. 账户不需要在链上存在,但必须是有效的 pubkey
|
|
126
|
+
* 4. (可选)可以通过环境变量 JITO_DONT_FRONT_ACCOUNT 使用唯一的变体
|
|
127
|
+
*/
|
|
128
|
+
private createComputeUnitLimitWithJitoDontFront(units: number): TransactionInstruction {
|
|
129
|
+
const jitoDontFrontAccount = getJitoDontFrontAccount();
|
|
130
|
+
|
|
131
|
+
// 构造 Compute Budget SetComputeUnitLimit 指令数据
|
|
132
|
+
// 1 字节鉴别符(2 表示 SetComputeUnitLimit)+ 4 字节 units(小端序)
|
|
133
|
+
const data = Buffer.alloc(5);
|
|
134
|
+
data.writeUInt8(2, 0); // 鉴别符:2 表示 SetComputeUnitLimit
|
|
135
|
+
data.writeUInt32LE(units, 1); // 设置计算单元(小端序)
|
|
136
|
+
|
|
137
|
+
return new TransactionInstruction({
|
|
138
|
+
keys: [
|
|
139
|
+
{ pubkey: jitoDontFrontAccount, isSigner: false, isWritable: false }, // jitodontfront 账户,标记为只读
|
|
140
|
+
],
|
|
141
|
+
programId: ComputeBudgetProgram.programId, // Compute Budget 程序 ID
|
|
142
|
+
data: data,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
64
147
|
// post-instructions
|
|
65
148
|
private getPostInstructions(context: TradeContext): TransactionInstruction[] {
|
|
66
149
|
return []
|
|
@@ -87,21 +170,21 @@ export class SolTransactionBuilder {
|
|
|
87
170
|
swapTx.lastValidBlockHeight = this.recentBlockheight + max_block_offset
|
|
88
171
|
swapTx.feePayer = this.keypair.publicKey
|
|
89
172
|
|
|
90
|
-
const {sol_bundle_only, sol_tip_fee} = context.trade_runtime.settings.strategy
|
|
173
|
+
const { sol_bundle_only, sol_tip_fee } = context.trade_runtime.settings.strategy
|
|
91
174
|
|
|
92
175
|
// sol_bundle_only = false, 使用 Helius Sender
|
|
93
176
|
// sol_bundle_only = true, 使用 Jito Bundle - 不需要给Helius小费
|
|
94
|
-
if(!sol_bundle_only) {
|
|
177
|
+
if (!sol_bundle_only) {
|
|
95
178
|
// 使用 Helius Sender:
|
|
96
179
|
// 1、swqos_only: 至少 5000 lamports 小费
|
|
97
180
|
// -> transaction must send a tip of at least 5000 lamports to one of the following Helius wallets: [xxx, ...]
|
|
98
181
|
// 2、swqos + jito: 至少 0.0002 SOL 小费 -> lamports = 0.0002 * LAMPORTS_PER_SOL
|
|
99
182
|
// -> Requires minimum 0.0002 SOL tip.
|
|
100
183
|
let tip_lamports = sol_tip_fee
|
|
101
|
-
if(tip_lamports < 5000) {
|
|
184
|
+
if (tip_lamports < 5000) {
|
|
102
185
|
tip_lamports = 5000
|
|
103
186
|
}
|
|
104
|
-
if(tip_lamports > 300000) {
|
|
187
|
+
if (tip_lamports > 300000) {
|
|
105
188
|
tip_lamports = 300000
|
|
106
189
|
}
|
|
107
190
|
let tip_instruction = SystemProgram.transfer({
|
|
@@ -127,19 +210,19 @@ export class SolTransactionBuilder {
|
|
|
127
210
|
const max_block_offset = context.trade_runtime.settings.strategy.max_block_offset
|
|
128
211
|
|
|
129
212
|
let tipPayer = this.jitoTipWalletManager.getNextWallet(groupId)
|
|
130
|
-
if(!tipPayer) {
|
|
213
|
+
if (!tipPayer) {
|
|
131
214
|
tipPayer = this.keypair
|
|
132
215
|
}
|
|
133
216
|
|
|
134
217
|
let tipAccount = getJitoTipAccount()
|
|
135
218
|
let tip_lamports = context.trade_runtime.settings.strategy.sol_tip_fee
|
|
136
|
-
if(tip_lamports < 5000) {
|
|
219
|
+
if (tip_lamports < 5000) {
|
|
137
220
|
tip_lamports = 5000
|
|
138
221
|
}
|
|
139
|
-
if(tip_lamports > 300000) {
|
|
222
|
+
if (tip_lamports > 300000) {
|
|
140
223
|
tip_lamports = 300000
|
|
141
224
|
}
|
|
142
|
-
|
|
225
|
+
|
|
143
226
|
const jitoTipTx = new Transaction();
|
|
144
227
|
jitoTipTx.add(
|
|
145
228
|
SystemProgram.transfer({
|