@clonegod/ttd-bsc-common 1.0.9 → 1.0.11
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 +59 -117
- package/dist/redis/index.d.ts +2 -16
- package/dist/redis/index.js +15 -111
- package/dist/{utils/redis_lock.d.ts → redis/redis_client.d.ts} +7 -1
- package/dist/{utils/redis_lock.js → redis/redis_client.js} +42 -3
- package/dist/redis/types.d.ts +7 -0
- package/dist/redis/types.js +2 -0
- 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
|
@@ -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 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);
|
|
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) {
|
|
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.endpoint = this.appConfig.env_args.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,66 @@ 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.endpoint}`);
|
|
66
|
+
this.wsProvider = new ethers_1.ethers.providers.WebSocketProvider(this.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.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.clearConnectionTimeout();
|
|
84
|
+
(0, dist_1.log_error)(`连接 WebSocket 失败: ${this.endpoint}`, error, '');
|
|
91
85
|
this.handleConnectionIssue();
|
|
92
86
|
}
|
|
93
87
|
});
|
|
94
88
|
}
|
|
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
89
|
handleConnectionIssue() {
|
|
109
90
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
-
if (
|
|
91
|
+
if (this.isReconnecting)
|
|
111
92
|
return;
|
|
93
|
+
this.isReconnecting = true;
|
|
112
94
|
this.isConnected = false;
|
|
113
|
-
this.
|
|
114
|
-
|
|
95
|
+
this.stopBlockListener();
|
|
96
|
+
this.cleanup();
|
|
115
97
|
this.reconnectAttempts++;
|
|
116
|
-
|
|
98
|
+
const delay = Math.min(this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay);
|
|
99
|
+
(0, dist_1.log_info)(`尝试重连 ${this.reconnectAttempts}/${this.maxReconnectAttempts}, 延迟 ${delay}ms, 节点: ${this.endpoint}`);
|
|
117
100
|
if (this.reconnectAttempts > this.maxReconnectAttempts) {
|
|
118
|
-
(0, dist_1.log_error)(
|
|
119
|
-
|
|
101
|
+
(0, dist_1.log_error)(`重连失败,尝试次数达到 ${this.maxReconnectAttempts} 次,程序退出`, new Error('Max reconnect attempts failed'), '');
|
|
102
|
+
this.appConfig.emit(common_1.EVENT_NAMES.WS_CONNECTION_FAILED, {
|
|
103
|
+
endpoint: this.endpoint,
|
|
104
|
+
attempts: this.maxReconnectAttempts,
|
|
105
|
+
});
|
|
106
|
+
process.exit(1);
|
|
120
107
|
}
|
|
121
108
|
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
|
-
}
|
|
109
|
+
yield this.connect();
|
|
110
|
+
this.isReconnecting = false;
|
|
133
111
|
});
|
|
134
112
|
}
|
|
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
113
|
startBlockListener() {
|
|
177
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
(
|
|
179
|
-
|
|
180
|
-
if (!this.isConnected || !this.wsProvider) {
|
|
181
|
-
(0, dist_1.log_warn)(`无法启动区块监听: WebSocket未连接`);
|
|
115
|
+
if (!this.wsProvider || !this.isConnected) {
|
|
116
|
+
(0, dist_1.log_warn)(`无法启动区块监听: WebSocket 未连接`);
|
|
182
117
|
return;
|
|
183
118
|
}
|
|
184
119
|
try {
|
|
@@ -189,28 +124,22 @@ class PoolEventListener {
|
|
|
189
124
|
try {
|
|
190
125
|
if (!this.isConnected || !this.isBlockListenerActive)
|
|
191
126
|
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
127
|
(0, dist_1.log_info)(`------- Block: ${blockNumber} -------`);
|
|
199
128
|
const previousBlockNumber = this.lastProcessedBlockNumber;
|
|
200
129
|
this.lastProcessedBlockNumber = blockNumber;
|
|
201
130
|
const blockUpdateEvent = {
|
|
202
|
-
blockNumber
|
|
203
|
-
previousBlockNumber
|
|
204
|
-
timestamp: Date.now()
|
|
131
|
+
blockNumber,
|
|
132
|
+
previousBlockNumber,
|
|
133
|
+
timestamp: Date.now(),
|
|
205
134
|
};
|
|
206
|
-
this.appConfig.emit(
|
|
135
|
+
this.appConfig.emit(common_1.EVENT_NAMES.BLOCK_UPDATE, blockUpdateEvent);
|
|
207
136
|
}
|
|
208
137
|
catch (error) {
|
|
209
138
|
(0, dist_1.log_error)(`处理区块事件出错:`, error, '');
|
|
210
139
|
}
|
|
211
140
|
}));
|
|
212
141
|
this.isBlockListenerActive = true;
|
|
213
|
-
(0, dist_1.log_info)(`区块监听已启动,使用WebSocket事件订阅方式`);
|
|
142
|
+
(0, dist_1.log_info)(`区块监听已启动,使用 WebSocket 事件订阅方式`);
|
|
214
143
|
}
|
|
215
144
|
catch (error) {
|
|
216
145
|
(0, dist_1.log_error)(`启动区块监听失败:`, error, '');
|
|
@@ -222,7 +151,21 @@ class PoolEventListener {
|
|
|
222
151
|
if (this.isBlockListenerActive && this.wsProvider) {
|
|
223
152
|
this.wsProvider.removeListener('block', () => { });
|
|
224
153
|
this.isBlockListenerActive = false;
|
|
225
|
-
(0, dist_1.log_info)(
|
|
154
|
+
(0, dist_1.log_info)(`区块监听器已停止`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
cleanup() {
|
|
158
|
+
if (this.wsProvider) {
|
|
159
|
+
try {
|
|
160
|
+
this.wsProvider.removeAllListeners();
|
|
161
|
+
if (this.wsProvider._websocket && this.wsProvider._websocket.readyState === 1) {
|
|
162
|
+
this.wsProvider._websocket.close(1000, 'Normal closure');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
(0, dist_1.log_error)(`清理 WebSocket 资源失败:`, error, '');
|
|
167
|
+
}
|
|
168
|
+
this.wsProvider = null;
|
|
226
169
|
}
|
|
227
170
|
}
|
|
228
171
|
isWSConnected() {
|
|
@@ -231,16 +174,15 @@ class PoolEventListener {
|
|
|
231
174
|
getConnectionDiagnostics() {
|
|
232
175
|
return {
|
|
233
176
|
isConnected: this.isConnected,
|
|
177
|
+
isReconnecting: this.isReconnecting,
|
|
234
178
|
isStarted: this.isStarted,
|
|
235
179
|
reconnectAttempts: this.reconnectAttempts,
|
|
236
|
-
|
|
237
|
-
wsEndpoint: this.appConfig.env_args.ws_endpoint,
|
|
180
|
+
endpoint: this.endpoint,
|
|
238
181
|
wsReadyState: this.wsProvider && this.wsProvider._websocket
|
|
239
182
|
? this.wsProvider._websocket.readyState
|
|
240
183
|
: null,
|
|
241
184
|
trackingPools: this.poolList.length,
|
|
242
185
|
lastProcessedBlock: this.lastProcessedBlockNumber,
|
|
243
|
-
metrics: Object.assign(Object.assign({}, this.metrics), { lastBlockTime: new Date(this.metrics.lastBlockTime).toISOString() })
|
|
244
186
|
};
|
|
245
187
|
}
|
|
246
188
|
}
|
package/dist/redis/index.d.ts
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
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
|
-
getLockValue(lock_key: string): Promise<string>;
|
|
15
|
-
setLockValue(lock_key: string, lock_value: string): Promise<void>;
|
|
16
|
-
}
|
|
1
|
+
export * from "./redis_client";
|
|
2
|
+
export * from "./types";
|
package/dist/redis/index.js
CHANGED
|
@@ -1,114 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
10
15
|
};
|
|
11
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports
|
|
13
|
-
|
|
14
|
-
class SimpleRedisClient {
|
|
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
|
-
getLockValue(lock_key) {
|
|
100
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
-
const redisClient = yield this.getRedisClient();
|
|
102
|
-
return yield redisClient.get(lock_key);
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
setLockValue(lock_key, lock_value) {
|
|
106
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
107
|
-
const redisClient = yield this.getRedisClient();
|
|
108
|
-
yield redisClient.set(lock_key, lock_value, {
|
|
109
|
-
EX: this.lockExpireSeconds
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
exports.SimpleRedisClient = SimpleRedisClient;
|
|
17
|
+
__exportStar(require("./redis_client"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RedisClientType } from "redis";
|
|
2
|
-
export declare class
|
|
2
|
+
export declare class SimpleRedisClient {
|
|
3
3
|
private lock_prefix;
|
|
4
4
|
private redisClient;
|
|
5
5
|
private lockMaxRetries;
|
|
@@ -11,4 +11,10 @@ export declare class RedisLock {
|
|
|
11
11
|
private acquireLock;
|
|
12
12
|
private releaseLock;
|
|
13
13
|
withLock<T>(lock_identifier: string, callback: () => Promise<T>): Promise<T>;
|
|
14
|
+
getValue(key: string): Promise<string>;
|
|
15
|
+
setValue(key: string, value: string, expireSeconds: number): Promise<any>;
|
|
16
|
+
hsetValue(key: string, field: string, value: string, expireSeconds: number): Promise<any>;
|
|
17
|
+
hgetvalue(key: string, field: string): Promise<any>;
|
|
18
|
+
hkeys(key: string): Promise<any>;
|
|
19
|
+
hgetall(key: string): Promise<any>;
|
|
14
20
|
}
|
|
@@ -9,9 +9,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.SimpleRedisClient = void 0;
|
|
13
13
|
const dist_1 = require("@clonegod/ttd-core/dist");
|
|
14
|
-
class
|
|
14
|
+
class SimpleRedisClient {
|
|
15
15
|
constructor(lock_prefix) {
|
|
16
16
|
this.lock_prefix = lock_prefix;
|
|
17
17
|
this.redisClient = null;
|
|
@@ -96,5 +96,44 @@ class RedisLock {
|
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
|
+
getValue(key) {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
const redisClient = yield this.getRedisClient();
|
|
102
|
+
return yield redisClient.get(key);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
setValue(key, value, expireSeconds) {
|
|
106
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
107
|
+
const redisClient = yield this.getRedisClient();
|
|
108
|
+
return yield redisClient.set(key, value, {
|
|
109
|
+
EX: expireSeconds
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
hsetValue(key, field, value, expireSeconds) {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
const redisClient = yield this.getRedisClient();
|
|
116
|
+
yield redisClient.hSet(key, field, value);
|
|
117
|
+
yield redisClient.hExpire(key, field, expireSeconds);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
hgetvalue(key, field) {
|
|
121
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
122
|
+
const redisClient = yield this.getRedisClient();
|
|
123
|
+
return yield redisClient.hGet(key, field);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
hkeys(key) {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
const redisClient = yield this.getRedisClient();
|
|
129
|
+
return yield redisClient.hKeys(key);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
hgetall(key) {
|
|
133
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
const redisClient = yield this.getRedisClient();
|
|
135
|
+
return yield redisClient.hGetAll(key);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
99
138
|
}
|
|
100
|
-
exports.
|
|
139
|
+
exports.SimpleRedisClient = SimpleRedisClient;
|
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;
|