@clonegod/ttd-bsc-common 1.0.10 → 1.0.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.
- package/dist/common/constants.d.ts +1 -0
- package/dist/common/constants.js +1 -0
- package/dist/quote/event/pool_event_listener.d.ts +7 -14
- package/dist/quote/event/pool_event_listener.js +73 -118
- package/package.json +1 -1
- package/dist/config/env_args.d.ts +0 -13
- package/dist/config/env_args.js +0 -23
- package/dist/constants/networks.d.ts +0 -10
- package/dist/constants/networks.js +0 -28
- package/dist/providers/index.d.ts +0 -9
- package/dist/providers/index.js +0 -21
- package/dist/utils/redis_lock.d.ts +0 -14
- package/dist/utils/redis_lock.js +0 -100
|
@@ -12,6 +12,7 @@ export declare const EVENT_NAMES: {
|
|
|
12
12
|
readonly POOL_SWAP: "POOL_SWAP";
|
|
13
13
|
readonly QUOTE_RESULT: "quote_result";
|
|
14
14
|
readonly QUOTE_TRIGGER: "quote_trigger";
|
|
15
|
+
readonly WS_CONNECTION_FAILED: "ws_connection_failed";
|
|
15
16
|
};
|
|
16
17
|
export declare const EVENT_SIGNATURES: {
|
|
17
18
|
SWAP_RAW: string;
|
package/dist/common/constants.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.EVENT_NAMES = {
|
|
|
15
15
|
POOL_SWAP: 'POOL_SWAP',
|
|
16
16
|
QUOTE_RESULT: 'quote_result',
|
|
17
17
|
QUOTE_TRIGGER: 'quote_trigger',
|
|
18
|
+
WS_CONNECTION_FAILED: 'ws_connection_failed',
|
|
18
19
|
};
|
|
19
20
|
exports.EVENT_SIGNATURES = {
|
|
20
21
|
SWAP_RAW: "Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick, uint128 protocolFeesToken0, uint128 protocolFeesToken1)",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { AppConfig } from "@clonegod/ttd-core/dist";
|
|
1
|
+
import { StandardPoolInfoType } from '@clonegod/ttd-core';
|
|
2
|
+
import { AppConfig } from '@clonegod/ttd-core/dist';
|
|
4
3
|
export interface BlockUpdateEvent {
|
|
5
4
|
blockNumber: number;
|
|
6
5
|
previousBlockNumber: number;
|
|
@@ -10,31 +9,25 @@ export declare class PoolEventListener {
|
|
|
10
9
|
private appConfig;
|
|
11
10
|
private wsProvider;
|
|
12
11
|
private poolList;
|
|
12
|
+
private ws_endpoint;
|
|
13
13
|
private isConnected;
|
|
14
|
+
private isReconnecting;
|
|
14
15
|
private isStarted;
|
|
15
16
|
private reconnectAttempts;
|
|
16
17
|
private maxReconnectAttempts;
|
|
17
18
|
private baseReconnectDelay;
|
|
18
19
|
private maxReconnectDelay;
|
|
19
|
-
private heartbeatInterval;
|
|
20
|
-
private connectionTimeout;
|
|
21
|
-
private connectionTimeoutMs;
|
|
22
20
|
private lastProcessedBlockNumber;
|
|
23
21
|
private isBlockListenerActive;
|
|
24
|
-
|
|
25
|
-
constructor(appConfig: AppConfig, wsProvider: ethers.providers.WebSocketProvider);
|
|
22
|
+
constructor(appConfig: AppConfig, ws_endpoint: string);
|
|
26
23
|
init(poolList: StandardPoolInfoType[]): Promise<void>;
|
|
27
24
|
start(): Promise<void>;
|
|
28
25
|
stop(): Promise<void>;
|
|
29
|
-
private
|
|
30
|
-
private setConnectionTimeout;
|
|
31
|
-
private clearConnectionTimeout;
|
|
26
|
+
private connect;
|
|
32
27
|
private handleConnectionIssue;
|
|
33
|
-
private startHeartbeat;
|
|
34
|
-
private stopHeartbeat;
|
|
35
|
-
private cleanupProvider;
|
|
36
28
|
private startBlockListener;
|
|
37
29
|
private stopBlockListener;
|
|
30
|
+
private cleanup;
|
|
38
31
|
isWSConnected(): boolean;
|
|
39
32
|
getConnectionDiagnostics(): object;
|
|
40
33
|
}
|
|
@@ -12,28 +12,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.PoolEventListener = void 0;
|
|
13
13
|
const ethers_1 = require("ethers");
|
|
14
14
|
const dist_1 = require("@clonegod/ttd-core/dist");
|
|
15
|
-
const
|
|
15
|
+
const common_1 = require("../../common");
|
|
16
16
|
class PoolEventListener {
|
|
17
|
-
constructor(appConfig,
|
|
17
|
+
constructor(appConfig, ws_endpoint) {
|
|
18
|
+
this.wsProvider = null;
|
|
18
19
|
this.poolList = [];
|
|
19
20
|
this.isConnected = false;
|
|
21
|
+
this.isReconnecting = false;
|
|
20
22
|
this.isStarted = false;
|
|
21
23
|
this.reconnectAttempts = 0;
|
|
22
24
|
this.maxReconnectAttempts = 10;
|
|
23
|
-
this.baseReconnectDelay =
|
|
25
|
+
this.baseReconnectDelay = 500;
|
|
24
26
|
this.maxReconnectDelay = 30000;
|
|
25
|
-
this.heartbeatInterval = null;
|
|
26
|
-
this.connectionTimeout = null;
|
|
27
|
-
this.connectionTimeoutMs = 15000;
|
|
28
27
|
this.lastProcessedBlockNumber = 0;
|
|
29
28
|
this.isBlockListenerActive = false;
|
|
30
|
-
this.metrics = {
|
|
31
|
-
lastBlockTime: 0,
|
|
32
|
-
blockInterval: 0,
|
|
33
|
-
missedBlocks: 0
|
|
34
|
-
};
|
|
35
29
|
this.appConfig = appConfig;
|
|
36
|
-
this.
|
|
30
|
+
this.ws_endpoint = ws_endpoint;
|
|
37
31
|
}
|
|
38
32
|
init(poolList) {
|
|
39
33
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -41,13 +35,13 @@ class PoolEventListener {
|
|
|
41
35
|
if (this.poolList.length !== poolList.length) {
|
|
42
36
|
(0, dist_1.log_warn)(`发现 ${poolList.length - this.poolList.length} 个无效池地址,已过滤`, '');
|
|
43
37
|
}
|
|
44
|
-
yield this.
|
|
38
|
+
yield this.connect();
|
|
45
39
|
});
|
|
46
40
|
}
|
|
47
41
|
start() {
|
|
48
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
43
|
(0, dist_1.log_info)(`开始启动区块监听...`);
|
|
50
|
-
if (!this.isConnected) {
|
|
44
|
+
if (!this.isConnected || !this.wsProvider) {
|
|
51
45
|
(0, dist_1.log_warn)('WebSocket 尚未连接,无法启动监听', '');
|
|
52
46
|
return;
|
|
53
47
|
}
|
|
@@ -60,125 +54,76 @@ class PoolEventListener {
|
|
|
60
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
55
|
(0, dist_1.log_info)(`停止区块监听...`);
|
|
62
56
|
this.stopBlockListener();
|
|
63
|
-
this.
|
|
57
|
+
this.cleanup();
|
|
64
58
|
this.isStarted = false;
|
|
65
59
|
(0, dist_1.log_info)(`区块监听已停止`);
|
|
66
60
|
});
|
|
67
61
|
}
|
|
68
|
-
|
|
62
|
+
connect() {
|
|
69
63
|
return __awaiter(this, void 0, void 0, function* () {
|
|
70
64
|
try {
|
|
71
|
-
(0, dist_1.log_info)(`正在连接WebSocket: ${this.
|
|
65
|
+
(0, dist_1.log_info)(`正在连接 WebSocket: ${this.ws_endpoint}`);
|
|
66
|
+
this.wsProvider = new ethers_1.ethers.providers.WebSocketProvider(this.ws_endpoint);
|
|
72
67
|
yield this.wsProvider.ready;
|
|
73
|
-
this.setConnectionTimeout();
|
|
74
|
-
this.clearConnectionTimeout();
|
|
75
68
|
this.isConnected = true;
|
|
76
69
|
this.reconnectAttempts = 0;
|
|
77
|
-
(0, dist_1.log_info)(`WebSocket
|
|
70
|
+
(0, dist_1.log_info)(`WebSocket 已连接: ${this.ws_endpoint}`);
|
|
78
71
|
this.wsProvider.on('error', (err) => {
|
|
79
|
-
(0, dist_1.log_error)(`WebSocket
|
|
72
|
+
(0, dist_1.log_error)(`WebSocket 错误:`, err, '');
|
|
80
73
|
this.handleConnectionIssue();
|
|
81
74
|
});
|
|
82
|
-
this.wsProvider._websocket.on('close', (code) =>
|
|
83
|
-
(0, dist_1.log_warn)(`WebSocket 连接关闭, 代码: ${code}
|
|
75
|
+
this.wsProvider._websocket.on('close', (code, reason) => {
|
|
76
|
+
(0, dist_1.log_warn)(`WebSocket 连接关闭, 代码: ${code}, 原因: ${reason || '未知'}`);
|
|
84
77
|
this.handleConnectionIssue();
|
|
85
|
-
})
|
|
86
|
-
this.
|
|
78
|
+
});
|
|
79
|
+
if (this.isStarted) {
|
|
80
|
+
yield this.startBlockListener();
|
|
81
|
+
}
|
|
87
82
|
}
|
|
88
83
|
catch (error) {
|
|
89
|
-
(0, dist_1.log_error)(
|
|
90
|
-
this.
|
|
91
|
-
|
|
84
|
+
(0, dist_1.log_error)(`首次连接 WebSocket 失败: ${this.ws_endpoint}`, error, '');
|
|
85
|
+
if (this.reconnectAttempts > 0) {
|
|
86
|
+
this.handleConnectionIssue();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.isReconnecting = true;
|
|
90
|
+
this.isConnected = false;
|
|
91
|
+
this.cleanup();
|
|
92
|
+
yield (0, dist_1.sleep)(this.baseReconnectDelay);
|
|
93
|
+
yield this.connect();
|
|
94
|
+
this.isReconnecting = false;
|
|
95
|
+
}
|
|
92
96
|
}
|
|
93
97
|
});
|
|
94
98
|
}
|
|
95
|
-
setConnectionTimeout() {
|
|
96
|
-
this.clearConnectionTimeout();
|
|
97
|
-
this.connectionTimeout = setTimeout(() => {
|
|
98
|
-
(0, dist_1.log_error)(`WebSocket 连接超时`, new Error('Connection timeout'), '');
|
|
99
|
-
this.handleConnectionIssue();
|
|
100
|
-
}, this.connectionTimeoutMs);
|
|
101
|
-
}
|
|
102
|
-
clearConnectionTimeout() {
|
|
103
|
-
if (this.connectionTimeout) {
|
|
104
|
-
clearTimeout(this.connectionTimeout);
|
|
105
|
-
this.connectionTimeout = null;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
99
|
handleConnectionIssue() {
|
|
109
100
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
-
if (
|
|
101
|
+
if (this.isReconnecting)
|
|
111
102
|
return;
|
|
103
|
+
this.isReconnecting = true;
|
|
112
104
|
this.isConnected = false;
|
|
113
|
-
this.
|
|
114
|
-
|
|
105
|
+
this.stopBlockListener();
|
|
106
|
+
this.cleanup();
|
|
115
107
|
this.reconnectAttempts++;
|
|
116
|
-
|
|
108
|
+
const delay = Math.min(this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay);
|
|
109
|
+
(0, dist_1.log_info)(`尝试重连 ${this.reconnectAttempts}/${this.maxReconnectAttempts}, 延迟 ${delay}ms, 节点: ${this.ws_endpoint}`);
|
|
117
110
|
if (this.reconnectAttempts > this.maxReconnectAttempts) {
|
|
118
|
-
(0, dist_1.log_error)(
|
|
119
|
-
|
|
111
|
+
(0, dist_1.log_error)(`重连失败,尝试次数达到 ${this.maxReconnectAttempts} 次,程序退出`, new Error('Max reconnect attempts failed'), '');
|
|
112
|
+
this.appConfig.emit(common_1.EVENT_NAMES.WS_CONNECTION_FAILED, {
|
|
113
|
+
endpoint: this.ws_endpoint,
|
|
114
|
+
attempts: this.maxReconnectAttempts,
|
|
115
|
+
});
|
|
116
|
+
process.exit(1);
|
|
120
117
|
}
|
|
121
118
|
yield (0, dist_1.sleep)(delay);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (this.isStarted) {
|
|
125
|
-
(0, dist_1.log_info)('重连成功,正在重新启动区块监听...');
|
|
126
|
-
yield this.startBlockListener();
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
catch (err) {
|
|
130
|
-
(0, dist_1.log_error)('重新连接失败:', err, '');
|
|
131
|
-
this.handleConnectionIssue();
|
|
132
|
-
}
|
|
119
|
+
yield this.connect();
|
|
120
|
+
this.isReconnecting = false;
|
|
133
121
|
});
|
|
134
122
|
}
|
|
135
|
-
startHeartbeat() {
|
|
136
|
-
this.stopHeartbeat();
|
|
137
|
-
this.heartbeatInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
138
|
-
try {
|
|
139
|
-
if (!this.wsProvider)
|
|
140
|
-
return;
|
|
141
|
-
const blockNumber = yield this.wsProvider.getBlockNumber();
|
|
142
|
-
(0, dist_1.log_debug)(`心跳检测成功,当前区块: ${blockNumber}`);
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
(0, dist_1.log_warn)(`心跳检测失败,正在重连...`);
|
|
146
|
-
this.handleConnectionIssue();
|
|
147
|
-
}
|
|
148
|
-
}), 15000);
|
|
149
|
-
}
|
|
150
|
-
stopHeartbeat() {
|
|
151
|
-
if (this.heartbeatInterval) {
|
|
152
|
-
clearInterval(this.heartbeatInterval);
|
|
153
|
-
this.heartbeatInterval = null;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
cleanupProvider() {
|
|
157
|
-
this.stopHeartbeat();
|
|
158
|
-
this.clearConnectionTimeout();
|
|
159
|
-
this.stopBlockListener();
|
|
160
|
-
if (this.wsProvider) {
|
|
161
|
-
try {
|
|
162
|
-
this.wsProvider.removeAllListeners();
|
|
163
|
-
if (this.wsProvider._websocket) {
|
|
164
|
-
this.wsProvider._websocket.removeAllListeners();
|
|
165
|
-
if (this.wsProvider._websocket.readyState === 1) {
|
|
166
|
-
this.wsProvider._websocket.close(1000, "Normal closure");
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
catch (error) {
|
|
171
|
-
(0, dist_1.log_error)(`清理 Provider 资源时出错:`, error, '');
|
|
172
|
-
}
|
|
173
|
-
this.wsProvider = undefined;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
123
|
startBlockListener() {
|
|
177
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
(
|
|
179
|
-
|
|
180
|
-
if (!this.isConnected || !this.wsProvider) {
|
|
181
|
-
(0, dist_1.log_warn)(`无法启动区块监听: WebSocket未连接`);
|
|
125
|
+
if (!this.wsProvider || !this.isConnected) {
|
|
126
|
+
(0, dist_1.log_warn)(`无法启动区块监听: WebSocket 未连接`);
|
|
182
127
|
return;
|
|
183
128
|
}
|
|
184
129
|
try {
|
|
@@ -189,28 +134,22 @@ class PoolEventListener {
|
|
|
189
134
|
try {
|
|
190
135
|
if (!this.isConnected || !this.isBlockListenerActive)
|
|
191
136
|
return;
|
|
192
|
-
this.metrics.blockInterval = Date.now() - this.metrics.lastBlockTime;
|
|
193
|
-
this.metrics.lastBlockTime = Date.now();
|
|
194
|
-
if (this.metrics.blockInterval > 30000) {
|
|
195
|
-
(0, dist_1.log_warn)(`区块间隔异常: ${this.metrics.blockInterval}ms`);
|
|
196
|
-
this.metrics.missedBlocks++;
|
|
197
|
-
}
|
|
198
137
|
(0, dist_1.log_info)(`------- Block: ${blockNumber} -------`);
|
|
199
138
|
const previousBlockNumber = this.lastProcessedBlockNumber;
|
|
200
139
|
this.lastProcessedBlockNumber = blockNumber;
|
|
201
140
|
const blockUpdateEvent = {
|
|
202
|
-
blockNumber
|
|
203
|
-
previousBlockNumber
|
|
204
|
-
timestamp: Date.now()
|
|
141
|
+
blockNumber,
|
|
142
|
+
previousBlockNumber,
|
|
143
|
+
timestamp: Date.now(),
|
|
205
144
|
};
|
|
206
|
-
this.appConfig.emit(
|
|
145
|
+
this.appConfig.emit(common_1.EVENT_NAMES.BLOCK_UPDATE, blockUpdateEvent);
|
|
207
146
|
}
|
|
208
147
|
catch (error) {
|
|
209
148
|
(0, dist_1.log_error)(`处理区块事件出错:`, error, '');
|
|
210
149
|
}
|
|
211
150
|
}));
|
|
212
151
|
this.isBlockListenerActive = true;
|
|
213
|
-
(0, dist_1.log_info)(`区块监听已启动,使用WebSocket事件订阅方式`);
|
|
152
|
+
(0, dist_1.log_info)(`区块监听已启动,使用 WebSocket 事件订阅方式`);
|
|
214
153
|
}
|
|
215
154
|
catch (error) {
|
|
216
155
|
(0, dist_1.log_error)(`启动区块监听失败:`, error, '');
|
|
@@ -225,22 +164,38 @@ class PoolEventListener {
|
|
|
225
164
|
(0, dist_1.log_info)(`区块监听已停止`);
|
|
226
165
|
}
|
|
227
166
|
}
|
|
167
|
+
cleanup() {
|
|
168
|
+
if (this.wsProvider) {
|
|
169
|
+
try {
|
|
170
|
+
this.wsProvider.removeAllListeners();
|
|
171
|
+
if (this.wsProvider._websocket && this.wsProvider._websocket.readyState === 1) {
|
|
172
|
+
this.wsProvider._websocket.close(1000, 'Normal closure');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
(0, dist_1.log_error)(`清理 WebSocket 资源失败:`, error, '');
|
|
177
|
+
}
|
|
178
|
+
this.wsProvider = null;
|
|
179
|
+
}
|
|
180
|
+
this.isConnected = false;
|
|
181
|
+
this.isReconnecting = false;
|
|
182
|
+
}
|
|
228
183
|
isWSConnected() {
|
|
229
|
-
|
|
184
|
+
var _a, _b;
|
|
185
|
+
return this.isConnected && ((_b = (_a = this.wsProvider) === null || _a === void 0 ? void 0 : _a._websocket) === null || _b === void 0 ? void 0 : _b.readyState) === 1;
|
|
230
186
|
}
|
|
231
187
|
getConnectionDiagnostics() {
|
|
232
188
|
return {
|
|
233
189
|
isConnected: this.isConnected,
|
|
190
|
+
isReconnecting: this.isReconnecting,
|
|
234
191
|
isStarted: this.isStarted,
|
|
235
192
|
reconnectAttempts: this.reconnectAttempts,
|
|
236
|
-
|
|
237
|
-
wsEndpoint: this.appConfig.env_args.ws_endpoint,
|
|
193
|
+
ws_endpoint: this.ws_endpoint,
|
|
238
194
|
wsReadyState: this.wsProvider && this.wsProvider._websocket
|
|
239
195
|
? this.wsProvider._websocket.readyState
|
|
240
196
|
: null,
|
|
241
197
|
trackingPools: this.poolList.length,
|
|
242
198
|
lastProcessedBlock: this.lastProcessedBlockNumber,
|
|
243
|
-
metrics: Object.assign(Object.assign({}, this.metrics), { lastBlockTime: new Date(this.metrics.lastBlockTime).toISOString() })
|
|
244
199
|
};
|
|
245
200
|
}
|
|
246
201
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { EnvArgs } from "@clonegod/ttd-core/dist";
|
|
2
|
-
export declare class BSCEnvArgs extends EnvArgs {
|
|
3
|
-
trade_mgt_http_port: number;
|
|
4
|
-
subscribe_dex_pool_txns: boolean;
|
|
5
|
-
subscribe_dex_pool_txns_startup: boolean;
|
|
6
|
-
subscribe_dex_pool_txns_interval: number;
|
|
7
|
-
onchain_data_save_file: boolean;
|
|
8
|
-
load_dex_pools_min_tvl: number;
|
|
9
|
-
load_dex_pools_min_vol: number;
|
|
10
|
-
load_dex_pools_all: boolean;
|
|
11
|
-
load_dex_pools_on_startup: boolean;
|
|
12
|
-
constructor();
|
|
13
|
-
}
|
package/dist/config/env_args.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BSCEnvArgs = void 0;
|
|
4
|
-
const dist_1 = require("@clonegod/ttd-core/dist");
|
|
5
|
-
const dist_2 = require("@clonegod/ttd-core/dist");
|
|
6
|
-
class BSCEnvArgs extends dist_1.EnvArgs {
|
|
7
|
-
constructor() {
|
|
8
|
-
super();
|
|
9
|
-
// BSC特定配置初始化
|
|
10
|
-
this.trade_mgt_http_port = parseInt(process.env.TRADE_MGT_HTTP_PORT || '8003');
|
|
11
|
-
this.subscribe_dex_pool_txns = process.env.SUBSCRIBE_DEX_POOL_TXNS === 'true';
|
|
12
|
-
this.subscribe_dex_pool_txns_startup = process.env.SUBSCRIBE_DEX_POOL_TXNS_STARTUP === 'true';
|
|
13
|
-
this.subscribe_dex_pool_txns_interval = parseInt(process.env.SUBSCRIBE_DEX_POOL_TXNS_INTERVAL || '3600');
|
|
14
|
-
this.onchain_data_save_file = process.env.ONCHAIN_DATA_SAVE_FILE === 'true';
|
|
15
|
-
// BSC链特定的池子配置初始化
|
|
16
|
-
this.load_dex_pools_min_tvl = parseInt(process.env.LOAD_DEX_POOLS_MIN_TVL || '50000');
|
|
17
|
-
this.load_dex_pools_min_vol = parseInt(process.env.LOAD_DEX_POOLS_MIN_VOL || '100000');
|
|
18
|
-
this.load_dex_pools_all = process.env.LOAD_DEX_POOLS_ALL === 'true';
|
|
19
|
-
this.load_dex_pools_on_startup = process.env.LOAD_DEX_POOLS_ON_STARTUP === 'true';
|
|
20
|
-
(0, dist_2.log_info)('BSC env args init finish', this);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.BSCEnvArgs = BSCEnvArgs;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { BSCNetworkConfig } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* BSC网络配置
|
|
4
|
-
*/
|
|
5
|
-
export declare const BSC_MAINNET: BSCNetworkConfig;
|
|
6
|
-
export declare const BSC_TESTNET: BSCNetworkConfig;
|
|
7
|
-
/**
|
|
8
|
-
* 根据环境变量获取当前使用的网络
|
|
9
|
-
*/
|
|
10
|
-
export declare const getCurrentNetwork: () => BSCNetworkConfig;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCurrentNetwork = exports.BSC_TESTNET = exports.BSC_MAINNET = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* BSC网络配置
|
|
6
|
-
*/
|
|
7
|
-
exports.BSC_MAINNET = {
|
|
8
|
-
chainId: 56,
|
|
9
|
-
name: 'BSC Mainnet',
|
|
10
|
-
rpcUrl: 'https://bsc-dataseed.binance.org/',
|
|
11
|
-
explorerUrl: 'https://bscscan.com',
|
|
12
|
-
blockTime: 3, // 3秒
|
|
13
|
-
};
|
|
14
|
-
exports.BSC_TESTNET = {
|
|
15
|
-
chainId: 97,
|
|
16
|
-
name: 'BSC Testnet',
|
|
17
|
-
rpcUrl: 'https://data-seed-prebsc-1-s1.binance.org:8545/',
|
|
18
|
-
explorerUrl: 'https://testnet.bscscan.com',
|
|
19
|
-
blockTime: 3, // 3秒
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* 根据环境变量获取当前使用的网络
|
|
23
|
-
*/
|
|
24
|
-
const getCurrentNetwork = () => {
|
|
25
|
-
const network = process.env.BSC_NETWORK || 'mainnet';
|
|
26
|
-
return network.toLowerCase() === 'testnet' ? exports.BSC_TESTNET : exports.BSC_MAINNET;
|
|
27
|
-
};
|
|
28
|
-
exports.getCurrentNetwork = getCurrentNetwork;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ethers } from 'ethers';
|
|
2
|
-
/**
|
|
3
|
-
* 创建BSC网络的Provider
|
|
4
|
-
*/
|
|
5
|
-
export declare const createBSCProvider: () => ethers.providers.JsonRpcProvider;
|
|
6
|
-
/**
|
|
7
|
-
* 使用私钥创建Signer
|
|
8
|
-
*/
|
|
9
|
-
export declare const createSigner: (privateKey: string, provider?: ethers.providers.Provider) => ethers.Wallet;
|
package/dist/providers/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createSigner = exports.createBSCProvider = void 0;
|
|
4
|
-
const ethers_1 = require("ethers");
|
|
5
|
-
const networks_1 = require("../constants/networks");
|
|
6
|
-
/**
|
|
7
|
-
* 创建BSC网络的Provider
|
|
8
|
-
*/
|
|
9
|
-
const createBSCProvider = () => {
|
|
10
|
-
const network = (0, networks_1.getCurrentNetwork)();
|
|
11
|
-
return new ethers_1.ethers.providers.JsonRpcProvider(network.rpcUrl);
|
|
12
|
-
};
|
|
13
|
-
exports.createBSCProvider = createBSCProvider;
|
|
14
|
-
/**
|
|
15
|
-
* 使用私钥创建Signer
|
|
16
|
-
*/
|
|
17
|
-
const createSigner = (privateKey, provider) => {
|
|
18
|
-
const bscProvider = provider || (0, exports.createBSCProvider)();
|
|
19
|
-
return new ethers_1.ethers.Wallet(privateKey, bscProvider);
|
|
20
|
-
};
|
|
21
|
-
exports.createSigner = createSigner;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { RedisClientType } from "redis";
|
|
2
|
-
export declare class RedisLock {
|
|
3
|
-
private lock_prefix;
|
|
4
|
-
private redisClient;
|
|
5
|
-
private lockMaxRetries;
|
|
6
|
-
private lockRetryDelayMs;
|
|
7
|
-
private lockExpireSeconds;
|
|
8
|
-
constructor(lock_prefix: string);
|
|
9
|
-
getRedisClient(): Promise<RedisClientType>;
|
|
10
|
-
private getLockKey;
|
|
11
|
-
private acquireLock;
|
|
12
|
-
private releaseLock;
|
|
13
|
-
withLock<T>(lock_identifier: string, callback: () => Promise<T>): Promise<T>;
|
|
14
|
-
}
|
package/dist/utils/redis_lock.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.RedisLock = void 0;
|
|
13
|
-
const dist_1 = require("@clonegod/ttd-core/dist");
|
|
14
|
-
class RedisLock {
|
|
15
|
-
constructor(lock_prefix) {
|
|
16
|
-
this.lock_prefix = lock_prefix;
|
|
17
|
-
this.redisClient = null;
|
|
18
|
-
this.lockMaxRetries = 10;
|
|
19
|
-
this.lockRetryDelayMs = 300;
|
|
20
|
-
this.lockExpireSeconds = 10;
|
|
21
|
-
}
|
|
22
|
-
getRedisClient() {
|
|
23
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
-
if (!this.redisClient) {
|
|
25
|
-
this.redisClient = yield (0, dist_1.getRedisCache)();
|
|
26
|
-
}
|
|
27
|
-
return this.redisClient;
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
getLockKey(lock_identifier) {
|
|
31
|
-
return `${this.lock_prefix}:lock:${lock_identifier}`;
|
|
32
|
-
}
|
|
33
|
-
acquireLock(lock_key_1, lock_value_1) {
|
|
34
|
-
return __awaiter(this, arguments, void 0, function* (lock_key, lock_value, expireSeconds = this.lockExpireSeconds) {
|
|
35
|
-
const redisClient = yield this.getRedisClient();
|
|
36
|
-
const result = yield redisClient.set(lock_key, lock_value, {
|
|
37
|
-
NX: true,
|
|
38
|
-
EX: expireSeconds
|
|
39
|
-
});
|
|
40
|
-
(0, dist_1.log_info)(`try acquireLock: lock_key=${lock_key}, lock_value=${lock_value}, expireSeconds=${expireSeconds}, result=${result}`);
|
|
41
|
-
const success = result === 'OK';
|
|
42
|
-
if (success) {
|
|
43
|
-
(0, dist_1.log_info)(`acquire lock success: lock_key=${lock_key}, lock_value=${lock_value}`);
|
|
44
|
-
}
|
|
45
|
-
return success;
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
releaseLock(lock_key, lock_value) {
|
|
49
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
const redisClient = yield this.getRedisClient();
|
|
51
|
-
const script = `
|
|
52
|
-
if redis.call('get', KEYS[1]) == ARGV[1] then
|
|
53
|
-
return redis.call('del', KEYS[1])
|
|
54
|
-
else
|
|
55
|
-
return 0
|
|
56
|
-
end
|
|
57
|
-
`;
|
|
58
|
-
const result = yield redisClient.eval(script, {
|
|
59
|
-
keys: [lock_key],
|
|
60
|
-
arguments: [lock_value]
|
|
61
|
-
});
|
|
62
|
-
const success = Number(result) === 1;
|
|
63
|
-
if (success) {
|
|
64
|
-
(0, dist_1.log_info)(`release lock success: lock_key=${lock_key}, lock_value=${lock_value}`);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
(0, dist_1.log_info)(`release lock failed: lock_key=${lock_key}, lock_value=${lock_value}, maybe expired or locked by other process`);
|
|
68
|
-
}
|
|
69
|
-
return success;
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
withLock(lock_identifier, callback) {
|
|
73
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
-
const lock_key = this.getLockKey(lock_identifier);
|
|
75
|
-
const lock_value = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
|
|
76
|
-
let retries = 0;
|
|
77
|
-
let acquired = false;
|
|
78
|
-
try {
|
|
79
|
-
while (retries < this.lockMaxRetries) {
|
|
80
|
-
acquired = yield this.acquireLock(lock_key, lock_value);
|
|
81
|
-
if (acquired)
|
|
82
|
-
break;
|
|
83
|
-
yield new Promise(resolve => setTimeout(resolve, this.lockRetryDelayMs));
|
|
84
|
-
retries++;
|
|
85
|
-
}
|
|
86
|
-
if (!acquired) {
|
|
87
|
-
throw new Error(`acquire lock failed: lock_key=${lock_key}, lock_value=${lock_value}, after ${this.lockMaxRetries} retries, maybe locked by other process`);
|
|
88
|
-
}
|
|
89
|
-
return yield callback();
|
|
90
|
-
}
|
|
91
|
-
finally {
|
|
92
|
-
if (acquired) {
|
|
93
|
-
yield (0, dist_1.sleep)(parseInt(process.env.NONCE_LOCK_RELEASE_DELAY_MS || '2000'));
|
|
94
|
-
yield this.releaseLock(lock_key, lock_value);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
exports.RedisLock = RedisLock;
|