@clonegod/ttd-bsc-common 3.1.5 → 3.1.12

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.
@@ -1,12 +1,12 @@
1
1
  import { EnvArgs } from '@clonegod/ttd-core';
2
2
  export declare class BscEnvArgs extends EnvArgs {
3
- large_trade_threshold_usd: number;
4
3
  gas_price_gwei: number;
5
4
  gas_limit: number;
6
5
  tip_amount_gwei: number;
7
- tx_status_check_interval_mills: number;
8
- tx_cancel_timeout_ms: number;
9
- tx_cancel_gas_boost_factor: number;
6
+ send_tx_blockrazor_bundle: boolean;
7
+ send_tx_48club_bundle: boolean;
8
+ send_tx_48club_bundle_ws: boolean;
9
+ send_tx_blox_bundle_ws: boolean;
10
10
  constructor();
11
11
  print(moduleName?: string): void;
12
12
  }
@@ -3,34 +3,42 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BscEnvArgs = void 0;
4
4
  const ttd_core_1 = require("@clonegod/ttd-core");
5
5
  const BSC_KEYS = [
6
- 'large_trade_threshold_usd',
7
6
  'gas_price_gwei',
8
7
  'gas_limit',
9
8
  'tip_amount_gwei',
10
- 'tx_status_check_interval_mills',
11
- 'tx_cancel_timeout_ms',
12
- 'tx_cancel_gas_boost_factor',
9
+ 'send_tx_blockrazor_bundle',
10
+ 'send_tx_48club_bundle',
11
+ 'send_tx_48club_bundle_ws',
12
+ 'send_tx_blox_bundle_ws',
13
13
  ];
14
14
  (0, ttd_core_1.registerEnvVars)({
15
- large_trade_threshold_usd: { env: 'LARGE_TRADE_THRESHOLD_USD', type: 'number', default: 500, desc: '大额交易识别阈值(USD)' },
16
15
  gas_price_gwei: { env: 'GAS_PRICE_GWEI', type: 'number', default: 1, desc: '交易 gas 价格(Gwei)' },
17
16
  gas_limit: { env: 'GAS_LIMIT', type: 'number', default: 300000, desc: '交易 gas 上限' },
18
- tip_amount_gwei: { env: 'EOA_TIP_AMOUNT_GWEI', type: 'number', default: 10000, desc: 'Builder tip(Gwei)' },
19
- tx_status_check_interval_mills: { env: 'TX_STATUS_CHECK_INTERVAL_MILLS', type: 'number', default: 3000, desc: '交易状态检查间隔(ms)' },
20
- tx_cancel_timeout_ms: { env: 'TX_CANCEL_TIMEOUT_MS', type: 'number', default: 15000, desc: '交易取消超时(ms)' },
21
- tx_cancel_gas_boost_factor: { env: 'TX_CANCEL_GAS_PRICE_BOOST_FACTOR', type: 'number', default: 1.5, desc: '取消交易 gas 提升倍数' },
17
+ tip_amount_gwei: { env: 'TIP_AMOUNT_GWEI', type: 'number', default: 10000, desc: 'Builder tip(Gwei)' },
18
+ send_tx_blockrazor_bundle: { env: 'SEND_TX_BLOCKRAZOR_BUNDLE', type: 'boolean', default: false, desc: 'BlockRazor Bundle 开关' },
19
+ send_tx_48club_bundle: { env: 'SEND_TX_48CLUB_BUNDLE', type: 'boolean', default: false, desc: '48Club Bundle HTTP 开关' },
20
+ send_tx_48club_bundle_ws: { env: 'SEND_TX_48CLUB_BUNDLE_WS', type: 'boolean', default: false, desc: '48Club Bundle WS 开关' },
21
+ send_tx_blox_bundle_ws: { env: 'SEND_TX_BLOX_BUNDLE_WS', type: 'boolean', default: false, desc: 'BloxRoute Bundle WS 开关' },
22
+ stream_quote_ws_host: { env: 'STREAM_QUOTE_WS_HOST', type: 'string', default: '127.0.0.1', desc: 'stream-quote WS 地址' },
23
+ min_quote_interval_ms: { env: 'MIN_QUOTE_INTERVAL_MS', type: 'number', default: 10000, desc: '最小询价间隔(ms)' },
24
+ skip_price_feed_yynode: { env: 'SKIP_PRICE_FEED_YYNODE', type: 'boolean', default: false, desc: '跳过 YYNode PriceFeed' },
25
+ push_price_feed: { env: 'PUSH_PRICE_FEED', type: 'boolean', default: false, desc: 'PriceFeed 推送开关' },
26
+ need_block_time_info: { env: 'NEED_BLOCK_TIME_INFO', type: 'boolean', default: false, desc: '区块时间信息开关' },
27
+ tick_cache_neighboring_words: { env: 'TICK_CACHE_NEIGHBORING_WORDS', type: 'number', default: 2, desc: 'tick 预加载 words 数' },
28
+ tick_cache_ttl: { env: 'TICK_CACHE_TTL', type: 'number', default: 30000, desc: 'tick 缓存 TTL(ms)' },
29
+ tick_cache_min_update_interval: { env: 'TICK_CACHE_MIN_UPDATE_INTERVAL', type: 'number', default: 3000, desc: 'tick 最小刷新间隔(ms)' },
22
30
  });
23
31
  class BscEnvArgs extends ttd_core_1.EnvArgs {
24
32
  constructor() {
25
33
  super();
26
34
  const cfg = (0, ttd_core_1.loadEnvConfig)(BSC_KEYS);
27
- this.large_trade_threshold_usd = cfg.large_trade_threshold_usd;
28
35
  this.gas_price_gwei = cfg.gas_price_gwei;
29
36
  this.gas_limit = cfg.gas_limit;
30
37
  this.tip_amount_gwei = cfg.tip_amount_gwei;
31
- this.tx_status_check_interval_mills = cfg.tx_status_check_interval_mills;
32
- this.tx_cancel_timeout_ms = cfg.tx_cancel_timeout_ms;
33
- this.tx_cancel_gas_boost_factor = cfg.tx_cancel_gas_boost_factor;
38
+ this.send_tx_blockrazor_bundle = cfg.send_tx_blockrazor_bundle;
39
+ this.send_tx_48club_bundle = cfg.send_tx_48club_bundle;
40
+ this.send_tx_48club_bundle_ws = cfg.send_tx_48club_bundle_ws;
41
+ this.send_tx_blox_bundle_ws = cfg.send_tx_blox_bundle_ws;
34
42
  }
35
43
  print(moduleName) {
36
44
  super.print(moduleName);
package/dist/index.d.ts CHANGED
@@ -4,6 +4,5 @@ export * from './quote';
4
4
  export * from './trade';
5
5
  export * from './types';
6
6
  export * from './utils';
7
- export * from './redis';
8
7
  export * from './ws';
9
8
  export * from './send-tx';
package/dist/index.js CHANGED
@@ -20,6 +20,5 @@ __exportStar(require("./quote"), exports);
20
20
  __exportStar(require("./trade"), exports);
21
21
  __exportStar(require("./types"), exports);
22
22
  __exportStar(require("./utils"), exports);
23
- __exportStar(require("./redis"), exports);
24
23
  __exportStar(require("./ws"), exports);
25
24
  __exportStar(require("./send-tx"), exports);
@@ -3,7 +3,7 @@ import { ethers } from "ethers";
3
3
  import { EvmChainConfig } from "../types";
4
4
  import { CallerManager } from "./caller_manager";
5
5
  import { ITransactionSender } from "../send-tx";
6
- import { SimpleRedisClient } from "../redis";
6
+ import { RedisClient } from "@clonegod/ttd-core";
7
7
  export interface TradeConfig {
8
8
  vaultAddress: string;
9
9
  executorIds: Record<string, string>;
@@ -19,17 +19,21 @@ export declare abstract class AbstractDexTrade extends AbastrcatTrade {
19
19
  protected provider: any;
20
20
  protected transactionSender: ITransactionSender;
21
21
  protected chainConfig: EvmChainConfig;
22
- protected redisClient: SimpleRedisClient;
22
+ protected redisClient: RedisClient;
23
23
  protected tradeConfig: TradeConfig;
24
24
  protected vaultInterface: any;
25
25
  protected chainNameLower: string;
26
26
  constructor(appConfig: AppConfig);
27
- protected abstract initConfigs(): void;
27
+ protected initConfigs(): void;
28
28
  abstract encodeTradeData(context: TradeContext): TradeCalldata;
29
29
  init(transactionSender?: ITransactionSender): Promise<void>;
30
30
  execute(context: TradeContext): Promise<string>;
31
31
  private scanCallerFiles;
32
- protected getGasPriceGwei(context: TradeContext): string;
32
+ protected buildGasFields(context: TradeContext): {
33
+ mainGasFields: any;
34
+ tipGasPriceGwei: string;
35
+ };
36
+ protected getLegacyGasPriceGwei(context: TradeContext): string;
33
37
  protected getBuilderTipAmoutGwei(context: TradeContext): string;
34
38
  protected buildTipTransferTx(to: string, transfer_amount_gwei: string, gas_price_gwei: string, nonce: number, wallet: ethers.Wallet): Promise<string>;
35
39
  protected determineInputOutputTokens(order_msg: any, pool_info: any): {
@@ -42,10 +42,11 @@ const ttd_core_1 = require("@clonegod/ttd-core");
42
42
  const logger = (0, ttd_core_1.createLogger)(__filename);
43
43
  const fs = __importStar(require("fs"));
44
44
  const path = __importStar(require("path"));
45
+ const constants_1 = require("../common/constants");
45
46
  const caller_manager_1 = require("./caller_manager");
46
47
  const send_tx_1 = require("../send-tx");
47
48
  const base_tx_result_checker_1 = require("./check/base_tx_result_checker");
48
- const redis_1 = require("../redis");
49
+ const ttd_core_2 = require("@clonegod/ttd-core");
49
50
  const trade_direction_1 = require("../utils/trade_direction");
50
51
  const ethers_compat_1 = require("../utils/ethers_compat");
51
52
  const fast_signer_1 = require("../utils/fast_signer");
@@ -79,9 +80,30 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
79
80
  this.appConfig = appConfig;
80
81
  this.initConfigs();
81
82
  this.chainNameLower = this.appConfig.env_args.chain_id.toLowerCase();
82
- this.redisClient = new redis_1.SimpleRedisClient(`${this.chainNameLower}:tx`);
83
+ this.redisClient = new ttd_core_2.RedisClient(`${this.chainNameLower}:tx`);
83
84
  this.vaultInterface = new ethers_compat_1.ethersCompat.Interface(VAULT_ABI);
84
85
  }
86
+ initConfigs() {
87
+ const env = this.appConfig.env_args;
88
+ this.chainConfig = {
89
+ chainId: 56,
90
+ nativeCurrency: 'BNB',
91
+ wrappedNativeCurrencyAddress: constants_1.WBNB_ADDRESS,
92
+ chainName: 'Binance Smart Chain',
93
+ rpcEndpoint: env.rpc_endpoint,
94
+ blockConfirmations: 12,
95
+ gasOptions: {
96
+ gasLimit: env.gas_limit,
97
+ defaultGasPriceGwei: env.gas_price_gwei,
98
+ maxGasPriceGwei: 10,
99
+ maxFeePerGasGwei: 10,
100
+ maxPriorityFeePerGasGwei: 3,
101
+ defaultTipAmountGwei: env.tip_amount_gwei,
102
+ maxTipAmountGwei: 500000,
103
+ }
104
+ };
105
+ this.tradeConfig = buildTradeConfig();
106
+ }
85
107
  async init(transactionSender) {
86
108
  (0, fast_signer_1.patchEthersV5Signer)();
87
109
  this.provider = new ethers_compat_1.ethersCompat.JsonRpcProvider(this.chainConfig.rpcEndpoint);
@@ -142,8 +164,7 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
142
164
  trace.mark('encode');
143
165
  const deadline = Math.floor(Date.now() / 1000) + 60;
144
166
  const vaultCalldata = this.vaultInterface.encodeFunctionData('delegatecallExecutorToTrade', [executorId, data, deadline]);
145
- const gasPriceGwei = this.getGasPriceGwei(context);
146
- const realGasPriceGwei = Math.min(Number(gasPriceGwei), this.chainConfig.gasOptions.maxGasPriceGwei).toString();
167
+ const { mainGasFields, tipGasPriceGwei } = this.buildGasFields(context);
147
168
  const tipNonce = nonce + 1;
148
169
  const transfer_amount_gwei = this.getBuilderTipAmoutGwei(context);
149
170
  context.ui_tip_amount = new decimal_js_1.default(transfer_amount_gwei).div(10 ** 9).toNumber();
@@ -151,19 +172,22 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
151
172
  to: this.tradeConfig.vaultAddress,
152
173
  data: vaultCalldata,
153
174
  gasLimit: this.chainConfig.gasOptions.gasLimit,
154
- gasPrice: ethers_compat_1.ethersCompat.parseUnits(realGasPriceGwei, 'gwei'),
175
+ ...mainGasFields,
155
176
  nonce,
156
177
  chainId: this.chainConfig.chainId,
157
178
  value: 0,
158
179
  };
159
- const builderAddresses = [
160
- send_tx_1.BSC_EOA_ADDRESS.BLOCKRAZOR,
161
- send_tx_1.BSC_EOA_ADDRESS._48CLUB,
162
- send_tx_1.BSC_EOA_ADDRESS.BLXR,
163
- ];
180
+ const env = this.appConfig.env_args;
181
+ const builderAddresses = [];
182
+ if (env.send_tx_blockrazor_bundle)
183
+ builderAddresses.push(send_tx_1.BSC_EOA_ADDRESS.BLOCKRAZOR);
184
+ if (env.send_tx_48club_bundle || env.send_tx_48club_bundle_ws)
185
+ builderAddresses.push(send_tx_1.BSC_EOA_ADDRESS._48CLUB);
186
+ if (env.send_tx_blox_bundle_ws)
187
+ builderAddresses.push(send_tx_1.BSC_EOA_ADDRESS.BLXR);
164
188
  const [rawMainTx, ...rawTips] = await Promise.all([
165
189
  caller.signTransaction(mainTx),
166
- ...builderAddresses.map(addr => this.buildTipTransferTx(addr, transfer_amount_gwei, realGasPriceGwei, tipNonce, caller)),
190
+ ...builderAddresses.map(addr => this.buildTipTransferTx(addr, transfer_amount_gwei, tipGasPriceGwei, tipNonce, caller)),
167
191
  ]);
168
192
  trace.mark('sign');
169
193
  const ensure0x = (tx) => tx.startsWith('0x') ? tx : `0x${tx}`;
@@ -174,7 +198,7 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
174
198
  builderAddresses.forEach((addr, idx) => tipTxMap.set(addr, signedTips[idx]));
175
199
  trace.set('txid', txid);
176
200
  trace.set('nonce', nonce);
177
- trace.set('gas', realGasPriceGwei);
201
+ trace.set('gasType', mainGasFields.type === 2 ? 'EIP1559' : 'Legacy');
178
202
  trace.set('tip', transfer_amount_gwei);
179
203
  const only_bundle = order_msg.is_dex_maker;
180
204
  await this.transactionSender.sendTransaction(signedMainTx, tipTxMap, order_trace_id, pair, only_bundle, trace);
@@ -228,7 +252,32 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
228
252
  .sort();
229
253
  return files.map(f => f.replace('.json', ''));
230
254
  }
231
- getGasPriceGwei(context) {
255
+ buildGasFields(context) {
256
+ const strategy = context.trade_runtime.settings.strategy;
257
+ const opts = this.chainConfig.gasOptions;
258
+ const legacyGasPrice = this.getLegacyGasPriceGwei(context);
259
+ const tipGasPriceGwei = Math.min(Number(legacyGasPrice), opts.maxGasPriceGwei).toString();
260
+ if (strategy.evm_tx_type === 2) {
261
+ const maxFee = Math.min(strategy.evm_max_fee_per_gas_gwei || opts.maxFeePerGasGwei, opts.maxFeePerGasGwei);
262
+ const maxPriority = Math.min(strategy.evm_max_priority_fee_per_gas_gwei ?? 0, opts.maxPriorityFeePerGasGwei);
263
+ return {
264
+ mainGasFields: {
265
+ type: 2,
266
+ maxFeePerGas: ethers_compat_1.ethersCompat.parseUnits(maxFee.toString(), 'gwei'),
267
+ maxPriorityFeePerGas: ethers_compat_1.ethersCompat.parseUnits(maxPriority.toString(), 'gwei'),
268
+ },
269
+ tipGasPriceGwei,
270
+ };
271
+ }
272
+ const realGasPrice = Math.min(Number(legacyGasPrice), opts.maxGasPriceGwei).toString();
273
+ return {
274
+ mainGasFields: {
275
+ gasPrice: ethers_compat_1.ethersCompat.parseUnits(realGasPrice, 'gwei'),
276
+ },
277
+ tipGasPriceGwei,
278
+ };
279
+ }
280
+ getLegacyGasPriceGwei(context) {
232
281
  let { evm_gas_price_gwei } = context.trade_runtime.settings.strategy;
233
282
  if (!evm_gas_price_gwei || evm_gas_price_gwei <= 0) {
234
283
  evm_gas_price_gwei = this.chainConfig.gasOptions.defaultGasPriceGwei;
@@ -4,7 +4,7 @@ exports.CallerManager = void 0;
4
4
  const dist_1 = require("@clonegod/ttd-core/dist");
5
5
  const logger = (0, dist_1.createLogger)(__filename);
6
6
  const ethers_1 = require("ethers");
7
- const redis_1 = require("../redis");
7
+ const ttd_core_1 = require("@clonegod/ttd-core");
8
8
  const CALLER_NONCE_KEY = 'caller:nonce';
9
9
  const CALLER_LAST_USED_KEY = 'caller:last_used';
10
10
  const VAULT_CALLERS_KEY = 'vault:callers';
@@ -12,13 +12,13 @@ class CallerManager {
12
12
  constructor(config) {
13
13
  this.callers = [];
14
14
  this.config = config;
15
- this.redis = new redis_1.SimpleRedisClient(`${config.chainName}:caller`);
15
+ this.redis = new ttd_core_1.RedisClient(`${config.chainName}:caller`);
16
16
  }
17
17
  async init() {
18
18
  const walletInfos = (0, dist_1.load_wallet_multi)(this.config.callerGroupIds, false);
19
19
  const allWallets = walletInfos.map(info => new ethers_1.ethers.Wallet(info.private_key, this.config.provider));
20
20
  const vaultCallersKey = `${this.config.chainName}:${VAULT_CALLERS_KEY}`;
21
- const rawJson = await this.redis.hgetvalue(vaultCallersKey, this.config.groupId);
21
+ const rawJson = await this.redis.hget(vaultCallersKey, this.config.groupId);
22
22
  let allowedAddresses = [];
23
23
  if (rawJson) {
24
24
  try {
@@ -96,13 +96,13 @@ class CallerManager {
96
96
  }
97
97
  }
98
98
  callerAddr = addresses[selectedIdx];
99
- await this.redis.hsetValue(lastUsedKey, callerAddr, String(Date.now()), 24 * 60 * 60);
99
+ await this.redis.hset(lastUsedKey, callerAddr, String(Date.now()), 24 * 60 * 60);
100
100
  }
101
101
  finally {
102
102
  this.redis.releaseLock(lockKey, lockValue).catch(() => { });
103
103
  }
104
104
  const nonceKey = this.getNonceRedisKey();
105
- const nonceStr = await this.redis.hgetvalue(nonceKey, callerAddr);
105
+ const nonceStr = await this.redis.hget(nonceKey, callerAddr);
106
106
  if (nonceStr === null || nonceStr === undefined) {
107
107
  throw new Error(`Caller ${callerAddr} nonce not found in Redis, stream-trade may not be running`);
108
108
  }
@@ -140,7 +140,7 @@ class CallerManager {
140
140
  }
141
141
  async getNonce(address) {
142
142
  const nonceKey = this.getNonceRedisKey();
143
- const val = await this.redis.hgetvalue(nonceKey, address.toLowerCase());
143
+ const val = await this.redis.hget(nonceKey, address.toLowerCase());
144
144
  if (val !== null && val !== undefined) {
145
145
  return parseInt(val, 10);
146
146
  }
@@ -148,7 +148,7 @@ class CallerManager {
148
148
  }
149
149
  async setNonce(address, nonce) {
150
150
  const nonceKey = this.getNonceRedisKey();
151
- await this.redis.hsetValue(nonceKey, address.toLowerCase(), String(nonce), 24 * 60 * 60);
151
+ await this.redis.hset(nonceKey, address.toLowerCase(), String(nonce), 24 * 60 * 60);
152
152
  }
153
153
  }
154
154
  exports.CallerManager = CallerManager;
@@ -2,11 +2,10 @@ export interface GasOptions {
2
2
  gasLimit: number;
3
3
  defaultGasPriceGwei: number;
4
4
  maxGasPriceGwei: number;
5
+ maxFeePerGasGwei: number;
6
+ maxPriorityFeePerGasGwei: number;
5
7
  defaultTipAmountGwei: number;
6
8
  maxTipAmountGwei: number;
7
- txStatusCheckIntervalMills: number;
8
- txCancelTimeoutMills: number;
9
- txCancelGasBoostFactor: number;
10
9
  }
11
10
  export interface EvmChainConfig {
12
11
  chainId: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-bsc-common",
3
- "version": "3.1.5",
3
+ "version": "3.1.12",
4
4
  "description": "BSC common library",
5
5
  "license": "UNLICENSED",
6
6
  "main": "dist/index.js",
@@ -14,7 +14,7 @@
14
14
  "push": "npm run build && npm publish"
15
15
  },
16
16
  "dependencies": {
17
- "@clonegod/ttd-core": "^3.1.6",
17
+ "@clonegod/ttd-core": "3.1.12",
18
18
  "axios": "^1.12.0",
19
19
  "dotenv": "^16.4.7",
20
20
  "ethers": "^5.8.0",