@clonegod/ttd-bsc-common 3.0.5 → 3.0.7
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.js +14 -11
- package/dist/trade/check/base_tx_result_checker.d.ts +0 -1
- package/dist/trade/check/base_tx_result_checker.js +58 -31
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/pool_filter.d.ts +8 -0
- package/dist/utils/pool_filter.js +38 -0
- package/package.json +1 -1
|
@@ -69,13 +69,16 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
69
69
|
var _a;
|
|
70
70
|
const { price_msg, order_msg, slippage_bps, order_trace_id, pool_info } = context;
|
|
71
71
|
const { pair } = price_msg;
|
|
72
|
-
const {
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
const { isBuy, amount } = order_msg;
|
|
73
|
+
const { inputToken, outputToken } = this.determineInputOutputTokens(order_msg, pool_info);
|
|
74
|
+
const amountOutMin = this.calculateAmountOutMin(context, inputToken, outputToken);
|
|
75
|
+
(0, ttd_core_1.log_info)(`执行交易`, {
|
|
76
|
+
orderId: order_trace_id,
|
|
75
77
|
pair,
|
|
76
|
-
|
|
77
|
-
amount
|
|
78
|
-
|
|
78
|
+
direction: isBuy ? 'BUY' : 'SELL',
|
|
79
|
+
input: `${amount} ${inputToken.symbol}`,
|
|
80
|
+
outputMin: `${ethers_1.ethers.utils.formatUnits(amountOutMin, outputToken.decimals)} ${outputToken.symbol}`,
|
|
81
|
+
slippage: `${slippage_bps / 100}%`,
|
|
79
82
|
});
|
|
80
83
|
let maxAttempts = Math.min(Math.max(parseInt(process.env.NONCE_LOCK_MAX_RETRIES || '3'), 1), 3);
|
|
81
84
|
const callerHandle = yield this.callerManager.acquireCaller();
|
|
@@ -114,7 +117,7 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
114
117
|
};
|
|
115
118
|
const signedTx = yield caller.signTransaction(tx);
|
|
116
119
|
txid = ethers_1.ethers.utils.keccak256(signedTx);
|
|
117
|
-
(0, ttd_core_1.log_info)(
|
|
120
|
+
(0, ttd_core_1.log_info)(`交易已签名`, { txid, nonce, caller: caller.address, gasPriceGwei: realGasPriceGwei }, order_trace_id);
|
|
118
121
|
const tipNonce = nonce + 1;
|
|
119
122
|
const eoa_tip_transaction = (eoa_address) => __awaiter(this, void 0, void 0, function* () {
|
|
120
123
|
const transfer_amount_gwei = this.getBuilderTipAmoutGwei(context);
|
|
@@ -123,9 +126,9 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
123
126
|
});
|
|
124
127
|
const only_bundle = order_msg.is_dex_maker;
|
|
125
128
|
yield this.transactionSender.sendTransaction(signedTx, eoa_tip_transaction, order_trace_id, pair, only_bundle);
|
|
126
|
-
(0, ttd_core_1.log_info)(
|
|
127
|
-
pair,
|
|
128
|
-
attempt: i, caller: caller.address
|
|
129
|
+
(0, ttd_core_1.log_info)(`交易发送成功`, {
|
|
130
|
+
pair, direction: isBuy ? 'BUY' : 'SELL',
|
|
131
|
+
txid, attempt: i, caller: caller.address
|
|
129
132
|
}, order_trace_id);
|
|
130
133
|
return txid;
|
|
131
134
|
}
|
|
@@ -154,7 +157,7 @@ class AbstractDexTrade extends ttd_core_1.AbastrcatTrade {
|
|
|
154
157
|
}
|
|
155
158
|
} while (++i <= maxAttempts);
|
|
156
159
|
if (!txid) {
|
|
157
|
-
throw new Error(
|
|
160
|
+
throw new Error(`交易执行失败,已重试 ${maxAttempts} 次,orderId: ${order_trace_id}`);
|
|
158
161
|
}
|
|
159
162
|
return txid;
|
|
160
163
|
}
|
|
@@ -13,6 +13,60 @@ exports.BaseTxResultChecker = void 0;
|
|
|
13
13
|
const ttd_core_1 = require("@clonegod/ttd-core");
|
|
14
14
|
const trade_1 = require("@clonegod/ttd-core/dist/trade");
|
|
15
15
|
const ethers_1 = require("ethers");
|
|
16
|
+
class TradeResultSubscriber {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.ws = null;
|
|
19
|
+
this.connected = false;
|
|
20
|
+
this.listeners = new Map();
|
|
21
|
+
}
|
|
22
|
+
static getInstance() {
|
|
23
|
+
if (!TradeResultSubscriber.instance) {
|
|
24
|
+
TradeResultSubscriber.instance = new TradeResultSubscriber();
|
|
25
|
+
}
|
|
26
|
+
return TradeResultSubscriber.instance;
|
|
27
|
+
}
|
|
28
|
+
listen(txHash, callback, timeoutMs = 30000) {
|
|
29
|
+
const key = txHash.toLowerCase();
|
|
30
|
+
this.listeners.set(key, callback);
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
this.listeners.delete(key);
|
|
33
|
+
}, timeoutMs);
|
|
34
|
+
this.ensureConnected();
|
|
35
|
+
}
|
|
36
|
+
remove(txHash) {
|
|
37
|
+
this.listeners.delete(txHash.toLowerCase());
|
|
38
|
+
}
|
|
39
|
+
ensureConnected() {
|
|
40
|
+
if (this.ws && this.connected)
|
|
41
|
+
return;
|
|
42
|
+
const host = process.env.STREAM_TRADE_WS_HOST || '127.0.0.1';
|
|
43
|
+
const wsUrl = `ws://${host}:${ttd_core_1.SERVICE_PORT.STREAM_TRADE_WS}`;
|
|
44
|
+
this.ws = new ttd_core_1.WebSocketClient(wsUrl);
|
|
45
|
+
this.ws.onOpen(() => {
|
|
46
|
+
this.connected = true;
|
|
47
|
+
const addresses = (process.env.VAULT_ADDRESS || '').split(',').map(a => a.trim()).filter(Boolean);
|
|
48
|
+
for (const addr of addresses) {
|
|
49
|
+
this.ws.send(JSON.stringify({ address: addr }));
|
|
50
|
+
}
|
|
51
|
+
(0, ttd_core_1.log_info)(`TradeResultSubscriber connected: ${wsUrl}`);
|
|
52
|
+
});
|
|
53
|
+
this.ws.onMessage((msg) => {
|
|
54
|
+
if (msg.type !== 'TradeResult' || !msg.data)
|
|
55
|
+
return;
|
|
56
|
+
const { txHash, receipt } = msg.data;
|
|
57
|
+
if (!txHash || !receipt)
|
|
58
|
+
return;
|
|
59
|
+
const key = txHash.toLowerCase();
|
|
60
|
+
const callback = this.listeners.get(key);
|
|
61
|
+
if (callback) {
|
|
62
|
+
this.listeners.delete(key);
|
|
63
|
+
callback(receipt);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
this.ws.connect();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
TradeResultSubscriber.instance = null;
|
|
16
70
|
class BaseTxResultChecker extends trade_1.AbstractTransactionResultCheck {
|
|
17
71
|
constructor(env_args, event_emitter) {
|
|
18
72
|
super(env_args, event_emitter);
|
|
@@ -51,39 +105,12 @@ class BaseTxResultChecker extends trade_1.AbstractTransactionResultCheck {
|
|
|
51
105
|
}
|
|
52
106
|
on_subscibe_transaction() {
|
|
53
107
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
-
this.
|
|
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}`);
|
|
108
|
+
(0, ttd_core_1.log_info)(`Subscribing trade result, txid=${this.txid}`);
|
|
109
|
+
TradeResultSubscriber.getInstance().listen(this.txid, (receipt) => {
|
|
110
|
+
(0, ttd_core_1.log_info)(`Received transaction result via stream-trade: ${this.txid}`);
|
|
81
111
|
this.processTransactionResult(receipt, 'websocket')
|
|
82
|
-
.catch(err => (0, ttd_core_1.log_error)(`Error processing trade result: ${
|
|
83
|
-
.finally(() => ws.disconnect());
|
|
112
|
+
.catch(err => (0, ttd_core_1.log_error)(`Error processing trade result: ${this.txid}`, err));
|
|
84
113
|
});
|
|
85
|
-
ws.connect();
|
|
86
|
-
setTimeout(() => { ws.disconnect(); }, 30000);
|
|
87
114
|
});
|
|
88
115
|
}
|
|
89
116
|
processTransactionResult(txReceipt, source) {
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ethers } from "ethers";
|
|
|
2
2
|
import Decimal from "decimal.js";
|
|
3
3
|
export * from './gas_helper';
|
|
4
4
|
export * from './trade_direction';
|
|
5
|
+
export * from './pool_filter';
|
|
5
6
|
export declare const sleep: (ms: number) => Promise<void>;
|
|
6
7
|
export declare const formatPrice: (price: number, precision?: number) => string;
|
|
7
8
|
export declare const formatUnits: (value: ethers.BigNumber, decimals: number) => Decimal;
|
package/dist/utils/index.js
CHANGED
|
@@ -22,6 +22,7 @@ const ethers_1 = require("ethers");
|
|
|
22
22
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
23
23
|
__exportStar(require("./gas_helper"), exports);
|
|
24
24
|
__exportStar(require("./trade_direction"), exports);
|
|
25
|
+
__exportStar(require("./pool_filter"), exports);
|
|
25
26
|
const sleep = (ms) => {
|
|
26
27
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
27
28
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StandardPoolInfoType } from '@clonegod/ttd-core';
|
|
2
|
+
export interface PoolFilterParams {
|
|
3
|
+
poolAddress?: string;
|
|
4
|
+
poolName?: string;
|
|
5
|
+
feeRate?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildPoolFilterFromEnv(envArgs: any): PoolFilterParams;
|
|
8
|
+
export declare function filterPools(pools: StandardPoolInfoType[], filter: PoolFilterParams, label?: string): StandardPoolInfoType[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildPoolFilterFromEnv = buildPoolFilterFromEnv;
|
|
4
|
+
exports.filterPools = filterPools;
|
|
5
|
+
const ttd_core_1 = require("@clonegod/ttd-core");
|
|
6
|
+
function buildPoolFilterFromEnv(envArgs) {
|
|
7
|
+
return {
|
|
8
|
+
poolAddress: envArgs.quote_pool_address || undefined,
|
|
9
|
+
poolName: envArgs.quote_pool_name || undefined,
|
|
10
|
+
feeRate: envArgs.quote_pool_fee_rate || undefined,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function filterPools(pools, filter, label = '') {
|
|
14
|
+
const prefix = label ? `[${label}] ` : '';
|
|
15
|
+
let result = pools;
|
|
16
|
+
if (filter.poolAddress) {
|
|
17
|
+
result = pools.filter(p => p.pool_address.toLowerCase() === filter.poolAddress.toLowerCase());
|
|
18
|
+
}
|
|
19
|
+
else if (filter.poolName || filter.feeRate) {
|
|
20
|
+
result = pools.filter(p => {
|
|
21
|
+
if (filter.poolName && p.pool_name !== filter.poolName)
|
|
22
|
+
return false;
|
|
23
|
+
if (filter.feeRate && p.fee_rate !== filter.feeRate)
|
|
24
|
+
return false;
|
|
25
|
+
return true;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (result.length === 0 && pools.length > 0) {
|
|
29
|
+
(0, ttd_core_1.log_warn)(`${prefix}Pool filter matched 0 pools from ${pools.length}`, {
|
|
30
|
+
filter,
|
|
31
|
+
available: pools.map(p => `${p.pool_name}(${p.pool_address}, fee=${p.fee_rate})`),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
(0, ttd_core_1.log_info)(`${prefix}Pool filter: ${pools.length} → ${result.length}`, result.map(p => `${p.pool_name}(${p.pool_address}, fee=${p.fee_rate})`));
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|