@clonegod/ttd-core 2.0.7 → 2.0.8

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.
@@ -22,6 +22,7 @@ class AppConfig extends events_1.default {
22
22
  this.env_args = new env_args_1.EnvArgs();
23
23
  let { chain_id, app_name, dex_id } = this.env_args;
24
24
  this.app_full_name = `${chain_id}_${dex_id}_${app_name}`;
25
+ global.app_config = this;
25
26
  }
26
27
  init() {
27
28
  return __awaiter(this, void 0, void 0, function* () {
@@ -0,0 +1,15 @@
1
+ import { TradeResponseType } from "../../types";
2
+ import { AbastrcatTrade } from "../trade/abstract_trade";
3
+ import { AbstractTransactionResultCheck } from "../trade/abstract_tx_check";
4
+ import { AppConfig } from "./app_config";
5
+ export declare class TradeAppConfig extends AppConfig {
6
+ is_already_subscribe_wallet_raw_txn: boolean;
7
+ trade_instance: AbastrcatTrade;
8
+ tx_result_checker: AbstractTransactionResultCheck;
9
+ constructor();
10
+ init(): Promise<void>;
11
+ init_trade_runtime(): Promise<void>;
12
+ subscribe_order_event(trade_instance: AbastrcatTrade, tx_result_checker: AbstractTransactionResultCheck): Promise<void>;
13
+ subscribe_wallet_raw_txn_event(): void;
14
+ cache_trade_result(trade_response: TradeResponseType): Promise<void>;
15
+ }
@@ -0,0 +1,68 @@
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.TradeAppConfig = void 0;
13
+ const __1 = require("..");
14
+ const handle_order_message_1 = require("../trade/handle_order_message");
15
+ const app_config_1 = require("./app_config");
16
+ class TradeAppConfig extends app_config_1.AppConfig {
17
+ constructor() {
18
+ super();
19
+ this.is_already_subscribe_wallet_raw_txn = false;
20
+ }
21
+ init() {
22
+ const _super = Object.create(null, {
23
+ init: { get: () => super.init }
24
+ });
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ yield _super.init.call(this);
27
+ });
28
+ }
29
+ init_trade_runtime() {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ try {
32
+ let { chain_id, dex_id, trade_group_id, trade_pair } = this.env_args;
33
+ this.trade_runtime = yield this.arb_cache.create_trade_runtime(chain_id, trade_group_id, dex_id, trade_pair);
34
+ this.trade_runtime.wallet_token_accounts = new Map();
35
+ }
36
+ catch (err) {
37
+ (0, __1.log_error)(`create_trade_runtime error!`, err);
38
+ yield (0, __1.sleep)(1000);
39
+ process.exit(0);
40
+ }
41
+ });
42
+ }
43
+ subscribe_order_event(trade_instance, tx_result_checker) {
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ let handler = (message) => (0, handle_order_message_1.handle_order_message)(this, trade_instance, tx_result_checker, message);
46
+ let group_id = this.trade_runtime.group.id;
47
+ let pair_name = this.trade_runtime.pair_name;
48
+ let dex_id = this.trade_runtime.dex_id;
49
+ yield this.arb_event_subscriber.subscribe_order_event(group_id, pair_name, dex_id, handler);
50
+ (0, __1.log_info)(`subscribe_order_event, success`, { dex_id, group_id, pair_name });
51
+ });
52
+ }
53
+ subscribe_wallet_raw_txn_event() {
54
+ throw new Error('not implemented');
55
+ }
56
+ cache_trade_result(trade_response) {
57
+ return __awaiter(this, void 0, void 0, function* () {
58
+ try {
59
+ (0, __1.log_info)(`cache_trade_result`, trade_response);
60
+ yield this.arb_cache.cache_trade_result(trade_response);
61
+ }
62
+ catch (err) {
63
+ (0, __1.log_error)(`cache_trade_result error!`, err);
64
+ }
65
+ });
66
+ }
67
+ }
68
+ exports.TradeAppConfig = TradeAppConfig;
@@ -1,2 +1,4 @@
1
+ import { AppConfig } from './app_config';
1
2
  export * from './env_args';
2
3
  export * from './app_config';
4
+ export declare const getGlobalAppConfig: () => AppConfig;
@@ -14,5 +14,14 @@ 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
+ exports.getGlobalAppConfig = void 0;
17
18
  __exportStar(require("./env_args"), exports);
18
19
  __exportStar(require("./app_config"), exports);
20
+ const getGlobalAppConfig = () => {
21
+ let app_config = global.app_config;
22
+ if (!app_config) {
23
+ throw new Error('app_config is not set');
24
+ }
25
+ return app_config;
26
+ };
27
+ exports.getGlobalAppConfig = getGlobalAppConfig;
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from './app_config';
8
8
  export * from './pool';
9
9
  export * from './quote';
10
10
  export * from './token';
11
+ export * from './trade';
11
12
  export declare const FAILED = "FAILED";
12
13
  export declare const SUCCESS = "SUCCESS";
13
14
  export declare const NOT_FOUND = "NOT_FOUND";
@@ -76,6 +77,11 @@ export declare enum CACHE_KEY_TYPE {
76
77
  ORDER_MESSAGE = "o:msg",
77
78
  ORDER_RESULT = "o:result"
78
79
  }
80
+ export declare enum LOCAL_EVENT_NAME {
81
+ EVENT_POOL_ACCOUNT_CHANGE = "EVENT_POOL_ACCOUNT_CHANGE",
82
+ EVENT_WALLET_TRANSACTION = "EVENT_WALLET_TRANSACTION",
83
+ EVENT_WALLET_TRANSACTION_NEW_TXID = "EVENT_WALLET_TRANSACTION_NEW_TXID"
84
+ }
79
85
  export declare const format_symbol_name: (symbol: string) => string;
80
86
  export declare const format_unique_orderbook_id: (chain_id: CHAIN_ID, dex_id: DEX_ID, pool_id: string, fee_rate: number) => string;
81
87
  export declare const parse_unique_orderbook_id: (unique_orderbook_id: string) => UniqueOrderbookIdType;
package/dist/index.js CHANGED
@@ -48,8 +48,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
48
48
  return (mod && mod.__esModule) ? mod : { "default": mod };
49
49
  };
50
50
  Object.defineProperty(exports, "__esModule", { value: true });
51
- exports.uuid = exports.DATE_TIME_FORMAT_NO_WHITESPACE = exports.DATE_TIME_FORMAT_DEFAULT = exports.to_json_str = exports.DecimalUtil = exports.generateRandomNumber = exports.LOG = exports._active_log_level = exports.LOG_LEVEL = exports.REDIS_EVENT_TYPE_TRADE_INSTANCE_CHANGE = exports.REDIS_EVENT_TYPE_ORDER = exports.REDIS_EVENT_TYPE_QUOTE = exports.REDIS_EVENT_TYPE_CONFIG_CHANGE = exports.REDIS_EVENT_CHANNEL = exports.get_tx_result_channel_name = exports.get_wallet_raw_tx_channel_name = exports.get_order_channel_name = exports.get_quote_channel_name = exports.get_config_channel_name = exports.get_cache_key = exports.getArbEventSubscriber = exports.getArbEventPublisher = exports.getArbCache = exports.getRedisCommamd = exports.getLoadingCache = exports.getRedisCache = exports.format_order_lock_key = exports.format_unique_order_msg_id = exports.parse_unique_orderbook_id = exports.format_unique_orderbook_id = exports.format_symbol_name = exports.CACHE_KEY_TYPE = exports.OnChainDataSubscribeType = exports.TradeErrorCodeType = exports.SystemErrorCodeType = exports.TRADE_TYPE = exports.GROUP_ID = exports.DEX_ID = exports.CHAIN_ID = exports.STREAMING_TRANSACTION_CONFIRMED = exports.TRANSACTION_STATE_FAILED = exports.TRANSACTION_STATE_SUCCESS = exports.TRANSACTION_STATE_PROCESSING = exports.QUOTE_AMOUNT_USD_MAX = exports.QUOTE_AMOUNT_USD_MIN = exports.REGEX_HEX_PREFIX = exports.PROCESSING = exports.NOT_FOUND = exports.SUCCESS = exports.FAILED = void 0;
52
- exports.execute_bash = exports.inspect_arb_local_cache = exports.save_trade_execution_logs = exports.parse_trade_cmdline_args = exports.get_input_out_token_fix = exports.get_input_out_token = exports.calc_amount_in_token = exports.estimate_amount_in_token = exports.failed = exports.success = exports.home_dir = exports.postJSON = exports.deep_merge_object = exports.isArray = exports.isTrue = exports.deep_clone = void 0;
51
+ exports.DATE_TIME_FORMAT_NO_WHITESPACE = exports.DATE_TIME_FORMAT_DEFAULT = exports.to_json_str = exports.DecimalUtil = exports.generateRandomNumber = exports.LOG = exports._active_log_level = exports.LOG_LEVEL = exports.REDIS_EVENT_TYPE_TRADE_INSTANCE_CHANGE = exports.REDIS_EVENT_TYPE_ORDER = exports.REDIS_EVENT_TYPE_QUOTE = exports.REDIS_EVENT_TYPE_CONFIG_CHANGE = exports.REDIS_EVENT_CHANNEL = exports.get_tx_result_channel_name = exports.get_wallet_raw_tx_channel_name = exports.get_order_channel_name = exports.get_quote_channel_name = exports.get_config_channel_name = exports.get_cache_key = exports.getArbEventSubscriber = exports.getArbEventPublisher = exports.getArbCache = exports.getRedisCommamd = exports.getLoadingCache = exports.getRedisCache = exports.format_order_lock_key = exports.format_unique_order_msg_id = exports.parse_unique_orderbook_id = exports.format_unique_orderbook_id = exports.format_symbol_name = exports.LOCAL_EVENT_NAME = exports.CACHE_KEY_TYPE = exports.OnChainDataSubscribeType = exports.TradeErrorCodeType = exports.SystemErrorCodeType = exports.TRADE_TYPE = exports.GROUP_ID = exports.DEX_ID = exports.CHAIN_ID = exports.STREAMING_TRANSACTION_CONFIRMED = exports.TRANSACTION_STATE_FAILED = exports.TRANSACTION_STATE_SUCCESS = exports.TRANSACTION_STATE_PROCESSING = exports.QUOTE_AMOUNT_USD_MAX = exports.QUOTE_AMOUNT_USD_MIN = exports.REGEX_HEX_PREFIX = exports.PROCESSING = exports.NOT_FOUND = exports.SUCCESS = exports.FAILED = void 0;
52
+ exports.execute_bash = exports.inspect_arb_local_cache = exports.save_trade_execution_logs = exports.parse_trade_cmdline_args = exports.get_input_out_token_fix = exports.get_input_out_token = exports.calc_amount_in_token = exports.estimate_amount_in_token = exports.failed = exports.success = exports.home_dir = exports.postJSON = exports.deep_merge_object = exports.isArray = exports.isTrue = exports.deep_clone = exports.uuid = void 0;
53
53
  exports._caller = _caller;
54
54
  exports.log_trace = log_trace;
55
55
  exports.log_debug = log_debug;
@@ -87,6 +87,7 @@ __exportStar(require("./app_config"), exports);
87
87
  __exportStar(require("./pool"), exports);
88
88
  __exportStar(require("./quote"), exports);
89
89
  __exportStar(require("./token"), exports);
90
+ __exportStar(require("./trade"), exports);
90
91
  const short = require('short-uuid');
91
92
  const exec = require('util').promisify(require('child_process').exec);
92
93
  exports.FAILED = 'FAILED';
@@ -165,6 +166,12 @@ var CACHE_KEY_TYPE;
165
166
  CACHE_KEY_TYPE["ORDER_MESSAGE"] = "o:msg";
166
167
  CACHE_KEY_TYPE["ORDER_RESULT"] = "o:result";
167
168
  })(CACHE_KEY_TYPE || (exports.CACHE_KEY_TYPE = CACHE_KEY_TYPE = {}));
169
+ var LOCAL_EVENT_NAME;
170
+ (function (LOCAL_EVENT_NAME) {
171
+ LOCAL_EVENT_NAME["EVENT_POOL_ACCOUNT_CHANGE"] = "EVENT_POOL_ACCOUNT_CHANGE";
172
+ LOCAL_EVENT_NAME["EVENT_WALLET_TRANSACTION"] = "EVENT_WALLET_TRANSACTION";
173
+ LOCAL_EVENT_NAME["EVENT_WALLET_TRANSACTION_NEW_TXID"] = "EVENT_WALLET_TRANSACTION_NEW_TXID";
174
+ })(LOCAL_EVENT_NAME || (exports.LOCAL_EVENT_NAME = LOCAL_EVENT_NAME = {}));
168
175
  const format_symbol_name = (symbol) => {
169
176
  return symbol.replace('USDC', 'USDT')
170
177
  .replace('WTRX', 'TRX')
@@ -0,0 +1,2 @@
1
+ import { FormattedTokenPrice } from "../..";
2
+ export declare const fetchPriceFromCache: (token_address_list: string[]) => Promise<Map<string, FormattedTokenPrice>>;
@@ -0,0 +1,55 @@
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.fetchPriceFromCache = void 0;
13
+ const __1 = require("../..");
14
+ const fetchPriceFromCache = (token_address_list) => __awaiter(void 0, void 0, void 0, function* () {
15
+ let result = new Map();
16
+ let global_app_config = (0, __1.getGlobalAppConfig)();
17
+ if (!global_app_config) {
18
+ (0, __1.log_warn)('global_app_config is not set, skip get token price from cache');
19
+ return result;
20
+ }
21
+ let token_price_timeout_seconds = 600;
22
+ let all_token_list = yield global_app_config.arb_cache.get_token_list();
23
+ let token_list = all_token_list.filter(e => token_address_list.includes(e.address) && !(0, __1.isEmpty)(e.market_price) && !(0, __1.isEmpty)(e.update_time));
24
+ for (let token_info of token_list) {
25
+ if ((0, __1.isEmpty)(token_info.market_price) || (0, __1.isEmpty)(token_info.update_time)) {
26
+ continue;
27
+ }
28
+ try {
29
+ let last_update_time = token_info.update_time;
30
+ let diff_seconds = Math.floor((Date.now() - (0, __1.parseDateTimeStrToMills)(last_update_time)) / 1000);
31
+ if (diff_seconds > token_price_timeout_seconds) {
32
+ (0, __1.log_warn)(`token price is too old, skip`, {
33
+ symbol: token_info.symbol,
34
+ last_update_time,
35
+ current_time: (0, __1.getCurDateTime)(),
36
+ diff_seconds,
37
+ price_timeout_seconds: token_price_timeout_seconds,
38
+ });
39
+ }
40
+ else {
41
+ result.set(token_info.address, {
42
+ address: token_info.address,
43
+ price: token_info.market_price,
44
+ update_time: token_info.update_time,
45
+ });
46
+ (0, __1.log_info)(`get token price from cache success: ${token_info.symbol} ${token_info.address} ${token_info.market_price}, ${token_info.update_time}, diff_seconds: ${diff_seconds}`);
47
+ }
48
+ }
49
+ catch (err) {
50
+ (0, __1.log_error)(`get token price from cache failed`, err);
51
+ }
52
+ }
53
+ return result;
54
+ });
55
+ exports.fetchPriceFromCache = fetchPriceFromCache;
@@ -17,11 +17,18 @@ require('dotenv').config();
17
17
  const axios_1 = __importDefault(require("axios"));
18
18
  const index_1 = require("../../index");
19
19
  const gecko_terminal_1 = require("./gecko_terminal");
20
+ const cached_price_1 = require("./cached_price");
20
21
  function get_bsc_token_price_info(addresses) {
21
22
  return __awaiter(this, void 0, void 0, function* () {
22
23
  addresses = addresses.map(addr => addr.toLowerCase());
23
24
  const result = new Map();
24
25
  const PRICE_CHANNELS = [
26
+ {
27
+ name: 'CachedPrice',
28
+ fetchFn: cached_price_1.fetchPriceFromCache,
29
+ batchSize: 100,
30
+ batchDelay: 1000,
31
+ },
25
32
  {
26
33
  name: 'PancakeSwap',
27
34
  fetchFn: fetchPriceFromPancakeSwap,
@@ -0,0 +1,5 @@
1
+ import { TradeContext } from "./trade_context";
2
+ export declare abstract class AbastrcatTrade {
3
+ abstract init(): void;
4
+ abstract execute(context: TradeContext): Promise<string>;
5
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbastrcatTrade = void 0;
4
+ class AbastrcatTrade {
5
+ }
6
+ exports.AbastrcatTrade = AbastrcatTrade;
@@ -0,0 +1,25 @@
1
+ import { EventEmitter } from 'events';
2
+ import { EnvArgs } from "..";
3
+ import { OrderMessageType, PriceMessageType, StandardPoolInfoType, StandardSwapDetailType, TradeResultType } from "../../types";
4
+ import { TradeContext } from "./trade_context";
5
+ export declare abstract class AbstractTransactionResultCheck {
6
+ env_args: EnvArgs;
7
+ event_emitter: EventEmitter;
8
+ wallet: string;
9
+ context: TradeContext;
10
+ group_id: string;
11
+ txid: string;
12
+ trace_id: string;
13
+ price_msg: PriceMessageType;
14
+ order_msg: OrderMessageType;
15
+ pool_info: StandardPoolInfoType;
16
+ intervalId: any;
17
+ check_count: number;
18
+ trade_result_already_processed: boolean;
19
+ constructor(env_args: EnvArgs, event_emitter: EventEmitter, context: TradeContext, txid: string);
20
+ init_tx_status(): this;
21
+ check(): Promise<void>;
22
+ abstract check_tx_result_interval(): void;
23
+ abstract on_subscibe_transaction(): void;
24
+ map_swap_result_to_tx_result(swap_result: StandardSwapDetailType): TradeResultType;
25
+ }
@@ -0,0 +1,131 @@
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.AbstractTransactionResultCheck = void 0;
13
+ const __1 = require("..");
14
+ class AbstractTransactionResultCheck {
15
+ constructor(env_args, event_emitter, context, txid) {
16
+ this.env_args = env_args;
17
+ this.event_emitter = event_emitter;
18
+ this.context = context;
19
+ this.group_id = context.group_id;
20
+ this.wallet = context.trade_runtime.wallet.public_key;
21
+ this.txid = txid;
22
+ this.price_msg = context.price_msg;
23
+ this.order_msg = context.order_msg;
24
+ this.pool_info = context.pool_info;
25
+ this.trace_id = context.order_msg.order_trace_id;
26
+ this.check_count = 0;
27
+ this.trade_result_already_processed = false;
28
+ }
29
+ init_tx_status() {
30
+ let empty_trade_result = JSON.parse(JSON.stringify({
31
+ group_id: this.context.group_id,
32
+ txid: this.txid
33
+ }));
34
+ this.event_emitter.emit(__1.TRANSACTION_STATE_PROCESSING, empty_trade_result);
35
+ return this;
36
+ }
37
+ check() {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ this.check_tx_result_interval();
40
+ this.on_subscibe_transaction();
41
+ });
42
+ }
43
+ map_swap_result_to_tx_result(swap_result) {
44
+ let { success, error_code, wallet, block_number, block_time: order_block_time, txid, tx_price, tokenA, tokenB, gas_fee } = swap_result;
45
+ let { pool_name, is_reverse_token } = this.pool_info;
46
+ let { chain_id, dex_id, unique_orderbook_id, pair, price_id, time: quote_time, ask, bid } = this.price_msg;
47
+ let { group_id, unique_order_msg_id, order_send_time, order_recv_time, order_submit_time, aToB } = this.order_msg;
48
+ let order_price = aToB ? bid.price : ask.price;
49
+ let server_info = (0, __1.getServerInfo)();
50
+ let order_end_time = Date.now();
51
+ let start_time = order_recv_time;
52
+ let end_time = order_end_time;
53
+ let total_time = end_time - start_time;
54
+ let total_order_time = total_time;
55
+ let time = {
56
+ block_time: quote_time.block_time,
57
+ stream_time: quote_time.stream_time,
58
+ quote_start_time: quote_time.quote_start_time,
59
+ quote_end_time: quote_time.quote_end_time,
60
+ price_time: quote_time.price_time,
61
+ total_quote_time: quote_time.total_quote_time,
62
+ order_send_time,
63
+ order_recv_time,
64
+ order_submit_time,
65
+ order_block_time,
66
+ order_end_time,
67
+ total_order_time,
68
+ };
69
+ let broadcast = [];
70
+ broadcast.push({
71
+ rpc: {
72
+ read: 'qn',
73
+ write: 'qn'
74
+ },
75
+ type: 'mainnet',
76
+ fee: gas_fee
77
+ });
78
+ let trade_balance_change = {
79
+ tokenA: {
80
+ symbol: tokenA.symbol,
81
+ address: tokenA.address,
82
+ pre_bal: tokenA.pre_bal,
83
+ post_bal: tokenA.post_bal,
84
+ change: Number(tokenA.change),
85
+ decimals: tokenA.decimals,
86
+ },
87
+ tokenB: {
88
+ symbol: tokenB.symbol,
89
+ address: tokenB.address,
90
+ pre_bal: tokenB.pre_bal,
91
+ post_bal: tokenB.post_bal,
92
+ change: Number(tokenB.change),
93
+ decimals: tokenB.decimals,
94
+ },
95
+ };
96
+ if (is_reverse_token) {
97
+ let { tokenA, tokenB } = trade_balance_change;
98
+ trade_balance_change.tokenA = tokenB;
99
+ trade_balance_change.tokenB = tokenA;
100
+ }
101
+ let trade_extra_info = {
102
+ time,
103
+ broadcast,
104
+ server_info,
105
+ };
106
+ const c_id = this.order_msg.c_id || '';
107
+ const trade_result = {
108
+ success,
109
+ error_code,
110
+ start_time,
111
+ end_time,
112
+ total_time,
113
+ group_id,
114
+ wallet,
115
+ chain_id,
116
+ pair,
117
+ dex_id,
118
+ txid,
119
+ unique_orderbook_id,
120
+ unique_order_msg_id,
121
+ order_price,
122
+ aToB,
123
+ tx_price,
124
+ balance: trade_balance_change,
125
+ execution: trade_extra_info,
126
+ c_id
127
+ };
128
+ return trade_result;
129
+ }
130
+ }
131
+ exports.AbstractTransactionResultCheck = AbstractTransactionResultCheck;
@@ -0,0 +1,6 @@
1
+ import { AppConfig } from "../app_config";
2
+ import { TradeAppConfig } from "../app_config/app_trade_config";
3
+ import { AbastrcatTrade } from "./abstract_trade";
4
+ import { AbstractTransactionResultCheck } from "./abstract_tx_check";
5
+ export declare const try_lock_order_msg: (appConfig: AppConfig, order_msg: any) => Promise<boolean>;
6
+ export declare const handle_order_message: (trade_appconfig: TradeAppConfig, trade_instance: AbastrcatTrade, tx_result_checker: AbstractTransactionResultCheck, recv_order_msg: string) => Promise<void>;
@@ -0,0 +1,117 @@
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.handle_order_message = exports.try_lock_order_msg = void 0;
13
+ const __1 = require("..");
14
+ const trade_context_1 = require("./trade_context");
15
+ const check_parse_order_msg = (appConfig, order_msg) => __awaiter(void 0, void 0, void 0, function* () {
16
+ let { unique_orderbook_id, price_id, group_id, unique_order_msg_id } = order_msg;
17
+ const runtime_group_id = appConfig.trade_runtime.group.id;
18
+ if (group_id !== runtime_group_id) {
19
+ throw new Error(`group_id not match!!! ${(0, __1.to_json_str)({ group_id, runtime_group_id })}`);
20
+ }
21
+ if ((0, __1.isEmpty)(unique_order_msg_id)) {
22
+ throw new Error(`unique_order_msg_id is empty or null! unique_order_msg_id=${unique_order_msg_id}`);
23
+ }
24
+ let price_msg = yield appConfig.arb_cache.get_price_message(price_id);
25
+ if ((0, __1.isEmpty)(price_msg)) {
26
+ throw new Error(`price_msg not found in the cache! price_id=${price_id}`);
27
+ }
28
+ let id_parts = (0, __1.parse_unique_orderbook_id)(unique_orderbook_id);
29
+ if (id_parts.dex_id != price_msg.dex_id ||
30
+ id_parts.pool_id != price_msg.pool_id) {
31
+ (0, __1.log_warn)(`check data: order_msg VS price_msg, not match!!!`, {
32
+ order_msg,
33
+ uinique_orderbook: id_parts,
34
+ price_msg,
35
+ });
36
+ }
37
+ return {
38
+ price_msg,
39
+ id_parts
40
+ };
41
+ });
42
+ const try_lock_order_msg = (appConfig, order_msg) => __awaiter(void 0, void 0, void 0, function* () {
43
+ let { chain_id, group_id, price_id, order_trace_id } = order_msg;
44
+ let lock_order_key = (0, __1.format_order_lock_key)(chain_id, group_id, price_id, order_trace_id);
45
+ (0, __1.log_info)(`try_lock_order_msg, key=${lock_order_key}`);
46
+ let is_lock_success = yield appConfig.arb_cache.redis_cmd.set_nx(lock_order_key, '');
47
+ if (is_lock_success) {
48
+ (0, __1.log_info)(`try_lock_order_msg, key=${lock_order_key}, success`);
49
+ appConfig.arb_cache.redis_cmd.expire(lock_order_key, 60)
50
+ .then(res => (0, __1.log_trace)(`expire lock: key=${lock_order_key}, success`))
51
+ .catch(err => (0, __1.log_error)(`expire lock: key=${lock_order_key}, error!`, err));
52
+ }
53
+ else {
54
+ (0, __1.log_info)(`try_lock_order_msg, key=${lock_order_key}, acquire lock failed!`);
55
+ }
56
+ return is_lock_success;
57
+ });
58
+ exports.try_lock_order_msg = try_lock_order_msg;
59
+ const handle_order_message = (trade_appconfig, trade_instance, tx_result_checker, recv_order_msg) => __awaiter(void 0, void 0, void 0, function* () {
60
+ (0, __1.new_line)(3);
61
+ console.log(`=================================================================================`);
62
+ console.log(`| NEW ORDER MESSAGE |`);
63
+ console.log(`=================================================================================`);
64
+ (0, __1.log_info)(`handle_order_message, on message: `, recv_order_msg);
65
+ let order_event_message = JSON.parse(recv_order_msg);
66
+ if (__1.LOG.debug) {
67
+ (0, __1.log_debug)(`order_event_msg`, order_event_message);
68
+ }
69
+ let { event_time, event_type, group_id, data: order_msg } = order_event_message;
70
+ let { price_msg, id_parts } = yield check_parse_order_msg(trade_appconfig, order_msg);
71
+ let { order_trace_id } = order_msg;
72
+ let { chain_id, dex_id, pool_id, fee_rate } = id_parts;
73
+ if (process.env.ENABLE_MULTIPLE_PROCESS === 'true') {
74
+ let lock_order = yield (0, exports.try_lock_order_msg)(trade_appconfig, order_msg);
75
+ if (!lock_order) {
76
+ (0, __1.log_warn)(`try lock order failed!`, {
77
+ chain_id, group_id, order_trace_id
78
+ });
79
+ return;
80
+ }
81
+ }
82
+ let context;
83
+ let txid = '';
84
+ let order_submit_result;
85
+ try {
86
+ context = new trade_context_1.TradeContext(price_msg, order_msg);
87
+ let { env_args } = trade_appconfig;
88
+ yield context.init(trade_appconfig);
89
+ txid = yield trade_instance.execute(context);
90
+ order_msg.order_submit_time = Date.now();
91
+ order_submit_result = {
92
+ success: true,
93
+ msg: 'SUCCESS',
94
+ txid
95
+ };
96
+ global.event_emitter = trade_appconfig;
97
+ tx_result_checker.init_tx_status().check();
98
+ trade_appconfig.subscribe_wallet_raw_txn_event();
99
+ }
100
+ catch (err) {
101
+ (0, __1.log_error)(`handle_order_message error!`, err);
102
+ order_submit_result = {
103
+ success: false,
104
+ msg: (err === null || err === void 0 ? void 0 : err.message) || 'FAILED',
105
+ txid
106
+ };
107
+ }
108
+ finally {
109
+ trade_appconfig.arb_cache.cache_order_message(Object.assign(Object.assign({}, order_msg), { order_submit_result })).then(res => {
110
+ (0, __1.log_info)(`cache order submit result, success`, { order_msg, order_submit_result, res });
111
+ }).catch(err => {
112
+ (0, __1.log_warn)('cache order submit result, error!', { order_msg, order_submit_result, err });
113
+ console.log(err);
114
+ });
115
+ }
116
+ });
117
+ exports.handle_order_message = handle_order_message;
@@ -0,0 +1,4 @@
1
+ export * from './abstract_trade';
2
+ export * from './abstract_tx_check';
3
+ export * from './trade_context';
4
+ export * from './handle_order_message';
@@ -0,0 +1,20 @@
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("./abstract_trade"), exports);
18
+ __exportStar(require("./abstract_tx_check"), exports);
19
+ __exportStar(require("./trade_context"), exports);
20
+ __exportStar(require("./handle_order_message"), exports);
@@ -0,0 +1,20 @@
1
+ import { AppConfig, DEX_ID } from "..";
2
+ import { CHAIN_ID } from "..";
3
+ import { OrderMessageType, PriceMessageType, StandardPoolInfoType } from "../../types";
4
+ import { TradeRuntimeType } from "../../types";
5
+ export declare class TradeContext {
6
+ trade_runtime: TradeRuntimeType;
7
+ price_msg: PriceMessageType;
8
+ order_msg: OrderMessageType;
9
+ order_trace_id: string;
10
+ group_id: string;
11
+ chain_id: CHAIN_ID;
12
+ dex_id: DEX_ID;
13
+ pool_id: string;
14
+ fee_rate: string;
15
+ pool_info: StandardPoolInfoType;
16
+ aToB: boolean;
17
+ slippage_bps: number;
18
+ constructor(price_msg: PriceMessageType, order_msg: OrderMessageType);
19
+ init(appConfig: AppConfig): Promise<void>;
20
+ }
@@ -0,0 +1,49 @@
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.TradeContext = void 0;
13
+ const __1 = require("..");
14
+ const __2 = require("..");
15
+ class TradeContext {
16
+ constructor(price_msg, order_msg) {
17
+ this.price_msg = price_msg;
18
+ this.order_msg = order_msg;
19
+ this.order_trace_id = order_msg.order_trace_id;
20
+ }
21
+ init(appConfig) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ this.trade_runtime = appConfig.trade_runtime;
24
+ let { group_id, unique_orderbook_id } = this.order_msg;
25
+ this.group_id = group_id;
26
+ let unique_orderbook_id_obj = (0, __1.parse_unique_orderbook_id)(unique_orderbook_id);
27
+ this.chain_id = __2.CHAIN_ID[unique_orderbook_id_obj.chain_id];
28
+ this.dex_id = __1.DEX_ID[unique_orderbook_id_obj.dex_id];
29
+ this.pool_id = unique_orderbook_id_obj.pool_id;
30
+ this.fee_rate = unique_orderbook_id_obj.fee_rate;
31
+ this.pool_info = yield appConfig.arb_cache.get_one_pool_info(this.pool_id);
32
+ if (!this.pool_info) {
33
+ throw new Error(`Not found pool_info! pool_id=${this.pool_id}, pool_info_list=${JSON.stringify(this.trade_runtime.pair_dex.pool_info_list)}`);
34
+ }
35
+ let { inputToken, outputToken } = (0, __1.get_input_out_token)(this.pool_info, this.order_msg.aToB);
36
+ let { amount } = this.order_msg;
37
+ let amount_dot_index = amount.indexOf('.');
38
+ if (amount_dot_index != -1) {
39
+ let amount_with_exact_decimals = amount.substring(0, amount_dot_index + inputToken.decimals + 1);
40
+ let uiAmount = parseFloat(amount_with_exact_decimals).toString();
41
+ this.order_msg.amount = uiAmount;
42
+ (0, __1.log_warn)(`Fix input token's amount decimal: from ${amount} to ${uiAmount}`);
43
+ }
44
+ this.slippage_bps = Math.min(300, Math.max(0, this.trade_runtime.settings.slippage_bps));
45
+ this.aToB = this.pool_info.is_reverse_token ? !this.order_msg.aToB : this.order_msg.aToB;
46
+ });
47
+ }
48
+ }
49
+ exports.TradeContext = TradeContext;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clonegod/ttd-core",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "description": "Common types and utilities for trading systems - use `npm run push` to publish",
5
5
  "main": "dist/index.js",
6
6
  "types": "types/index.d.ts",