@clonegod/ttd-bsc-common 3.0.4 → 3.0.5
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/trade/abstract_dex_trade.d.ts +0 -1
- package/dist/trade/abstract_dex_trade.js +6 -28
- package/dist/trade/caller_manager.js +0 -1
- package/dist/trade/check/base_tx_result_checker.d.ts +15 -0
- package/dist/trade/check/base_tx_result_checker.js +123 -0
- package/dist/trade/check/index.d.ts +1 -1
- package/dist/trade/check/index.js +1 -1
- package/dist/trade/parse/base_parser.js +11 -11
- package/package.json +1 -1
|
@@ -28,7 +28,6 @@ export declare abstract class AbstractDexTrade extends AbastrcatTrade {
|
|
|
28
28
|
abstract encodeTradeData(context: TradeContext): TradeCalldata;
|
|
29
29
|
init(): Promise<void>;
|
|
30
30
|
execute(context: TradeContext): Promise<string>;
|
|
31
|
-
private subscribeTradeMonitor;
|
|
32
31
|
protected getGasPriceGwei(context: TradeContext): string;
|
|
33
32
|
protected getBuilderTipAmoutGwei(context: TradeContext): string;
|
|
34
33
|
protected buildTipTransferTx(to: string, transfer_amount_gwei: string, gas_price_gwei: string, nonce: number, wallet: ethers.Wallet): Promise<string>;
|
|
@@ -61,7 +61,6 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
61
61
|
chainId: this.chainConfig.chainId,
|
|
62
62
|
});
|
|
63
63
|
yield this.callerManager.init();
|
|
64
|
-
this.subscribeTradeMonitor();
|
|
65
64
|
(0, ttd_core_1.log_info)(`AbstractDexTrade initialized, vault=${this.tradeConfig.vaultAddress}, callers=${this.callerManager.getCallerCount()}`);
|
|
66
65
|
});
|
|
67
66
|
}
|
|
@@ -83,20 +82,20 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
83
82
|
const { wallet: caller, nonce: initialNonce } = callerHandle;
|
|
84
83
|
try {
|
|
85
84
|
let nonce = initialNonce;
|
|
86
|
-
let nonce_from_error =
|
|
85
|
+
let nonce_from_error = -1;
|
|
87
86
|
let txid = '';
|
|
88
87
|
let i = 1;
|
|
89
88
|
do {
|
|
90
89
|
try {
|
|
91
90
|
if (i > 1) {
|
|
92
|
-
if (nonce_from_error
|
|
91
|
+
if (nonce_from_error >= 0) {
|
|
93
92
|
nonce = nonce_from_error;
|
|
94
|
-
nonce_from_error =
|
|
93
|
+
nonce_from_error = -1;
|
|
95
94
|
(0, ttd_core_1.log_info)(`Attempt ${i}/${maxAttempts}, using nonce from error msg: ${nonce}`, {}, order_trace_id);
|
|
96
95
|
}
|
|
97
96
|
else {
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
nonce = yield this.provider.getTransactionCount(caller.address, 'pending');
|
|
98
|
+
(0, ttd_core_1.log_info)(`Attempt ${i}/${maxAttempts}, using nonce from chain: ${nonce}`, {}, order_trace_id);
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
const { executorId, data } = this.encodeTradeData(context);
|
|
@@ -148,7 +147,7 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
148
147
|
(0, ttd_core_1.log_info)(`Nonce error detected, will retry! i=${i}`, {}, order_trace_id);
|
|
149
148
|
if (errorMessage.includes('nonce too')) {
|
|
150
149
|
const correctNonce = this.extractNonceFromErrorMsg(errorMessage);
|
|
151
|
-
if (correctNonce !== null && correctNonce
|
|
150
|
+
if (correctNonce !== null && correctNonce >= 0) {
|
|
152
151
|
nonce_from_error = correctNonce;
|
|
153
152
|
}
|
|
154
153
|
}
|
|
@@ -164,27 +163,6 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
164
163
|
}
|
|
165
164
|
});
|
|
166
165
|
}
|
|
167
|
-
subscribeTradeMonitor() {
|
|
168
|
-
const host = process.env.STREAM_TRADE_HOST || '127.0.0.1';
|
|
169
|
-
const wsUrl = `ws://${host}:${ttd_core_1.SERVICE_PORT.STREAM_TRADE_WS}`;
|
|
170
|
-
const wsClient = new ttd_core_1.WebSocketClient(wsUrl);
|
|
171
|
-
wsClient.onOpen(() => {
|
|
172
|
-
wsClient.send(JSON.stringify({
|
|
173
|
-
address: this.tradeConfig.vaultAddress,
|
|
174
|
-
}));
|
|
175
|
-
(0, ttd_core_1.log_info)(`Subscribed to trade-monitor for ${this.tradeConfig.vaultAddress}`);
|
|
176
|
-
});
|
|
177
|
-
wsClient.onMessage((event) => {
|
|
178
|
-
if (event.type === 'TradeResult' && event.data) {
|
|
179
|
-
const { caller, callerNonce } = event.data;
|
|
180
|
-
if (caller) {
|
|
181
|
-
const nextNonce = callerNonce + 2;
|
|
182
|
-
this.callerManager.confirmNonce(caller, nextNonce).catch(err => (0, ttd_core_1.log_warn)(`Failed to confirm nonce from trade-monitor`, err));
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
wsClient.connect();
|
|
187
|
-
}
|
|
188
166
|
getGasPriceGwei(context) {
|
|
189
167
|
let { evm_gas_price_gwei } = context.trade_runtime.settings.strategy;
|
|
190
168
|
if (!evm_gas_price_gwei || evm_gas_price_gwei <= 0) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EnvArgs } from '@clonegod/ttd-core';
|
|
2
|
+
import { AbstractTransactionResultCheck } from "@clonegod/ttd-core/dist/trade";
|
|
3
|
+
import { ethers } from 'ethers';
|
|
4
|
+
import { EventEmitter } from 'events';
|
|
5
|
+
export declare abstract class BaseTxResultChecker extends AbstractTransactionResultCheck {
|
|
6
|
+
protected provider: ethers.providers.JsonRpcProvider;
|
|
7
|
+
constructor(env_args: EnvArgs, event_emitter: EventEmitter);
|
|
8
|
+
protected abstract createParser(): {
|
|
9
|
+
parseTransaction(txReceipt: any, poolInfo: any): Promise<any>;
|
|
10
|
+
};
|
|
11
|
+
check_tx_result_interval(): Promise<void>;
|
|
12
|
+
on_subscibe_transaction(): Promise<void>;
|
|
13
|
+
start_ws_listener(): Promise<void>;
|
|
14
|
+
private processTransactionResult;
|
|
15
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
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.BaseTxResultChecker = void 0;
|
|
13
|
+
const ttd_core_1 = require("@clonegod/ttd-core");
|
|
14
|
+
const trade_1 = require("@clonegod/ttd-core/dist/trade");
|
|
15
|
+
const ethers_1 = require("ethers");
|
|
16
|
+
class BaseTxResultChecker extends trade_1.AbstractTransactionResultCheck {
|
|
17
|
+
constructor(env_args, event_emitter) {
|
|
18
|
+
super(env_args, event_emitter);
|
|
19
|
+
this.provider = new ethers_1.ethers.providers.JsonRpcProvider(this.env_args.rpc_endpoint);
|
|
20
|
+
}
|
|
21
|
+
check_tx_result_interval() {
|
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
+
const check_start_time = Date.now();
|
|
24
|
+
const check_interval = parseInt(process.env.CHECK_TX_RESULT_INTERVAL_MILLS || '3000');
|
|
25
|
+
const check_timeout = parseInt(process.env.CHECK_TX_RESULT_TIMEOUT_MILLS || '15000');
|
|
26
|
+
if (check_interval >= check_timeout)
|
|
27
|
+
return;
|
|
28
|
+
const intervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
this.check_count += 1;
|
|
30
|
+
(0, ttd_core_1.log_info)(`check transaction start: seq=[${this.check_count}], txhash=${this.txid}, trace_id=${this.trace_id}`);
|
|
31
|
+
try {
|
|
32
|
+
if (Date.now() - check_start_time < check_timeout) {
|
|
33
|
+
let txReceipt = yield this.provider.getTransactionReceipt(this.txid);
|
|
34
|
+
if (!txReceipt)
|
|
35
|
+
return;
|
|
36
|
+
(0, ttd_core_1.log_info)(`Received transaction result via polling: ${this.txid}`);
|
|
37
|
+
clearInterval(intervalId);
|
|
38
|
+
yield this.processTransactionResult(txReceipt, 'interval');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
clearInterval(intervalId);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
clearInterval(intervalId);
|
|
46
|
+
(0, ttd_core_1.log_error)('parse transaction error!', err);
|
|
47
|
+
}
|
|
48
|
+
}), check_interval);
|
|
49
|
+
this.intervalId = intervalId;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
on_subscibe_transaction() {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
this.start_ws_listener();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
start_ws_listener() {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const host = process.env.STREAM_TRADE_WS_HOST || '127.0.0.1';
|
|
60
|
+
const wsUrl = `ws://${host}:${ttd_core_1.SERVICE_PORT.STREAM_TRADE_WS}`;
|
|
61
|
+
(0, ttd_core_1.log_info)(`Subscribing trade result from stream-trade: ${wsUrl}, txid=${this.txid}`);
|
|
62
|
+
const ws = new ttd_core_1.WebSocketClient(wsUrl);
|
|
63
|
+
ws.onOpen(() => {
|
|
64
|
+
const vaultAddress = process.env.VAULT_ADDRESS || '';
|
|
65
|
+
if (vaultAddress) {
|
|
66
|
+
ws.send(JSON.stringify({ address: vaultAddress }));
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
ws.onMessage((msg) => {
|
|
70
|
+
var _a;
|
|
71
|
+
if (msg.type !== 'TradeResult' || !msg.data)
|
|
72
|
+
return;
|
|
73
|
+
const { txHash, receipt } = msg.data;
|
|
74
|
+
if ((txHash === null || txHash === void 0 ? void 0 : txHash.toLowerCase()) !== ((_a = this.txid) === null || _a === void 0 ? void 0 : _a.toLowerCase()))
|
|
75
|
+
return;
|
|
76
|
+
if (!receipt) {
|
|
77
|
+
(0, ttd_core_1.log_warn)(`TradeResult received but no receipt: ${txHash}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
(0, ttd_core_1.log_info)(`Received transaction result via stream-trade: ${txHash}`);
|
|
81
|
+
this.processTransactionResult(receipt, 'websocket')
|
|
82
|
+
.catch(err => (0, ttd_core_1.log_error)(`Error processing trade result: ${txHash}`, err))
|
|
83
|
+
.finally(() => ws.disconnect());
|
|
84
|
+
});
|
|
85
|
+
ws.connect();
|
|
86
|
+
setTimeout(() => { ws.disconnect(); }, 30000);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
processTransactionResult(txReceipt, source) {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
if (ttd_core_1.LOG.debug) {
|
|
92
|
+
(0, ttd_core_1.writeFile)(`./dist/tx_receipt_${this.txid}_${source}.json`, JSON.stringify(txReceipt, null, 2));
|
|
93
|
+
}
|
|
94
|
+
if (this.trade_result_already_processed) {
|
|
95
|
+
(0, ttd_core_1.log_warn)(`trade_result_already_processed, ignore result from ${source}!`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const parser = this.createParser();
|
|
99
|
+
const swap_detail = yield parser.parseTransaction(txReceipt, this.pool_info);
|
|
100
|
+
let trade_result = this.map_swap_result_to_tx_result(swap_detail);
|
|
101
|
+
this.trade_result_already_processed = true;
|
|
102
|
+
if (this.intervalId) {
|
|
103
|
+
clearInterval(this.intervalId);
|
|
104
|
+
this.intervalId = null;
|
|
105
|
+
}
|
|
106
|
+
if (trade_result.success) {
|
|
107
|
+
this.event_emitter.emit(ttd_core_1.TRANSACTION_STATE_SUCCESS, trade_result);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.event_emitter.emit(ttd_core_1.TRANSACTION_STATE_FAILED, trade_result);
|
|
111
|
+
}
|
|
112
|
+
if (source === 'interval') {
|
|
113
|
+
console.log('--------------------- Transaction Result from Polling ---------------------');
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
console.log('===================== Transaction Result from stream-trade =====================');
|
|
117
|
+
}
|
|
118
|
+
console.log(JSON.stringify(trade_result, null, 2));
|
|
119
|
+
console.log('-----------------------------------------------------------------------------');
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.BaseTxResultChecker = BaseTxResultChecker;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./base_tx_result_checker";
|
|
@@ -14,4 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./
|
|
17
|
+
__exportStar(require("./base_tx_result_checker"), exports);
|
|
@@ -44,17 +44,17 @@ class BaseTxParser {
|
|
|
44
44
|
}
|
|
45
45
|
calculateGasFee(txReceipt) {
|
|
46
46
|
try {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
const toBN = (val) => {
|
|
48
|
+
if (!val)
|
|
49
|
+
return ethers_1.ethers.BigNumber.from(0);
|
|
50
|
+
if (ethers_1.ethers.BigNumber.isBigNumber(val))
|
|
51
|
+
return val;
|
|
52
|
+
if (val.hex)
|
|
53
|
+
return ethers_1.ethers.BigNumber.from(val.hex);
|
|
54
|
+
return ethers_1.ethers.BigNumber.from(val);
|
|
55
|
+
};
|
|
56
|
+
const gasUsed = toBN(txReceipt.gasUsed);
|
|
57
|
+
const effectiveGasPrice = toBN(txReceipt.effectiveGasPrice || txReceipt.gasPrice);
|
|
58
58
|
const gasFeeBN = gasUsed.mul(effectiveGasPrice);
|
|
59
59
|
const base_fee = Number(ethers_1.ethers.utils.formatEther(gasFeeBN));
|
|
60
60
|
const priority_fee = 0;
|