@clonegod/ttd-core 3.1.23 → 3.1.25
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/alert/codes.js +1 -0
- package/dist/alert/log_rules.js +1 -0
- package/dist/app_config/AppConfig.d.ts +1 -3
- package/dist/app_config/AppConfig.js +1 -14
- package/dist/app_config/EnvArgs.d.ts +2 -1
- package/dist/app_config/env_registry.js +2 -1
- package/dist/cache/arb_cache.d.ts +1 -2
- package/dist/cache/arb_cache.js +46 -37
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/market_price/estimate_token_amount.js +3 -3
- package/dist/pool/cache_pool_config.js +45 -53
- package/dist/token/cache_token_config.js +25 -36
- package/dist/token/price/get_bsc_token_price.d.ts +4 -1
- package/dist/token/price/get_bsc_token_price.js +27 -12
- package/dist/token/price/get_eth_token_price.d.ts +4 -1
- package/dist/token/price/get_eth_token_price.js +27 -12
- package/dist/token/price/get_solana_token_price.d.ts +4 -1
- package/dist/token/price/get_solana_token_price.js +27 -12
- package/dist/token/price/get_sui_token_price.d.ts +4 -1
- package/dist/token/price/get_sui_token_price.js +27 -12
- package/dist/token/price/get_tron_token_price.d.ts +4 -1
- package/dist/token/price/get_tron_token_price.js +27 -12
- package/dist/token/price/get_xlayer_token_price.d.ts +4 -1
- package/dist/token/price/get_xlayer_token_price.js +27 -12
- package/dist/token/price/index.d.ts +2 -0
- package/dist/token/price/index.js +2 -0
- package/dist/token/price/price_cache.d.ts +6 -1
- package/dist/token/price/price_cache.js +67 -76
- package/dist/token/price/token_price_syncer.d.ts +25 -0
- package/dist/token/price/token_price_syncer.js +80 -0
- package/package.json +1 -1
- package/types/index.d.ts +2 -0
package/dist/alert/codes.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.ALERT_CODES = {
|
|
|
16
16
|
QUOTE_TICK_STALE: { code: 'QUOTE_TICK_STALE', severity: S.ERROR, category: 'quote', desc: 'tick 数据过期但仍在报价', suggested_action: '风险提示' },
|
|
17
17
|
QUOTE_PRICE_ANOMALY: { code: 'QUOTE_PRICE_ANOMALY', severity: S.ERROR, category: 'quote', desc: '报价偏离参考价 > 阈值', suggested_action: '检查数据源' },
|
|
18
18
|
QUOTE_INTERVAL_BREACH: { code: 'QUOTE_INTERVAL_BREACH', severity: S.WARN, category: 'quote', desc: '询价间隔超出预期' },
|
|
19
|
+
QUOTE_PRICE_CACHE_MISS: { code: 'QUOTE_PRICE_CACHE_MISS', severity: S.WARN, category: 'quote', desc: 'token 在系统里但 cache 无价(scheduler 未刷到)', suggested_action: '观察 market-data TokenPriceSyncer 是否正常' },
|
|
19
20
|
TRADE_ENCODE_FAIL: { code: 'TRADE_ENCODE_FAIL', severity: S.ERROR, category: 'trade', desc: 'calldata 编码失败', suggested_action: '检查订单参数' },
|
|
20
21
|
TRADE_SIGN_FAIL: { code: 'TRADE_SIGN_FAIL', severity: S.ERROR, category: 'trade', desc: '交易签名失败', suggested_action: '检查 caller 钱包' },
|
|
21
22
|
TRADE_NONCE_CONFLICT: {
|
package/dist/alert/log_rules.js
CHANGED
|
@@ -45,6 +45,7 @@ registerLogRules([
|
|
|
45
45
|
level: 'error', code: 'THIRDPARTY_AUTH_FAIL' },
|
|
46
46
|
{ pattern: /pricefeed.*(parse failed|not an array|empty)|empty response at page/i,
|
|
47
47
|
level: 'warn', code: 'THIRDPARTY_DATA_INVALID' },
|
|
48
|
+
{ pattern: /price cache miss/i, level: 'warn', code: 'QUOTE_PRICE_CACHE_MISS' },
|
|
48
49
|
{ pattern: /sqlite.*(disk|full|i\/o error|cleanup error|write.*fail)/i,
|
|
49
50
|
level: 'error', code: 'ANALYZE_SQLITE_WRITE_FAIL' },
|
|
50
51
|
{ pattern: /db size.*\d+mb.*limit/i, level: 'warn', code: 'ANALYZE_SQLITE_FULL' },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import EventEmitter from "events";
|
|
2
|
-
import {
|
|
2
|
+
import { TradeRuntimeType } from "../../types";
|
|
3
3
|
import { ArbCache, ArbEventSubscriber } from "../cache";
|
|
4
4
|
import { EnvArgs } from "./EnvArgs";
|
|
5
5
|
export declare class AppConfig extends EventEmitter {
|
|
@@ -11,6 +11,4 @@ export declare class AppConfig extends EventEmitter {
|
|
|
11
11
|
constructor();
|
|
12
12
|
init(): Promise<void>;
|
|
13
13
|
subscribe_config_change(): Promise<void>;
|
|
14
|
-
cache_token_market_price(token_info_with_price: StandardTokenInfoType, ttl?: number): Promise<void>;
|
|
15
|
-
get_token_market_price(symbol: string): Promise<StandardTokenInfoType>;
|
|
16
14
|
}
|
|
@@ -15,13 +15,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.AppConfig = void 0;
|
|
16
16
|
const events_1 = __importDefault(require("events"));
|
|
17
17
|
const __1 = require("..");
|
|
18
|
-
const EnvArgs_1 = require("./EnvArgs");
|
|
19
18
|
const core_env_1 = require("./core_env");
|
|
20
19
|
class AppConfig extends events_1.default {
|
|
21
20
|
constructor() {
|
|
22
21
|
super();
|
|
23
|
-
this.env_args =
|
|
24
|
-
(0, core_env_1.setCoreEnv)(this.env_args);
|
|
22
|
+
this.env_args = (0, core_env_1.getCoreEnv)();
|
|
25
23
|
let { chain_id, app_name, dex_id } = this.env_args;
|
|
26
24
|
this.app_full_name = `${chain_id}_${dex_id}_${app_name}`;
|
|
27
25
|
global.app_config = this;
|
|
@@ -49,16 +47,5 @@ class AppConfig extends events_1.default {
|
|
|
49
47
|
yield this.arb_event_subscriber.subscribe_config_change_event(refresh_trade_runtime);
|
|
50
48
|
});
|
|
51
49
|
}
|
|
52
|
-
cache_token_market_price(token_info_with_price_1) {
|
|
53
|
-
return __awaiter(this, arguments, void 0, function* (token_info_with_price, ttl = -1) {
|
|
54
|
-
token_info_with_price.update_time = (0, __1.getCurDateTime)();
|
|
55
|
-
yield this.arb_cache.cache_token_market_price(token_info_with_price, ttl);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
get_token_market_price(symbol) {
|
|
59
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
-
return yield this.arb_cache.get_token_market_price(symbol);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
50
|
}
|
|
64
51
|
exports.AppConfig = AppConfig;
|
|
@@ -10,6 +10,7 @@ export declare class EnvArgs {
|
|
|
10
10
|
redis_host: string;
|
|
11
11
|
redis_port: string;
|
|
12
12
|
config_center_host: string;
|
|
13
|
+
market_data_host: string;
|
|
13
14
|
enable_init_cache: string;
|
|
14
15
|
trade_analyze_url: string;
|
|
15
16
|
trade_analyze_host: string;
|
|
@@ -31,7 +32,7 @@ export declare class EnvArgs {
|
|
|
31
32
|
trade_pair: string;
|
|
32
33
|
trade_log_report_cex_url: string;
|
|
33
34
|
trade_log_report_cex_data_type: string;
|
|
34
|
-
|
|
35
|
+
token_price_refresh_interval_seconds: number;
|
|
35
36
|
token_market_price_url: string;
|
|
36
37
|
wallet_dir: string;
|
|
37
38
|
encryption_key: string;
|
|
@@ -24,6 +24,7 @@ registerEnvVars({
|
|
|
24
24
|
grpc_endpoint: { env: 'GRPC_ENDPOINT', type: 'string', default: '', desc: 'gRPC 端点' },
|
|
25
25
|
grpc_token: { env: 'GRPC_TOKEN', type: 'string', default: '', sensitive: true, desc: 'gRPC 认证 token' },
|
|
26
26
|
config_center_host: { env: 'CONFIG_CENTER_HOST', type: 'string', default: '127.0.0.1', desc: '配置中心' },
|
|
27
|
+
market_data_host: { env: 'MARKET_DATA_HOST', type: 'string', default: '127.0.0.1', desc: 'market-data 服务(L3 现查 / fetch-pool 调用)' },
|
|
27
28
|
enable_init_cache: { env: 'ENABLE_INIT_CACHE', type: 'string', default: '', desc: '仅 config-center:是否初始化缓存(空或 true 视为启用;false 则跳过)' },
|
|
28
29
|
trade_analyze_host: { env: 'TRADE_ANALYZE_HOST', type: 'string', default: '', desc: 'analyze 上报地址(IP);为空则不上报' },
|
|
29
30
|
auto_quote_enable: { env: 'AUTO_QUOTE_ENABLE', type: 'boolean', default: false, desc: '自动报价开关' },
|
|
@@ -44,7 +45,7 @@ registerEnvVars({
|
|
|
44
45
|
encryption_key: { env: 'ENCRYPTION_KEY', type: 'string', default: '', sensitive: true, desc: '对称加密密钥(用于钱包文件等)' },
|
|
45
46
|
trade_analyze_url: { env: 'TRADE_ANALYZE_URL', type: 'string', default: '', desc: 'analyze HTTP 基址(旧 EnvArgs;未配则 analyze 上报走默认拼接)' },
|
|
46
47
|
providers_file_path: { env: 'PROVIDERS_FILE_PATH', type: 'string', default: '', desc: 'stream-quote providers.json 绝对路径;留空则仅写 Redis' },
|
|
47
|
-
|
|
48
|
+
token_price_refresh_interval_seconds: { env: 'TOKEN_PRICE_REFRESH_INTERVAL_SECONDS', type: 'number', default: 600, desc: 'TokenPriceSyncer 刷价周期(s):market-data 拉价并推送给 config-center 写 token_list 的频率' },
|
|
48
49
|
token_market_price_url: { env: 'TOKEN_MARKET_PRICE_URL', type: 'string', default: '', desc: '【使用方: ttd-core estimate_token_amount】config-center 市价估算 HTTP 基址;为空则跳过远程回退' },
|
|
49
50
|
fixed_symbol_address_file: { env: 'FIXED_SYMBOL_ADDRESS_FILE', type: 'string', default: '', desc: '固定 symbol/address 映射文件路径(覆盖默认按 CHAIN_ID 推断的路径)' },
|
|
50
51
|
zh_pinyin_map_file: { env: 'ZH_PINYIN_MAP_FILE', type: 'string', default: '', desc: '中文拼音映射文件路径(覆盖默认路径)' },
|
|
@@ -51,8 +51,7 @@ export declare class ArbCache {
|
|
|
51
51
|
create_trade_runtime(chain_id: string, group_id: string, dex_id: string, pair_name: string): Promise<TradeRuntimeType>;
|
|
52
52
|
find_pair_in_trade_config(pair_name: string, trade_config: TradeServiceConfigType): TradePairType;
|
|
53
53
|
find_pair_dex_in_trade_config(dex_id: string, pair_config: TradePairType): TradePairDexPoolsType;
|
|
54
|
-
|
|
55
|
-
get_token_market_price(symbol: string): Promise<StandardTokenInfoType>;
|
|
54
|
+
update_token_prices(input_tokens: StandardTokenInfoType[]): Promise<number>;
|
|
56
55
|
cache_price_message(price_msg: PriceMessageType, ttl?: number): Promise<void>;
|
|
57
56
|
get_price_message(price_id: string): Promise<PriceMessageType>;
|
|
58
57
|
cache_order_message(order_msg: OrderMessageType, ttl?: number): Promise<{
|
package/dist/cache/arb_cache.js
CHANGED
|
@@ -81,18 +81,40 @@ class ArbCache {
|
|
|
81
81
|
return path_1.default.join('config', chain_id, file_name);
|
|
82
82
|
}
|
|
83
83
|
refresh_local_cache_token_list(token_list) {
|
|
84
|
-
|
|
84
|
+
const new_by_addr = new Map();
|
|
85
|
+
const merged = [];
|
|
86
|
+
for (const fresh of token_list) {
|
|
87
|
+
new_by_addr.set(fresh.address, fresh);
|
|
88
|
+
}
|
|
89
|
+
const to_delete_addr = [];
|
|
90
|
+
for (const [addr, existing] of this.token_address_map) {
|
|
91
|
+
const fresh = new_by_addr.get(addr);
|
|
92
|
+
if (fresh) {
|
|
93
|
+
Object.assign(existing, fresh);
|
|
94
|
+
merged.push(existing);
|
|
95
|
+
new_by_addr.delete(addr);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
to_delete_addr.push(addr);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (const addr of to_delete_addr) {
|
|
102
|
+
this.token_address_map.delete(addr);
|
|
103
|
+
}
|
|
104
|
+
for (const fresh of new_by_addr.values()) {
|
|
105
|
+
this.token_address_map.set(fresh.address, fresh);
|
|
106
|
+
merged.push(fresh);
|
|
107
|
+
}
|
|
85
108
|
this.token_symbol_map.clear();
|
|
86
|
-
|
|
87
|
-
for (let token of token_list) {
|
|
109
|
+
for (const token of merged) {
|
|
88
110
|
this.token_symbol_map.set(token.symbol, token);
|
|
89
|
-
this.token_address_map.set(token.address, token);
|
|
90
111
|
}
|
|
112
|
+
this.token_list = merged;
|
|
91
113
|
this.token_list_cache_last_update_time = (0, index_1.getCurDateTime)();
|
|
92
114
|
(0, index_1.log_trace)('refresh_local_cache_token_list, success', {
|
|
93
115
|
token_list_len: this.token_list.length,
|
|
94
116
|
token_symbol_map_size: this.token_symbol_map.size,
|
|
95
|
-
token_address_map_szie: this.token_address_map.size
|
|
117
|
+
token_address_map_szie: this.token_address_map.size,
|
|
96
118
|
});
|
|
97
119
|
}
|
|
98
120
|
refresh_local_cache_pool_list(pool_list) {
|
|
@@ -141,9 +163,6 @@ class ArbCache {
|
|
|
141
163
|
if (index_1.LOG.debug) {
|
|
142
164
|
(0, index_1.log_trace)(`cache_token_list, symbol=${field}, result: ` + JSON.stringify(result));
|
|
143
165
|
}
|
|
144
|
-
if (token.market_price) {
|
|
145
|
-
this.cache_token_market_price(token, -1);
|
|
146
|
-
}
|
|
147
166
|
}
|
|
148
167
|
this.refresh_local_cache_token_list(token_list);
|
|
149
168
|
let result = yield this.loading_cache.hlen(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST);
|
|
@@ -644,36 +663,26 @@ class ArbCache {
|
|
|
644
663
|
let pair_dex_config = pair_config.dex_list.find(e => e.dex_id === dex_id);
|
|
645
664
|
return pair_dex_config;
|
|
646
665
|
}
|
|
647
|
-
|
|
648
|
-
return __awaiter(this, arguments, void 0, function* (token_with_price, ttl = -1) {
|
|
649
|
-
(0, index_1.log_trace)(`cache_market_price, start`);
|
|
650
|
-
if ((0, index_1.isEmpty)(token_with_price.market_price)) {
|
|
651
|
-
(0, index_1.log_warn)(`cache_token_market_price skip: empty market_price, symbol=${token_with_price.symbol}, address=${token_with_price.address}`);
|
|
652
|
-
return;
|
|
653
|
-
}
|
|
654
|
-
let { symbol } = token_with_price;
|
|
655
|
-
let field = (0, index_1.format_symbol_name)(symbol);
|
|
656
|
-
let value = JSON.stringify(token_with_price);
|
|
657
|
-
let result = yield this.loading_cache.hset_ex(this.chain_id, index_1.CACHE_KEY_TYPE.MARKET_TOKEN_PRICE, field, value, ttl);
|
|
658
|
-
(0, index_1.log_trace)('cache_market_price, end', result);
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
get_token_market_price(symbol) {
|
|
666
|
+
update_token_prices(input_tokens) {
|
|
662
667
|
return __awaiter(this, void 0, void 0, function* () {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
668
|
+
if ((0, index_1.isEmpty)(input_tokens))
|
|
669
|
+
return 0;
|
|
670
|
+
let count = 0;
|
|
671
|
+
for (const token of input_tokens) {
|
|
672
|
+
if (!(token === null || token === void 0 ? void 0 : token.symbol) || (0, index_1.isEmpty)(token.market_price))
|
|
673
|
+
continue;
|
|
674
|
+
const field = (0, index_1.format_symbol_name)(token.symbol);
|
|
675
|
+
yield this.loading_cache.hset(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST, field, JSON.stringify(token));
|
|
676
|
+
count++;
|
|
677
|
+
}
|
|
678
|
+
if (count > 0) {
|
|
679
|
+
yield this.redis_event_publisher.publish_config_change_event({
|
|
680
|
+
event_type: index_1.REDIS_EVENT_TYPE_CONFIG_CHANGE.TOKEN_CONFIG_CHANGE,
|
|
681
|
+
event_time: Date.now(),
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
(0, index_1.log_trace)(`update_token_prices, end. count=${count}`);
|
|
685
|
+
return count;
|
|
677
686
|
});
|
|
678
687
|
}
|
|
679
688
|
cache_price_message(price_msg_1) {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -207,7 +207,6 @@ var OnChainDataSubscribeType;
|
|
|
207
207
|
})(OnChainDataSubscribeType || (exports.OnChainDataSubscribeType = OnChainDataSubscribeType = {}));
|
|
208
208
|
var CACHE_KEY_TYPE;
|
|
209
209
|
(function (CACHE_KEY_TYPE) {
|
|
210
|
-
CACHE_KEY_TYPE["MARKET_TOKEN_PRICE"] = "m:price";
|
|
211
210
|
CACHE_KEY_TYPE["CONFIG_TOKEN_LIST"] = "c:token";
|
|
212
211
|
CACHE_KEY_TYPE["CONFIG_POOL_LIST"] = "c:pool";
|
|
213
212
|
CACHE_KEY_TYPE["CONFIG_PAIR_LIST"] = "c:pair";
|
|
@@ -61,12 +61,12 @@ class EstimateAmountInToken {
|
|
|
61
61
|
}
|
|
62
62
|
else {
|
|
63
63
|
if (index_1.LOG.debug) {
|
|
64
|
-
(0, index_1.log_debug)(`try-2 get market price from
|
|
64
|
+
(0, index_1.log_debug)(`try-2 get market price from in-memory token_address_map`);
|
|
65
65
|
}
|
|
66
|
-
token_info =
|
|
66
|
+
token_info = arb_cache.token_symbol_map.get(symbol);
|
|
67
67
|
set_tmp_market_price(token_info);
|
|
68
68
|
if (index_1.LOG.debug) {
|
|
69
|
-
(0, index_1.log_debug)(`try-2 get market price from
|
|
69
|
+
(0, index_1.log_debug)(`try-2 get market price from in-memory map, res=`, token_info);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
let market_price = token_info === null || token_info === void 0 ? void 0 : token_info.market_price;
|
|
@@ -24,63 +24,55 @@ const cache_pool_config = (chain_id, valid_tokens_map, sol_pools_cache) => __awa
|
|
|
24
24
|
let skip_pool_list = [];
|
|
25
25
|
const genv = (0, core_env_1.getCoreEnv)();
|
|
26
26
|
const ccBase = `http://${(genv.config_center_host || '127.0.0.1').trim()}:${service_ports_1.SERVICE_PORT.CONFIG_CENTER_HTTP}/${chain_id}/config`;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
skip_pool_list.push(pool);
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
let std_pool = {
|
|
39
|
-
program_id: pool.program_id,
|
|
40
|
-
authority: pool.authority,
|
|
41
|
-
subscribe_type: 'grpc',
|
|
42
|
-
pair: pool.pair,
|
|
43
|
-
dex_id: dex_id,
|
|
44
|
-
pool_name: pool.pool_name,
|
|
45
|
-
pool_address: pool.pool_address,
|
|
46
|
-
pool_address_hex: '',
|
|
47
|
-
tokenA: null,
|
|
48
|
-
tokenB: null,
|
|
49
|
-
vaultA: pool.vaultA,
|
|
50
|
-
vaultB: pool.vaultB,
|
|
51
|
-
subscribe_vault_change: pool.subscribe_vault_change,
|
|
52
|
-
router_id: null,
|
|
53
|
-
fee_rate: pool.fee_rate_bps,
|
|
54
|
-
quote_token: pool.quote_token,
|
|
55
|
-
quote_amount_usd: genv.quote_amount_usd,
|
|
56
|
-
quote_price_decimals: 18,
|
|
57
|
-
is_reverse_token: null,
|
|
58
|
-
cu_limit: get_cu_limit(dex_id),
|
|
59
|
-
tvl: pool.tvl,
|
|
60
|
-
vol_24h: pool.vol_24h,
|
|
61
|
-
update_time: (0, index_1.getCurDateTime)(),
|
|
62
|
-
is_trade_native_token: pool.is_trade_native_token,
|
|
63
|
-
enable: true,
|
|
64
|
-
};
|
|
65
|
-
valid_pool_list.push(std_pool);
|
|
66
|
-
count = count + 1;
|
|
67
|
-
}
|
|
68
|
-
if (valid_pool_list.length === 0) {
|
|
27
|
+
const config_pool_url = `${ccBase}/pools`;
|
|
28
|
+
const body = [];
|
|
29
|
+
for (const [dex_id, pool_list] of sol_pools_cache) {
|
|
30
|
+
const valid_pool_list = [];
|
|
31
|
+
for (const pool of pool_list) {
|
|
32
|
+
const is_contains_unkown_symbol = !valid_tokens_map.has(pool.tokenA.symbol) || !valid_tokens_map.has(pool.tokenB.symbol);
|
|
33
|
+
if (is_contains_unkown_symbol || (0, is_not_arb_token_1.is_not_arb_token)(pool.pool_name)) {
|
|
34
|
+
skip_pool_list.push(pool);
|
|
69
35
|
continue;
|
|
70
36
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
37
|
+
valid_pool_list.push({
|
|
38
|
+
program_id: pool.program_id,
|
|
39
|
+
authority: pool.authority,
|
|
40
|
+
subscribe_type: 'grpc',
|
|
41
|
+
pair: pool.pair,
|
|
42
|
+
dex_id,
|
|
43
|
+
pool_name: pool.pool_name,
|
|
44
|
+
pool_address: pool.pool_address,
|
|
45
|
+
pool_address_hex: '',
|
|
46
|
+
tokenA: null,
|
|
47
|
+
tokenB: null,
|
|
48
|
+
vaultA: pool.vaultA,
|
|
49
|
+
vaultB: pool.vaultB,
|
|
50
|
+
subscribe_vault_change: pool.subscribe_vault_change,
|
|
51
|
+
router_id: null,
|
|
52
|
+
fee_rate: pool.fee_rate_bps,
|
|
53
|
+
quote_token: pool.quote_token,
|
|
54
|
+
quote_amount_usd: genv.quote_amount_usd,
|
|
55
|
+
quote_price_decimals: 18,
|
|
56
|
+
is_reverse_token: null,
|
|
57
|
+
cu_limit: get_cu_limit(dex_id),
|
|
58
|
+
tvl: pool.tvl,
|
|
59
|
+
vol_24h: pool.vol_24h,
|
|
60
|
+
update_time: (0, index_1.getCurDateTime)(),
|
|
61
|
+
is_trade_native_token: pool.is_trade_native_token,
|
|
62
|
+
enable: true,
|
|
63
|
+
});
|
|
64
|
+
count = count + 1;
|
|
65
|
+
}
|
|
66
|
+
if (valid_pool_list.length > 0) {
|
|
67
|
+
body.push({ dex_id, pool_list: valid_pool_list });
|
|
82
68
|
}
|
|
83
69
|
}
|
|
70
|
+
if (body.length > 0) {
|
|
71
|
+
const res = (yield axios_1.default.post(config_pool_url, body, {
|
|
72
|
+
headers: { 'Content-Type': 'application/json' },
|
|
73
|
+
})).data;
|
|
74
|
+
(0, index_1.log_trace)('cache_pool_config, res', res);
|
|
75
|
+
}
|
|
84
76
|
(0, index_1.log_info)(`cache_pool_config finished! sync pool count:${count}, skip: ${skip_pool_list.length}`);
|
|
85
77
|
skip_pool_list.sort((a, b) => a.pair.localeCompare(b.pair));
|
|
86
78
|
(0, index_1.writeFile)(`dist/${chain_id.toLowerCase()}_skip_pool_list.json`, JSON.stringify({
|
|
@@ -22,46 +22,35 @@ const cache_token_config = (chain_id, valid_tokens_map) => __awaiter(void 0, voi
|
|
|
22
22
|
(0, index_1.log_info)(`cache_token_config start`);
|
|
23
23
|
const genv = (0, core_env_1.getCoreEnv)();
|
|
24
24
|
const ccBase = `http://${(genv.config_center_host || '127.0.0.1').trim()}:${service_ports_1.SERVICE_PORT.CONFIG_CENTER_HTTP}/${chain_id}/config`;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
let valid_tokens = [];
|
|
30
|
-
for (let key of one_batch) {
|
|
31
|
-
let value = valid_tokens_map.get(key);
|
|
32
|
-
if (!value || value.length !== 1) {
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
let token = value[0];
|
|
36
|
-
let std_token = {
|
|
37
|
-
symbol: token.symbol,
|
|
38
|
-
address: token.address,
|
|
39
|
-
address_hex: '',
|
|
40
|
-
decimals: token.decimals,
|
|
41
|
-
name: token.name,
|
|
42
|
-
is_token2022: token.is_token_2022,
|
|
43
|
-
market_price: token.price,
|
|
44
|
-
update_time: (0, index_1.getCurDateTime)(),
|
|
45
|
-
alias: (0, index_1.get_token_symbol_alias)(token.address),
|
|
46
|
-
enable: true
|
|
47
|
-
};
|
|
48
|
-
if ((0, is_not_arb_token_1.is_not_arb_token)(std_token.symbol)) {
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
valid_tokens.push(std_token);
|
|
52
|
-
count += 1;
|
|
53
|
-
}
|
|
54
|
-
if (valid_tokens.length === 0) {
|
|
25
|
+
const config_token_url = `${ccBase}/tokens`;
|
|
26
|
+
const valid_tokens = [];
|
|
27
|
+
for (const [, value] of valid_tokens_map) {
|
|
28
|
+
if (!value || value.length !== 1)
|
|
55
29
|
continue;
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
30
|
+
const token = value[0];
|
|
31
|
+
const std_token = {
|
|
32
|
+
symbol: token.symbol,
|
|
33
|
+
address: token.address,
|
|
34
|
+
address_hex: '',
|
|
35
|
+
decimals: token.decimals,
|
|
36
|
+
name: token.name,
|
|
37
|
+
is_token2022: token.is_token_2022,
|
|
38
|
+
market_price: token.price,
|
|
39
|
+
update_time: (0, index_1.getCurDateTime)(),
|
|
40
|
+
alias: (0, index_1.get_token_symbol_alias)(token.address),
|
|
41
|
+
enable: true,
|
|
42
|
+
};
|
|
43
|
+
if ((0, is_not_arb_token_1.is_not_arb_token)(std_token.symbol))
|
|
44
|
+
continue;
|
|
45
|
+
valid_tokens.push(std_token);
|
|
46
|
+
}
|
|
47
|
+
if (valid_tokens.length > 0) {
|
|
48
|
+
const res = (yield axios_1.default.post(config_token_url, valid_tokens, {
|
|
49
|
+
headers: { 'Content-Type': 'application/json' },
|
|
60
50
|
})).data;
|
|
61
51
|
(0, index_1.log_trace)('cache_token_config, res', res);
|
|
62
|
-
yield (0, index_1.sleep)(200);
|
|
63
52
|
}
|
|
64
|
-
(0, index_1.log_info)(`cache_token_config finish! sync token count: ${
|
|
53
|
+
(0, index_1.log_info)(`cache_token_config finish! sync token count: ${valid_tokens.length}`);
|
|
65
54
|
let notify_config_change_url = `${ccBase}/change?type=token`;
|
|
66
55
|
let res = (yield axios_1.default.get(notify_config_change_url)).data;
|
|
67
56
|
(0, index_1.log_info)('fetch tokens end, notify config change', {
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { FormattedTokenPrice } from "../types";
|
|
2
|
-
export
|
|
2
|
+
export type PriceSource = 'cache_only' | 'cache_first' | 'force_fetch';
|
|
3
|
+
export declare function get_bsc_token_price_info(addresses: string[], opts?: {
|
|
4
|
+
source?: PriceSource;
|
|
5
|
+
}): Promise<Map<string, FormattedTokenPrice>>;
|
|
@@ -15,17 +15,19 @@ const index_1 = require("../../index");
|
|
|
15
15
|
const defi_llama_1 = require("./defi_llama");
|
|
16
16
|
const gecko_terminal_1 = require("./gecko_terminal");
|
|
17
17
|
const price_cache_1 = require("./price_cache");
|
|
18
|
-
function get_bsc_token_price_info(addresses) {
|
|
18
|
+
function get_bsc_token_price_info(addresses, opts) {
|
|
19
19
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
var _a;
|
|
21
|
+
const source = (_a = opts === null || opts === void 0 ? void 0 : opts.source) !== null && _a !== void 0 ? _a : 'cache_only';
|
|
20
22
|
addresses = addresses.map(addr => addr.toLowerCase());
|
|
21
23
|
const result = new Map();
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const cachedChannel = {
|
|
25
|
+
name: 'CachedPrice',
|
|
26
|
+
fetchFn: price_cache_1.fetchPriceFromCache,
|
|
27
|
+
batchSize: 100,
|
|
28
|
+
batchDelay: 1000,
|
|
29
|
+
};
|
|
30
|
+
const externalChannels = [
|
|
29
31
|
{
|
|
30
32
|
name: 'DefiLlama',
|
|
31
33
|
fetchFn: (address_list) => (0, defi_llama_1.fetchPriceFromDefiLlama)(index_1.CHAIN_ID.BSC, address_list),
|
|
@@ -39,6 +41,10 @@ function get_bsc_token_price_info(addresses) {
|
|
|
39
41
|
batchDelay: 1000,
|
|
40
42
|
},
|
|
41
43
|
];
|
|
44
|
+
const PRICE_CHANNELS = source === 'cache_only' ? [cachedChannel] :
|
|
45
|
+
source === 'cache_first' ? [cachedChannel, ...externalChannels] :
|
|
46
|
+
[...externalChannels];
|
|
47
|
+
const externalHits = [];
|
|
42
48
|
try {
|
|
43
49
|
for (const channel of PRICE_CHANNELS) {
|
|
44
50
|
if (addresses.length === 0)
|
|
@@ -58,7 +64,7 @@ function get_bsc_token_price_info(addresses) {
|
|
|
58
64
|
result.set(address, priceInfo);
|
|
59
65
|
remainingAddresses = remainingAddresses.filter(addr => addr !== address);
|
|
60
66
|
if (channel.name !== 'CachedPrice') {
|
|
61
|
-
(
|
|
67
|
+
externalHits.push({ address, price: priceInfo.price, source: channel.name });
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
70
|
}
|
|
@@ -75,17 +81,26 @@ function get_bsc_token_price_info(addresses) {
|
|
|
75
81
|
break;
|
|
76
82
|
}
|
|
77
83
|
}
|
|
78
|
-
if (
|
|
84
|
+
if (externalHits.length > 0) {
|
|
85
|
+
yield (0, price_cache_1.cache_new_market_price_batch)(externalHits);
|
|
86
|
+
}
|
|
87
|
+
if (source === 'cache_only' && addresses.length > 0) {
|
|
88
|
+
(0, price_cache_1.warnPriceCacheMiss)(addresses);
|
|
89
|
+
}
|
|
90
|
+
if (source === 'force_fetch' && result.size === 0) {
|
|
79
91
|
throw new Error(`Unable to get price information for any token: ${addresses.join(', ')}`);
|
|
80
92
|
}
|
|
81
|
-
if (addresses.length > 0) {
|
|
93
|
+
if (source !== 'cache_only' && addresses.length > 0) {
|
|
82
94
|
(0, index_1.log_warn)(`[get_token_price_info] Failed to get prices for ${addresses.length} tokens after trying all channels: ${addresses.join(', ')}`);
|
|
83
95
|
}
|
|
84
96
|
(0, index_1.log_debug)(`[get_token_price_info] Completed price fetching for ${result.size} tokens`);
|
|
85
97
|
return result;
|
|
86
98
|
}
|
|
87
99
|
catch (error) {
|
|
88
|
-
|
|
100
|
+
if (source === 'force_fetch') {
|
|
101
|
+
throw new Error(`Failed to get token price information: ${error instanceof Error ? error.message : String(error)}`);
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
89
104
|
}
|
|
90
105
|
});
|
|
91
106
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { EvmChainInfoType } from '../../chains';
|
|
2
2
|
import { FormattedTokenPrice } from "../types";
|
|
3
|
-
|
|
3
|
+
import type { PriceSource } from './get_bsc_token_price';
|
|
4
|
+
export declare function get_eth_token_price_info(evm_chain_info: EvmChainInfoType, addresses: string[], opts?: {
|
|
5
|
+
source?: PriceSource;
|
|
6
|
+
}): Promise<Map<string, FormattedTokenPrice>>;
|
|
@@ -19,17 +19,19 @@ const index_1 = require("../../index");
|
|
|
19
19
|
const defi_llama_1 = require("./defi_llama");
|
|
20
20
|
const gecko_terminal_1 = require("./gecko_terminal");
|
|
21
21
|
const price_cache_1 = require("./price_cache");
|
|
22
|
-
function get_eth_token_price_info(evm_chain_info, addresses) {
|
|
22
|
+
function get_eth_token_price_info(evm_chain_info, addresses, opts) {
|
|
23
23
|
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
var _a;
|
|
25
|
+
const source = (_a = opts === null || opts === void 0 ? void 0 : opts.source) !== null && _a !== void 0 ? _a : 'cache_only';
|
|
24
26
|
addresses = addresses.map(addr => addr.toLowerCase());
|
|
25
27
|
const result = new Map();
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
const cachedChannel = {
|
|
29
|
+
name: 'CachedPrice',
|
|
30
|
+
fetchFn: price_cache_1.fetchPriceFromCache,
|
|
31
|
+
batchSize: 100,
|
|
32
|
+
batchDelay: 1000,
|
|
33
|
+
};
|
|
34
|
+
const externalChannels = [
|
|
33
35
|
{
|
|
34
36
|
name: 'DefiLlama',
|
|
35
37
|
fetchFn: (address_list) => (0, defi_llama_1.fetchPriceFromDefiLlama)(evm_chain_info.chain_short_name, address_list),
|
|
@@ -49,6 +51,10 @@ function get_eth_token_price_info(evm_chain_info, addresses) {
|
|
|
49
51
|
batchDelay: 1000,
|
|
50
52
|
},
|
|
51
53
|
];
|
|
54
|
+
const PRICE_CHANNELS = source === 'cache_only' ? [cachedChannel] :
|
|
55
|
+
source === 'cache_first' ? [cachedChannel, ...externalChannels] :
|
|
56
|
+
[...externalChannels];
|
|
57
|
+
const externalHits = [];
|
|
52
58
|
try {
|
|
53
59
|
for (const channel of PRICE_CHANNELS) {
|
|
54
60
|
if (addresses.length === 0)
|
|
@@ -68,7 +74,7 @@ function get_eth_token_price_info(evm_chain_info, addresses) {
|
|
|
68
74
|
result.set(address, priceInfo);
|
|
69
75
|
remainingAddresses = remainingAddresses.filter(addr => addr !== address);
|
|
70
76
|
if (channel.name !== 'CachedPrice') {
|
|
71
|
-
(
|
|
77
|
+
externalHits.push({ address, price: priceInfo.price, source: channel.name });
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
}
|
|
@@ -85,17 +91,26 @@ function get_eth_token_price_info(evm_chain_info, addresses) {
|
|
|
85
91
|
break;
|
|
86
92
|
}
|
|
87
93
|
}
|
|
88
|
-
if (
|
|
94
|
+
if (externalHits.length > 0) {
|
|
95
|
+
yield (0, price_cache_1.cache_new_market_price_batch)(externalHits);
|
|
96
|
+
}
|
|
97
|
+
if (source === 'cache_only' && addresses.length > 0) {
|
|
98
|
+
(0, price_cache_1.warnPriceCacheMiss)(addresses);
|
|
99
|
+
}
|
|
100
|
+
if (source === 'force_fetch' && result.size === 0) {
|
|
89
101
|
throw new Error(`Unable to get price information for any token: ${addresses.join(', ')}`);
|
|
90
102
|
}
|
|
91
|
-
if (addresses.length > 0) {
|
|
103
|
+
if (source !== 'cache_only' && addresses.length > 0) {
|
|
92
104
|
(0, index_1.log_warn)(`[get_token_price_info] Failed to get prices for ${addresses.length} tokens after trying all channels: ${addresses.join(', ')}`);
|
|
93
105
|
}
|
|
94
106
|
(0, index_1.log_debug)(`[get_token_price_info] Completed price fetching for ${result.size} tokens`);
|
|
95
107
|
return result;
|
|
96
108
|
}
|
|
97
109
|
catch (error) {
|
|
98
|
-
|
|
110
|
+
if (source === 'force_fetch') {
|
|
111
|
+
throw new Error(`Failed to get token price information: ${error instanceof Error ? error.message : String(error)}`);
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
99
114
|
}
|
|
100
115
|
});
|
|
101
116
|
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { FormattedTokenPrice } from "../types";
|
|
2
|
-
|
|
2
|
+
import type { PriceSource } from './get_bsc_token_price';
|
|
3
|
+
export declare function get_solana_token_price_info(addresses: string[], opts?: {
|
|
4
|
+
source?: PriceSource;
|
|
5
|
+
}): Promise<Map<string, FormattedTokenPrice>>;
|