@clonegod/ttd-base-common 1.0.7 → 1.0.9

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/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export * from './trade';
5
5
  export * from './types';
6
6
  export * from './utils';
7
7
  export * from './redis';
8
+ export * from './ws';
package/dist/index.js CHANGED
@@ -21,3 +21,4 @@ __exportStar(require("./trade"), exports);
21
21
  __exportStar(require("./types"), exports);
22
22
  __exportStar(require("./utils"), exports);
23
23
  __exportStar(require("./redis"), exports);
24
+ __exportStar(require("./ws"), exports);
@@ -4,7 +4,9 @@ import { DexConfig, EvmChainConfig } from "../types";
4
4
  export declare abstract class AbstractEvmDexTradePlus extends AbastrcatTrade {
5
5
  protected appConfig: AppConfig;
6
6
  protected group_wallets: ethers.Wallet[];
7
+ protected wallet: ethers.Wallet;
7
8
  protected provider: ethers.providers.JsonRpcProvider;
9
+ protected walletMode: 'single' | 'multi';
8
10
  protected approvedTokens: Map<string, Map<string, boolean>>;
9
11
  protected pairContracts: Map<string, ethers.Contract>;
10
12
  protected tokenContracts: Map<string, ethers.Contract>;
@@ -14,6 +16,9 @@ export declare abstract class AbstractEvmDexTradePlus extends AbastrcatTrade {
14
16
  constructor(appConfig: AppConfig);
15
17
  protected abstract initConfigs(): void;
16
18
  init(): Promise<void>;
19
+ protected getWalletMode(): 'single' | 'multi';
20
+ protected getSingleWallet(): ethers.Wallet;
21
+ protected getGroupWallets(): ethers.Wallet[];
17
22
  protected getTokenContract(tokenAddress: string): ethers.Contract;
18
23
  protected getTokenContractWithWallet(tokenAddress: string, wallet: ethers.Wallet): ethers.Contract;
19
24
  protected getGasPriceGwei(context: TradeContext): string;
@@ -17,6 +17,7 @@ class AbstractEvmDexTradePlus extends dist_1.AbastrcatTrade {
17
17
  constructor(appConfig) {
18
18
  super();
19
19
  this.appConfig = appConfig;
20
+ this.walletMode = 'multi';
20
21
  this.approvedTokens = new Map();
21
22
  this.pairContracts = new Map();
22
23
  this.tokenContracts = new Map();
@@ -27,18 +28,37 @@ class AbstractEvmDexTradePlus extends dist_1.AbastrcatTrade {
27
28
  }
28
29
  init() {
29
30
  return __awaiter(this, void 0, void 0, function* () {
30
- var _a;
31
31
  this.provider = new ethers_1.ethers.providers.JsonRpcProvider(this.chainConfig.rpcEndpoint);
32
- if (!process.env.WALLET_GROUP_IDS) {
33
- throw new Error('必须配置 WALLET_GROUP_IDS 环境变量来启用多钱包功能');
32
+ const walletGroupIds = process.env.WALLET_GROUP_IDS || '';
33
+ this.walletMode = walletGroupIds && walletGroupIds.trim().split(',').length > 0 ? 'multi' : 'single';
34
+ if (this.walletMode === 'multi') {
35
+ let wallet_infos = (0, dist_1.load_wallet_multi)(walletGroupIds.split(','), false);
36
+ this.group_wallets = wallet_infos.map(info => new ethers_1.ethers.Wallet(info.private_key, this.provider));
37
+ (0, dist_1.log_info)(`组钱包已初始化,数量: ${this.group_wallets.length}`, this.group_wallets.map(e => e.address));
38
+ }
39
+ else {
40
+ this.wallet = new ethers_1.ethers.Wallet(this.appConfig.trade_runtime.wallet.private_key, this.provider);
41
+ (0, dist_1.log_info)(`单钱包已初始化,walletAddress= ${this.wallet.address}`);
34
42
  }
35
- let wallet_infos = (0, dist_1.load_wallet_multi)(((_a = process.env.WALLET_GROUP_IDS) === null || _a === void 0 ? void 0 : _a.split(',')) || [], false);
36
- this.group_wallets = wallet_infos.map(info => new ethers_1.ethers.Wallet(info.private_key, this.provider));
37
- (0, dist_1.log_info)(`组钱包已初始化,数量: ${this.group_wallets.length}`, this.group_wallets.map(e => e.address));
38
43
  this.routerContract = new ethers_1.ethers.Contract(this.dexConfig.routerAddress, this.dexConfig.routerAbi, this.provider);
39
- (0, dist_1.log_info)(`${this.dexConfig.dexName} Router已初始化, 地址: ${this.dexConfig.routerAddress}, 钱包数量: ${this.group_wallets.length}`);
44
+ (0, dist_1.log_info)(`${this.dexConfig.dexName} Router已初始化, routerAddress= ${this.dexConfig.routerAddress}`);
40
45
  });
41
46
  }
47
+ getWalletMode() {
48
+ return this.walletMode;
49
+ }
50
+ getSingleWallet() {
51
+ if (this.walletMode !== 'single' || !this.wallet) {
52
+ throw new Error('Single wallet not available in multi-wallet mode or not initialized');
53
+ }
54
+ return this.wallet;
55
+ }
56
+ getGroupWallets() {
57
+ if (this.walletMode !== 'multi' || !this.group_wallets) {
58
+ throw new Error('Group wallets not available in single-wallet mode or not initialized');
59
+ }
60
+ return this.group_wallets;
61
+ }
42
62
  getTokenContract(tokenAddress) {
43
63
  if (!this.tokenContracts.has(tokenAddress)) {
44
64
  const tokenContract = new ethers_1.ethers.Contract(tokenAddress, common_1.ERC20_ABI, this.provider);
@@ -68,37 +88,70 @@ class AbstractEvmDexTradePlus extends dist_1.AbastrcatTrade {
68
88
  }
69
89
  preApproveAllWallets() {
70
90
  return __awaiter(this, arguments, void 0, function* (token_list = []) {
71
- if (!this.group_wallets || this.group_wallets.length === 0) {
72
- (0, dist_1.log_info)('No wallets available for pre-approval');
73
- return;
74
- }
75
- if (!token_list || token_list.length === 0) {
76
- token_list = Array.from(this.tokenContracts.keys());
77
- }
78
- (0, dist_1.log_info)(`Pre-approve: ${this.group_wallets.length} wallets, ${token_list.length} tokens`, token_list);
79
- const tokenAddresses = new Set();
80
- for (const token_address of token_list) {
81
- tokenAddresses.add(token_address.toLowerCase());
82
- }
83
- const tokens = Array.from(tokenAddresses);
84
- for (const wallet of this.group_wallets) {
91
+ if (this.walletMode === 'single') {
92
+ if (!this.wallet) {
93
+ (0, dist_1.log_info)('Single wallet not available for pre-approval');
94
+ return;
95
+ }
96
+ if (!token_list || token_list.length === 0) {
97
+ token_list = Array.from(this.tokenContracts.keys());
98
+ }
99
+ (0, dist_1.log_info)(`Pre-approve: single wallet ${this.wallet.address}, ${token_list.length} tokens`, token_list);
100
+ const tokenAddresses = new Set();
101
+ for (const token_address of token_list) {
102
+ tokenAddresses.add(token_address.toLowerCase());
103
+ }
104
+ const tokens = Array.from(tokenAddresses);
85
105
  try {
86
- (0, dist_1.log_info)(`Pre-approve: wallet ${wallet.address}`);
106
+ (0, dist_1.log_info)(`Pre-approve: wallet ${this.wallet.address}`);
87
107
  for (const tokenAddress of tokens) {
88
108
  try {
89
- yield this.approveTokenIfNeeded(wallet, tokenAddress);
109
+ yield this.approveTokenIfNeeded(this.wallet, tokenAddress);
90
110
  }
91
111
  catch (error) {
92
- console.warn(`Failed to pre-approve token ${tokenAddress} for wallet ${wallet.address}:`, error);
112
+ console.warn(`Failed to pre-approve token ${tokenAddress} for wallet ${this.wallet.address}:`, error);
93
113
  }
94
114
  }
95
- (0, dist_1.log_info)(`Pre-approve: wallet ${wallet.address} completed`);
115
+ (0, dist_1.log_info)(`Pre-approve: wallet ${this.wallet.address} completed`);
96
116
  }
97
117
  catch (error) {
98
- console.warn(`Failed to pre-approve tokens for wallet ${wallet.address}:`, error);
118
+ console.warn(`Failed to pre-approve tokens for wallet ${this.wallet.address}:`, error);
119
+ }
120
+ (0, dist_1.log_info)('Pre-approve: single wallet completed');
121
+ }
122
+ else {
123
+ if (!this.group_wallets || this.group_wallets.length === 0) {
124
+ (0, dist_1.log_info)('No wallets available for pre-approval');
125
+ return;
126
+ }
127
+ if (!token_list || token_list.length === 0) {
128
+ token_list = Array.from(this.tokenContracts.keys());
129
+ }
130
+ (0, dist_1.log_info)(`Pre-approve: ${this.group_wallets.length} wallets, ${token_list.length} tokens`, token_list);
131
+ const tokenAddresses = new Set();
132
+ for (const token_address of token_list) {
133
+ tokenAddresses.add(token_address.toLowerCase());
134
+ }
135
+ const tokens = Array.from(tokenAddresses);
136
+ for (const wallet of this.group_wallets) {
137
+ try {
138
+ (0, dist_1.log_info)(`Pre-approve: wallet ${wallet.address}`);
139
+ for (const tokenAddress of tokens) {
140
+ try {
141
+ yield this.approveTokenIfNeeded(wallet, tokenAddress);
142
+ }
143
+ catch (error) {
144
+ console.warn(`Failed to pre-approve token ${tokenAddress} for wallet ${wallet.address}:`, error);
145
+ }
146
+ }
147
+ (0, dist_1.log_info)(`Pre-approve: wallet ${wallet.address} completed`);
148
+ }
149
+ catch (error) {
150
+ console.warn(`Failed to pre-approve tokens for wallet ${wallet.address}:`, error);
151
+ }
99
152
  }
153
+ (0, dist_1.log_info)('Pre-approve: all wallets completed');
100
154
  }
101
- (0, dist_1.log_info)('Pre-approve: all wallets completed');
102
155
  });
103
156
  }
104
157
  approveTokenIfNeeded(wallet, tokenAddress) {
@@ -0,0 +1,29 @@
1
+ export interface OnchainPoolData {
2
+ address: string;
3
+ token0: string;
4
+ token1: string;
5
+ fee: number;
6
+ tickSpacing: number;
7
+ reserve0: string;
8
+ reserve1: string;
9
+ tick: number;
10
+ sqrtPriceX96: string;
11
+ liquidity: string;
12
+ }
13
+ export interface OnchainPoolChangeEvent {
14
+ pool_address: string;
15
+ type: string;
16
+ event_time: number;
17
+ data: {
18
+ blockNumber: number;
19
+ transactionIndex: number;
20
+ transactionHash: string;
21
+ amount0: string;
22
+ amount1: string;
23
+ reserve0: BigInt;
24
+ reserve1: BigInt;
25
+ tick: number;
26
+ sqrtPriceX96: BigInt;
27
+ liquidity: BigInt;
28
+ };
29
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ export * from './subscribe_v2_events';
2
+ export * from './subscribe_v3_events';
@@ -0,0 +1,18 @@
1
+ "use strict";
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);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./subscribe_v2_events"), exports);
18
+ __exportStar(require("./subscribe_v3_events"), exports);
@@ -0,0 +1,14 @@
1
+ export declare class UniswapV2AmmPoolEventsSubscriber {
2
+ private wsUrl;
3
+ private poolAddress;
4
+ private provider;
5
+ private poolContract;
6
+ private eventCallbacks;
7
+ private isConnected;
8
+ constructor(wsUrl: string, poolAddress: string);
9
+ initialize(): Promise<void>;
10
+ subscribe(eventType: string, callback: any): void;
11
+ unsubscribe(eventType: string): Promise<void>;
12
+ disconnect(): Promise<void>;
13
+ _reconnect(): void;
14
+ }
@@ -0,0 +1,173 @@
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.UniswapV2AmmPoolEventsSubscriber = void 0;
13
+ const ethers_1 = require("ethers");
14
+ const UNISWAP_V2_POOL_ABI = [
15
+ 'event Sync(uint112 reserve0, uint112 reserve1)',
16
+ 'event Mint(address indexed sender, uint amount0, uint amount1)',
17
+ 'event Burn(address indexed sender, uint amount0, uint amount1, address indexed to)'
18
+ ];
19
+ class UniswapV2AmmPoolEventsSubscriber {
20
+ constructor(wsUrl, poolAddress) {
21
+ this.wsUrl = wsUrl;
22
+ this.poolAddress = poolAddress;
23
+ this.provider = null;
24
+ this.poolContract = null;
25
+ this.eventCallbacks = {
26
+ sync: null,
27
+ mint: null,
28
+ burn: null
29
+ };
30
+ this.isConnected = false;
31
+ }
32
+ initialize() {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ try {
35
+ if (!this.wsUrl || !this.poolAddress) {
36
+ throw new Error(`wsUrl and poolAddress are required! wsUrl=${this.wsUrl} poolAddress=${this.poolAddress}`);
37
+ }
38
+ this.provider = new ethers_1.ethers.providers.WebSocketProvider(this.wsUrl);
39
+ this.poolContract = new ethers_1.ethers.Contract(this.poolAddress, UNISWAP_V2_POOL_ABI, this.provider);
40
+ this.isConnected = true;
41
+ console.log(`Connected to WebSocket: ${this.wsUrl} for pool: ${this.poolAddress}`);
42
+ this.provider._websocket.on('error', (error) => {
43
+ console.error('WebSocket Error:', error);
44
+ this.isConnected = false;
45
+ this._reconnect();
46
+ });
47
+ this.provider._websocket.on('close', (code, reason) => {
48
+ console.error('WebSocket Closed:', code, reason);
49
+ this.isConnected = false;
50
+ this._reconnect();
51
+ });
52
+ }
53
+ catch (error) {
54
+ console.error('Initialization Error:', error);
55
+ this.isConnected = false;
56
+ this._reconnect();
57
+ }
58
+ });
59
+ }
60
+ subscribe(eventType, callback) {
61
+ if (!this.poolContract) {
62
+ throw new Error('Contract not initialized. Call initialize() first.');
63
+ }
64
+ if (!['sync', 'mint', 'burn'].includes(eventType.toLowerCase())) {
65
+ throw new Error('Invalid event type. Use "sync", "mint", or "burn".');
66
+ }
67
+ this.eventCallbacks[eventType.toLowerCase()] = callback;
68
+ if (eventType.toLowerCase() === 'sync') {
69
+ this.poolContract.on('Sync', (reserve0, reserve1, event) => {
70
+ const data = {
71
+ pool_address: this.poolAddress,
72
+ type: 'sync',
73
+ event_time: Date.now(),
74
+ data: {
75
+ blockNumber: event.blockNumber,
76
+ transactionIndex: event.transactionIndex,
77
+ transactionHash: event.transactionHash,
78
+ amount0: '0',
79
+ amount1: '0',
80
+ reserve0: BigInt(reserve0.toString()),
81
+ reserve1: BigInt(reserve1.toString()),
82
+ tick: 0,
83
+ sqrtPriceX96: BigInt(0),
84
+ liquidity: BigInt(0),
85
+ }
86
+ };
87
+ callback(data);
88
+ });
89
+ }
90
+ else if (eventType.toLowerCase() === 'mint') {
91
+ this.poolContract.on('Mint', (sender, amount0, amount1, event) => {
92
+ const data = {
93
+ pool_address: this.poolAddress,
94
+ type: 'mint',
95
+ event_time: Date.now(),
96
+ data: {
97
+ blockNumber: event.blockNumber,
98
+ transactionIndex: event.transactionIndex,
99
+ transactionHash: event.transactionHash,
100
+ amount0: amount0.toString(),
101
+ amount1: amount1.toString(),
102
+ reserve0: BigInt(0),
103
+ reserve1: BigInt(0),
104
+ tick: 0,
105
+ sqrtPriceX96: BigInt(0),
106
+ liquidity: BigInt(0),
107
+ }
108
+ };
109
+ callback(data);
110
+ });
111
+ }
112
+ else if (eventType.toLowerCase() === 'burn') {
113
+ this.poolContract.on('Burn', (sender, amount0, amount1, to, event) => {
114
+ const data = {
115
+ pool_address: this.poolAddress,
116
+ type: 'burn',
117
+ event_time: Date.now(),
118
+ data: {
119
+ blockNumber: event.blockNumber,
120
+ transactionIndex: event.transactionIndex,
121
+ transactionHash: event.transactionHash,
122
+ amount0: amount0.toString(),
123
+ amount1: amount1.toString(),
124
+ reserve0: BigInt(0),
125
+ reserve1: BigInt(0),
126
+ tick: 0,
127
+ sqrtPriceX96: BigInt(0),
128
+ liquidity: BigInt(0),
129
+ }
130
+ };
131
+ callback(data);
132
+ });
133
+ }
134
+ }
135
+ unsubscribe(eventType) {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ if (!this.poolContract) {
138
+ throw new Error('Contract not initialized.');
139
+ }
140
+ if (!['sync', 'mint', 'burn'].includes(eventType.toLowerCase())) {
141
+ throw new Error('Invalid event type. Use "sync", "mint", or "burn".');
142
+ }
143
+ this.poolContract.removeAllListeners(eventType);
144
+ this.eventCallbacks[eventType.toLowerCase()] = null;
145
+ console.log(`Unsubscribed from ${eventType} events`);
146
+ });
147
+ }
148
+ disconnect() {
149
+ return __awaiter(this, void 0, void 0, function* () {
150
+ if (this.provider) {
151
+ yield this.provider.destroy();
152
+ this.provider = null;
153
+ this.poolContract = null;
154
+ this.isConnected = false;
155
+ console.log('Disconnected from WebSocket');
156
+ }
157
+ });
158
+ }
159
+ _reconnect() {
160
+ if (!this.isConnected) {
161
+ console.log('Attempting to reconnect...');
162
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
163
+ yield this.initialize();
164
+ for (const [eventType, callback] of Object.entries(this.eventCallbacks)) {
165
+ if (callback) {
166
+ this.subscribe(eventType, callback);
167
+ }
168
+ }
169
+ }), 2000);
170
+ }
171
+ }
172
+ }
173
+ exports.UniswapV2AmmPoolEventsSubscriber = UniswapV2AmmPoolEventsSubscriber;
@@ -0,0 +1,14 @@
1
+ export declare class UniswapV3PoolEventsSubscriber {
2
+ private wsUrl;
3
+ private poolAddress;
4
+ private provider;
5
+ private poolContract;
6
+ private eventCallbacks;
7
+ private isConnected;
8
+ constructor(wsUrl: string, poolAddress: string);
9
+ initialize(): Promise<void>;
10
+ subscribe(eventType: string, callback: any): void;
11
+ unsubscribe(eventType: string): Promise<void>;
12
+ disconnect(): Promise<void>;
13
+ _reconnect(): void;
14
+ }
@@ -0,0 +1,173 @@
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.UniswapV3PoolEventsSubscriber = void 0;
13
+ const ethers_1 = require("ethers");
14
+ const UNISWAP_V3_POOL_ABI = [
15
+ 'event Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)',
16
+ 'event Mint(address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)',
17
+ 'event Burn(address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)'
18
+ ];
19
+ class UniswapV3PoolEventsSubscriber {
20
+ constructor(wsUrl, poolAddress) {
21
+ this.wsUrl = wsUrl;
22
+ this.poolAddress = poolAddress;
23
+ this.provider = null;
24
+ this.poolContract = null;
25
+ this.eventCallbacks = {
26
+ swap: null,
27
+ mint: null,
28
+ burn: null
29
+ };
30
+ this.isConnected = false;
31
+ }
32
+ initialize() {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ try {
35
+ if (!this.wsUrl || !this.poolAddress) {
36
+ throw new Error(`wsUrl and poolAddress are required! wsUrl=${this.wsUrl} poolAddress=${this.poolAddress}`);
37
+ }
38
+ this.provider = new ethers_1.ethers.providers.WebSocketProvider(this.wsUrl);
39
+ this.poolContract = new ethers_1.ethers.Contract(this.poolAddress, UNISWAP_V3_POOL_ABI, this.provider);
40
+ this.isConnected = true;
41
+ console.log(`Connected to WebSocket: ${this.wsUrl} for pool: ${this.poolAddress}`);
42
+ this.provider._websocket.on('error', (error) => {
43
+ console.error('WebSocket Error:', error);
44
+ this.isConnected = false;
45
+ this._reconnect();
46
+ });
47
+ this.provider._websocket.on('close', (code, reason) => {
48
+ console.error('WebSocket Closed:', code, reason);
49
+ this.isConnected = false;
50
+ this._reconnect();
51
+ });
52
+ }
53
+ catch (error) {
54
+ console.error('Initialization Error:', error);
55
+ this.isConnected = false;
56
+ this._reconnect();
57
+ }
58
+ });
59
+ }
60
+ subscribe(eventType, callback) {
61
+ if (!this.poolContract) {
62
+ throw new Error('Contract not initialized. Call initialize() first.');
63
+ }
64
+ if (!['swap', 'mint', 'burn'].includes(eventType.toLowerCase())) {
65
+ throw new Error('Invalid event type. Use "swap", "mint", or "burn".');
66
+ }
67
+ this.eventCallbacks[eventType.toLowerCase()] = callback;
68
+ if (eventType.toLowerCase() === 'swap') {
69
+ this.poolContract.on('Swap', (sender, recipient, amount0, amount1, sqrtPriceX96, liquidity, tick, event) => {
70
+ const data = {
71
+ pool_address: this.poolAddress,
72
+ type: 'swap',
73
+ event_time: Date.now(),
74
+ data: {
75
+ blockNumber: event.blockNumber,
76
+ transactionIndex: event.transactionIndex,
77
+ transactionHash: event.transactionHash,
78
+ amount0: amount0.toString(),
79
+ amount1: amount1.toString(),
80
+ reserve0: BigInt(0),
81
+ reserve1: BigInt(0),
82
+ tick,
83
+ sqrtPriceX96: sqrtPriceX96.toString(),
84
+ liquidity: liquidity.toString(),
85
+ }
86
+ };
87
+ callback(data);
88
+ });
89
+ }
90
+ else if (eventType.toLowerCase() === 'mint') {
91
+ this.poolContract.on('Mint', (sender, owner, tickLower, tickUpper, amount, amount0, amount1, event) => {
92
+ const data = {
93
+ pool_address: this.poolAddress,
94
+ type: 'mint',
95
+ event_time: Date.now(),
96
+ data: {
97
+ blockNumber: event.blockNumber,
98
+ transactionIndex: event.transactionIndex,
99
+ transactionHash: event.transactionHash,
100
+ amount0: amount0.toString(),
101
+ amount1: amount1.toString(),
102
+ reserve0: BigInt(0),
103
+ reserve1: BigInt(0),
104
+ tick: 0,
105
+ sqrtPriceX96: BigInt(0),
106
+ liquidity: BigInt(0),
107
+ }
108
+ };
109
+ callback(data);
110
+ });
111
+ }
112
+ else if (eventType.toLowerCase() === 'burn') {
113
+ this.poolContract.on('Burn', (owner, tickLower, tickUpper, amount, amount0, amount1, event) => {
114
+ const data = {
115
+ pool_address: this.poolAddress,
116
+ type: 'burn',
117
+ event_time: Date.now(),
118
+ data: {
119
+ blockNumber: event.blockNumber,
120
+ transactionIndex: event.transactionIndex,
121
+ transactionHash: event.transactionHash,
122
+ amount0: amount0.toString(),
123
+ amount1: amount1.toString(),
124
+ reserve0: BigInt(0),
125
+ reserve1: BigInt(0),
126
+ tick: 0,
127
+ sqrtPriceX96: BigInt(0),
128
+ liquidity: BigInt(0),
129
+ }
130
+ };
131
+ callback(data);
132
+ });
133
+ }
134
+ }
135
+ unsubscribe(eventType) {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ if (!this.poolContract) {
138
+ throw new Error('Contract not initialized.');
139
+ }
140
+ if (!['swap', 'mint', 'burn'].includes(eventType.toLowerCase())) {
141
+ throw new Error('Invalid event type. Use "swap", "mint", or "burn".');
142
+ }
143
+ this.poolContract.removeAllListeners(eventType);
144
+ this.eventCallbacks[eventType.toLowerCase()] = null;
145
+ console.log(`Unsubscribed from ${eventType} events`);
146
+ });
147
+ }
148
+ disconnect() {
149
+ return __awaiter(this, void 0, void 0, function* () {
150
+ if (this.provider) {
151
+ yield this.provider.destroy();
152
+ this.provider = null;
153
+ this.poolContract = null;
154
+ this.isConnected = false;
155
+ console.log('Disconnected from WebSocket');
156
+ }
157
+ });
158
+ }
159
+ _reconnect() {
160
+ if (!this.isConnected) {
161
+ console.log('Attempting to reconnect...');
162
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
163
+ yield this.initialize();
164
+ for (const [eventType, callback] of Object.entries(this.eventCallbacks)) {
165
+ if (callback) {
166
+ this.subscribe(eventType, callback);
167
+ }
168
+ }
169
+ }), 2000);
170
+ }
171
+ }
172
+ }
173
+ exports.UniswapV3PoolEventsSubscriber = UniswapV3PoolEventsSubscriber;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-base-common",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Base common library",
5
5
  "license": "UNLICENSED",
6
6
  "main": "dist/index.js",