@clonegod/ttd-bsc-send-tx 2.0.4 → 2.0.6

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/.env.example ADDED
@@ -0,0 +1,40 @@
1
+ APP_NAME=send-tx
2
+
3
+ CHAIN_ID=BSC
4
+
5
+ REDIS_HOST=127.0.0.1
6
+ REDIS_PORT=6379
7
+
8
+ LOG_LEVEL=INFO
9
+ LOG_DEPTH=4
10
+
11
+ # WS client(trade 进程连 send-tx server 用)
12
+ SEND_TX_WS_HOST=127.0.0.1
13
+
14
+ # WS server 开关
15
+ SEND_TX_48CLUB_WS=false
16
+ SEND_TX_BLOXROUTE_WS=false
17
+
18
+ # HTTP providers
19
+ SEND_TX_DEFAULT_RPC=false
20
+ SEND_TX_BLOCKRAZOR_PRIVATE=false
21
+ SEND_TX_BLOCKRAZOR_BUNDLE=false
22
+ SEND_TX_48CLUB_PRIVATE=false
23
+ SEND_TX_48CLUB_BUNDLE=false
24
+ SEND_TX_BLOX_BUNDLE_WS=false
25
+ SEND_TX_48CLUB_BUNDLE_WS=false
26
+
27
+ # Builder endpoints
28
+ BSC_RPC_ENDPOINT=
29
+ BLOXROUTE_WS_URL=
30
+ BLOX_AUTH_KEY=
31
+ _48CLUB_WS_URL=
32
+ _48CLUB_RPC_URL=
33
+ _48CLUB_SP_WALLET_ID=TTD-PAYMENT
34
+ BLOCKRAZOR_RPC_URL=
35
+ BLOCKRAZOR_AUTH_TOKEN=
36
+
37
+ # 间接依赖(通过 ttd-core 工具函数读取)
38
+ # load_wallet
39
+ WALLET_DIR=
40
+ ENCRYPTION_KEY=
@@ -14,12 +14,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports._48ClubTrade = void 0;
16
16
  const axios_1 = __importDefault(require("axios"));
17
+ const appconfig_1 = require("../appconfig");
17
18
  const https_1 = __importDefault(require("https"));
18
19
  const sp_signature_1 = require("./sp_signature");
19
20
  const member_1 = require("./member");
20
21
  class _48ClubTrade {
21
22
  constructor() {
22
- const rpcUrl = process.env._48CLUB_RPC_URL || 'https://puissant-builder.48.club/';
23
+ const rpcUrl = appconfig_1.envArgs._48club_rpc_url;
23
24
  this.client = axios_1.default.create({
24
25
  baseURL: rpcUrl,
25
26
  headers: { 'Content-Type': 'application/json' },
@@ -2,13 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.get_48club_sp_private_key = void 0;
4
4
  const ttd_core_1 = require("@clonegod/ttd-core");
5
+ const appconfig_1 = require("../appconfig");
5
6
  var _48club_sp_wallet_private_key = null;
6
7
  const get_48club_sp_private_key = () => {
7
8
  if (_48club_sp_wallet_private_key) {
8
9
  return _48club_sp_wallet_private_key;
9
10
  }
10
11
  try {
11
- const wallet = (0, ttd_core_1.load_wallet)(process.env._48CLUB_SP_WALLET_ID || 'TTD-PAYMENT', false);
12
+ const wallet = (0, ttd_core_1.load_wallet)(appconfig_1.envArgs._48club_sp_wallet_id, false);
12
13
  console.log('Load 48club SP wallet success, wallet address:', wallet.public_key);
13
14
  _48club_sp_wallet_private_key = wallet.private_key;
14
15
  return _48club_sp_wallet_private_key;
@@ -11,10 +11,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports._48ClubWsSender = void 0;
13
13
  const ttd_core_1 = require("@clonegod/ttd-core");
14
+ const appconfig_1 = require("../appconfig");
14
15
  class _48ClubWsSender {
15
16
  constructor() {
16
17
  this.wsClient = null;
17
- this.wsUrl = process.env._48CLUB_WS_URL || 'wss://puissant-builder.48.club/';
18
+ this.wsUrl = appconfig_1.envArgs._48club_ws_url;
18
19
  }
19
20
  connect() {
20
21
  var _a;
@@ -36,11 +37,11 @@ class _48ClubWsSender {
36
37
  sendTransaction(request) {
37
38
  return __awaiter(this, void 0, void 0, function* () {
38
39
  if (!this.isConnected()) {
39
- (0, ttd_core_1.log_warn)('[48club-ws] not connected');
40
+ (0, ttd_core_1.log_error)('[48club-ws] not connected, dropping tx', new Error('48club not connected'));
40
41
  return;
41
42
  }
42
43
  if (!request.tipTx) {
43
- (0, ttd_core_1.log_warn)('[48club-ws] tipTx required for bundle');
44
+ (0, ttd_core_1.log_error)('[48club-ws] tipTx required for bundle, dropping tx', new Error('tipTx required for bundle'));
44
45
  return;
45
46
  }
46
47
  const currentTimestamp = Math.floor(Date.now() / 1000);
@@ -0,0 +1,24 @@
1
+ import { EnvArgs as CoreEnvArgs } from '@clonegod/ttd-core/dist';
2
+ import './env_registry';
3
+ export declare class SendTxEnvArgs extends CoreEnvArgs {
4
+ rpc_endpoint: string;
5
+ wallet_dir: string;
6
+ encryption_key: string;
7
+ send_tx_ws_host: string;
8
+ send_tx_default_rpc: boolean;
9
+ send_tx_blockrazor_private: boolean;
10
+ send_tx_48club_private: boolean;
11
+ send_tx_blockrazor_bundle: boolean;
12
+ send_tx_48club_bundle: boolean;
13
+ send_tx_48club_bundle_ws: boolean;
14
+ send_tx_blox_bundle_ws: boolean;
15
+ bsc_rpc_endpoint: string;
16
+ bloxroute_ws_url: string;
17
+ blox_auth_key: string;
18
+ _48club_ws_url: string;
19
+ _48club_rpc_url: string;
20
+ _48club_sp_wallet_id: string;
21
+ blockrazor_rpc_url: string;
22
+ blockrazor_auth_token: string;
23
+ constructor();
24
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SendTxEnvArgs = void 0;
4
+ const dist_1 = require("@clonegod/ttd-core/dist");
5
+ require("./env_registry");
6
+ class SendTxEnvArgs extends dist_1.EnvArgs {
7
+ constructor() {
8
+ var _a, _b;
9
+ super();
10
+ const cfg = this._cfg;
11
+ this.app_name = (cfg.app_name || '').toLowerCase();
12
+ this.chain_id = (cfg.chain_id || '').toUpperCase();
13
+ this.server_id = (_a = cfg.server_id) !== null && _a !== void 0 ? _a : '';
14
+ this.redis_host = cfg.redis_host;
15
+ this.redis_port = String(cfg.redis_port);
16
+ this.rpc_endpoint = cfg.rpc_endpoint;
17
+ this.wallet_dir = cfg.wallet_dir;
18
+ this.encryption_key = (_b = cfg.encryption_key) !== null && _b !== void 0 ? _b : '';
19
+ this.send_tx_ws_host = cfg.send_tx_ws_host;
20
+ this.send_tx_default_rpc = cfg.send_tx_default_rpc;
21
+ this.send_tx_blockrazor_private = cfg.send_tx_blockrazor_private;
22
+ this.send_tx_48club_private = cfg.send_tx_48club_private;
23
+ this.send_tx_blockrazor_bundle = cfg.send_tx_blockrazor_bundle;
24
+ this.send_tx_48club_bundle = cfg.send_tx_48club_bundle;
25
+ this.send_tx_48club_bundle_ws = cfg.send_tx_48club_bundle_ws;
26
+ this.send_tx_blox_bundle_ws = cfg.send_tx_blox_bundle_ws;
27
+ this.bsc_rpc_endpoint = cfg.bsc_rpc_endpoint;
28
+ this.bloxroute_ws_url = cfg.bloxroute_ws_url;
29
+ this.blox_auth_key = cfg.blox_auth_key;
30
+ this._48club_ws_url = cfg._48club_ws_url;
31
+ this._48club_rpc_url = cfg._48club_rpc_url;
32
+ this._48club_sp_wallet_id = cfg._48club_sp_wallet_id;
33
+ this.blockrazor_rpc_url = cfg.blockrazor_rpc_url;
34
+ this.blockrazor_auth_token = cfg.blockrazor_auth_token;
35
+ (0, dist_1.printEnvConfig)('send-tx', this);
36
+ }
37
+ }
38
+ exports.SendTxEnvArgs = SendTxEnvArgs;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ttd_core_1 = require("@clonegod/ttd-core");
4
+ (0, ttd_core_1.registerEnvVars)({
5
+ bloxroute_ws_url: { env: 'BLOXROUTE_WS_URL', type: 'string', default: 'wss://api.blxrbdn.com/ws', desc: 'BloxRoute WS URL(send-tx 上游)' },
6
+ blox_auth_key: { env: 'BLOX_AUTH_KEY', type: 'string', default: '', sensitive: true, desc: 'BloxRoute 认证 key(send-tx 上游)' },
7
+ _48club_ws_url: { env: '_48CLUB_WS_URL', type: 'string', default: 'wss://puissant-builder.48.club/', desc: '48Club WS URL(send-tx 上游)' },
8
+ });
@@ -0,0 +1,3 @@
1
+ import { SendTxEnvArgs } from './EnvArgs';
2
+ export { SendTxEnvArgs };
3
+ export declare const envArgs: SendTxEnvArgs;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.envArgs = exports.SendTxEnvArgs = void 0;
4
+ const EnvArgs_1 = require("./EnvArgs");
5
+ Object.defineProperty(exports, "SendTxEnvArgs", { enumerable: true, get: function () { return EnvArgs_1.SendTxEnvArgs; } });
6
+ exports.envArgs = new EnvArgs_1.SendTxEnvArgs();
@@ -14,12 +14,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.BlockRazorTrade = void 0;
16
16
  const ttd_core_1 = require("@clonegod/ttd-core");
17
+ const appconfig_1 = require("../appconfig");
17
18
  const axios_1 = __importDefault(require("axios"));
18
19
  const https_1 = __importDefault(require("https"));
19
20
  class BlockRazorTrade {
20
21
  constructor() {
21
- const rpcUrl = process.env.BLOCKRAZOR_RPC_URL || 'https://rpc.blockrazor.builders';
22
- const authToken = process.env.BLOCKRAZOR_AUTH_TOKEN || '';
22
+ const rpcUrl = appconfig_1.envArgs.blockrazor_rpc_url;
23
+ const authToken = appconfig_1.envArgs.blockrazor_auth_token;
23
24
  this.client = axios_1.default.create({
24
25
  baseURL: rpcUrl,
25
26
  headers: { 'Content-Type': 'application/json', 'Authorization': authToken },
@@ -11,11 +11,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.BloXRouteWsSender = void 0;
13
13
  const ttd_core_1 = require("@clonegod/ttd-core");
14
+ const appconfig_1 = require("../appconfig");
14
15
  class BloXRouteWsSender {
15
16
  constructor() {
16
17
  this.wsClient = null;
17
- this.wsUrl = process.env.BLOXROUTE_WS_URL || 'wss://api.blxrbdn.com/ws';
18
- this.authToken = process.env.BLOX_AUTH_KEY || '';
18
+ this.wsUrl = appconfig_1.envArgs.bloxroute_ws_url;
19
+ this.authToken = appconfig_1.envArgs.blox_auth_key;
19
20
  }
20
21
  connect() {
21
22
  var _a;
@@ -40,11 +41,11 @@ class BloXRouteWsSender {
40
41
  sendTransaction(request) {
41
42
  return __awaiter(this, void 0, void 0, function* () {
42
43
  if (!this.isConnected()) {
43
- (0, ttd_core_1.log_warn)('[bloxroute-ws] not connected');
44
+ (0, ttd_core_1.log_error)('[bloxroute-ws] not connected, dropping tx', new Error('bloxroute not connected'));
44
45
  return;
45
46
  }
46
47
  if (!request.tipTx) {
47
- (0, ttd_core_1.log_warn)('[bloxroute-ws] tipTx required for bundle');
48
+ (0, ttd_core_1.log_error)('[bloxroute-ws] tipTx required for bundle, dropping tx', new Error('tipTx required for bundle'));
48
49
  return;
49
50
  }
50
51
  const targetBlockNumber = request.blockNumber + 4;
package/dist/rpc/index.js CHANGED
@@ -11,9 +11,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.BscMainnetRpc = void 0;
13
13
  const ttd_core_1 = require("@clonegod/ttd-core");
14
+ const appconfig_1 = require("../appconfig");
14
15
  class BscMainnetRpc {
15
16
  constructor(rpc_endpoint) {
16
- this.url = rpc_endpoint || process.env.BSC_RPC_ENDPOINT || '';
17
+ this.url = rpc_endpoint || appconfig_1.envArgs.bsc_rpc_endpoint;
17
18
  this.headers = new Headers();
18
19
  this.headers.append("Content-Type", "application/json");
19
20
  }
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.TransactionSender = void 0;
13
13
  const ttd_core_1 = require("@clonegod/ttd-core");
14
+ const appconfig_1 = require("./appconfig");
14
15
  const rpc_1 = require("./rpc");
15
16
  const blockrazor_1 = require("./blockrazor");
16
17
  const _48club_1 = require("./_48club");
@@ -29,7 +30,7 @@ class TransactionSender {
29
30
  return __awaiter(this, arguments, void 0, function* (signedMainTx, tipTxMap, order_trace_id, pair = '', only_bundle = false, trace) {
30
31
  const results = [];
31
32
  const errors = [];
32
- if (process.env.SEND_TX_BLOX_BUNDLE_WS === 'true') {
33
+ if (appconfig_1.envArgs.send_tx_blox_bundle_ws) {
33
34
  try {
34
35
  const tipTx = tipTxMap.get(constants_1.BSC_EOA_ADDRESS.BLXR);
35
36
  this.sendBundleProxy.sendTransaction('bloxroute', pair, signedMainTx, tipTx);
@@ -40,7 +41,7 @@ class TransactionSender {
40
41
  (0, ttd_core_1.log_info)(`Transaction send failed`, { provider: 'bloxroute_ws', order_trace_id, error: error.message });
41
42
  }
42
43
  }
43
- if (process.env.SEND_TX_48CLUB_BUNDLE_WS === 'true') {
44
+ if (appconfig_1.envArgs.send_tx_48club_bundle_ws) {
44
45
  try {
45
46
  const tipTx = tipTxMap.get(constants_1.BSC_EOA_ADDRESS._48CLUB);
46
47
  let spSignature;
@@ -63,19 +64,19 @@ class TransactionSender {
63
64
  const httpProviders = [
64
65
  {
65
66
  name: 'default_rpc',
66
- enable: process.env.SEND_TX_DEFAULT_RPC_PRIVATE === 'true',
67
+ enable: appconfig_1.envArgs.send_tx_default_rpc,
67
68
  is_bundle: false,
68
69
  send: () => __awaiter(this, void 0, void 0, function* () { return this.rpc.eth_sendRawTransaction(signedMainTx); }),
69
70
  },
70
71
  {
71
72
  name: 'blockrazor_private',
72
- enable: process.env.SEND_TX_BLOCKRAZOR_PRIVATE === 'true',
73
+ enable: appconfig_1.envArgs.send_tx_blockrazor_private,
73
74
  is_bundle: false,
74
75
  send: () => __awaiter(this, void 0, void 0, function* () { return this.blockRazor.sendPrivateTransaction(signedMainTx); }),
75
76
  },
76
77
  {
77
78
  name: 'blockrazor_bundle',
78
- enable: process.env.SEND_TX_BLOCKRAZOR_BUNDLE === 'true',
79
+ enable: appconfig_1.envArgs.send_tx_blockrazor_bundle,
79
80
  is_bundle: true,
80
81
  send: () => __awaiter(this, void 0, void 0, function* () {
81
82
  const tipTx = tipTxMap.get(constants_1.BSC_EOA_ADDRESS.BLOCKRAZOR);
@@ -84,13 +85,13 @@ class TransactionSender {
84
85
  },
85
86
  {
86
87
  name: '48club_private',
87
- enable: process.env.SEND_TX_48CLUB_PRIVATE === 'true',
88
+ enable: appconfig_1.envArgs.send_tx_48club_private,
88
89
  is_bundle: false,
89
90
  send: () => __awaiter(this, void 0, void 0, function* () { return this._48Club.sendPrivateTransactionWith48SP(signedMainTx); }),
90
91
  },
91
92
  {
92
93
  name: '48club_bundle',
93
- enable: process.env.SEND_TX_48CLUB_BUNDLE === 'true',
94
+ enable: appconfig_1.envArgs.send_tx_48club_bundle,
94
95
  is_bundle: true,
95
96
  send: () => __awaiter(this, void 0, void 0, function* () {
96
97
  const tipTx = tipTxMap.get(constants_1.BSC_EOA_ADDRESS._48CLUB);
@@ -111,16 +112,16 @@ class TransactionSender {
111
112
  (0, ttd_core_1.log_info)(`Transaction send failed`, { provider: provider.name, order_trace_id, error: error.message });
112
113
  }
113
114
  })));
114
- if (errors.some(e => e.includes('nonce'))) {
115
- throw new Error(`Nonce error: ${JSON.stringify(errors)}`);
115
+ if (results.length > 0) {
116
+ return results;
116
117
  }
117
118
  if (errors.some(e => e.includes('bundle already exist') || e.includes('already known'))) {
118
119
  return results;
119
120
  }
120
- if (results.length === 0 || errors.length > 0) {
121
- throw new Error(`Send failed: ${JSON.stringify(errors)}`);
121
+ if (errors.some(e => e.includes('nonce'))) {
122
+ throw new Error(`Nonce error: ${JSON.stringify(errors)}`);
122
123
  }
123
- return results;
124
+ throw new Error(`Send failed: ${JSON.stringify(errors)}`);
124
125
  });
125
126
  }
126
127
  }
package/dist/ws_client.js CHANGED
@@ -2,12 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BscSendTxProxy = void 0;
4
4
  const ttd_core_1 = require("@clonegod/ttd-core");
5
+ const appconfig_1 = require("./appconfig");
5
6
  const logger = (0, ttd_core_1.createLogger)(__filename);
6
7
  class BscSendTxProxy {
7
8
  constructor() {
8
9
  this.connected = false;
9
10
  this.pendingQueue = [];
10
- const host = process.env.SEND_TX_WS_HOST || '127.0.0.1';
11
+ const host = appconfig_1.envArgs.send_tx_ws_host;
11
12
  this.wsUrl = `ws://${host}:${ttd_core_1.SERVICE_PORT.SEND_TX_WS}/bsc/send_tx`;
12
13
  this.clientName = process.env.APP_NAME
13
14
  || process.env.name
package/dist/ws_server.js CHANGED
@@ -11,6 +11,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  require('dotenv').config();
13
13
  const ttd_core_1 = require("@clonegod/ttd-core");
14
+ const appconfig_1 = require("./appconfig");
15
+ (0, ttd_core_1.setCoreEnv)(appconfig_1.envArgs);
14
16
  const ws_1 = require("ws");
15
17
  const _48club_1 = require("./_48club");
16
18
  const bloxroute_1 = require("./bloxroute");
@@ -35,13 +37,28 @@ class BscSendTxWebSocketServer {
35
37
  this.initSenders();
36
38
  }
37
39
  initSenders() {
38
- if (process.env.SEND_TX_48CLUB_WS === 'true') {
39
- this._48clubWsSender = new _48club_1._48ClubWsSender();
40
- this._48clubWsSender.connect();
40
+ if (appconfig_1.envArgs._48club_ws_url) {
41
+ try {
42
+ this._48clubWsSender = new _48club_1._48ClubWsSender();
43
+ this._48clubWsSender.connect();
44
+ (0, ttd_core_1.log_info)(`[WS_SERVER] 48Club upstream WS client started → ${appconfig_1.envArgs._48club_ws_url}`);
45
+ }
46
+ catch (e) {
47
+ (0, ttd_core_1.log_error)('[WS_SERVER] 48Club upstream init failed', e instanceof Error ? e : new Error(String(e)));
48
+ }
49
+ }
50
+ if (appconfig_1.envArgs.bloxroute_ws_url && appconfig_1.envArgs.blox_auth_key) {
51
+ try {
52
+ this.bloxrouteWsSender = new bloxroute_1.BloXRouteWsSender();
53
+ this.bloxrouteWsSender.connect();
54
+ (0, ttd_core_1.log_info)(`[WS_SERVER] BloxRoute upstream WS client started → ${appconfig_1.envArgs.bloxroute_ws_url}`);
55
+ }
56
+ catch (e) {
57
+ (0, ttd_core_1.log_error)('[WS_SERVER] BloxRoute upstream init failed', e instanceof Error ? e : new Error(String(e)));
58
+ }
41
59
  }
42
- if (process.env.SEND_TX_BLOXROUTE_WS === 'true') {
43
- this.bloxrouteWsSender = new bloxroute_1.BloXRouteWsSender();
44
- this.bloxrouteWsSender.connect();
60
+ else if (appconfig_1.envArgs.bloxroute_ws_url && !appconfig_1.envArgs.blox_auth_key) {
61
+ (0, ttd_core_1.log_info)(`[WS_SERVER] BloxRoute upstream skipped: BLOX_AUTH_KEY 未配置`);
45
62
  }
46
63
  }
47
64
  handleMessage(ws, message) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-bsc-send-tx",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "BSC 交易发送模块(HTTP直发 + WS bundle 转发)",
5
5
  "license": "UNLICENSED",
6
6
  "main": "dist/index.js",
@@ -12,8 +12,8 @@
12
12
  "push": "npm run build && npm publish"
13
13
  },
14
14
  "dependencies": {
15
- "@clonegod/ttd-core": "3.0.13",
16
- "axios": "^1.12.0",
15
+ "@clonegod/ttd-core": "3.1.53",
16
+ "axios": "1.15.0",
17
17
  "dotenv": "^16.4.7",
18
18
  "ethers": "^5.8.0",
19
19
  "ws": "^8.18.3"