@clonegod/ttd-core 3.1.39 → 3.1.41
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/log_rules.js +1 -1
- package/dist/appconfig/EnvArgs.d.ts +0 -1
- package/dist/appconfig/env_registry.js +0 -1
- package/dist/cache/arb_cache.d.ts +14 -5
- package/dist/cache/arb_cache.js +138 -78
- package/dist/cache/arb_event_sub.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -9
- package/dist/pool/cache_pool_config.d.ts +1 -1
- package/dist/pool/cache_pool_config.js +6 -5
- package/dist/pool/types.d.ts +1 -0
- package/dist/quote/to_price_message.js +2 -2
- package/dist/token/cache_token_config.d.ts +1 -1
- package/dist/token/cache_token_config.js +9 -10
- package/dist/token/index.d.ts +0 -1
- package/dist/token/index.js +0 -1
- package/dist/token/price/token_price_syncer.d.ts +3 -0
- package/dist/token/price/token_price_syncer.js +17 -0
- package/dist/token/token_util.d.ts +0 -1
- package/dist/token/token_util.js +4 -16
- package/dist/token/types.d.ts +2 -4
- package/package.json +1 -1
- package/types/index.d.ts +15 -2
package/dist/alert/log_rules.js
CHANGED
|
@@ -28,7 +28,7 @@ function detectProvider(msg) {
|
|
|
28
28
|
registerLogRules([
|
|
29
29
|
{ pattern: /redis.*(disconnect|connection.*lost|econnrefused|pubsub.*error|subscribe.*failed|exceeded max reconnect|连接失败)/i,
|
|
30
30
|
code: 'INFRA_REDIS_DISCONNECT' },
|
|
31
|
-
{ pattern: /econnrefused.*4000|config-center.*(down|unavailable)|(get|update|delete|post|check)\s+(pools|tokens|group|fixed-symbol
|
|
31
|
+
{ pattern: /econnrefused.*4000|config-center.*(down|unavailable)|(get|update|delete|post|check)\s+(pools|tokens|group|fixed-symbol).*error|init_.*client.*error/i,
|
|
32
32
|
level: 'error', code: 'INFRA_CONFIG_CENTER_DOWN' },
|
|
33
33
|
{ pattern: /uncaught exception|unhandled rejection|startup failed|main error|create_trade_runtime error|arb_cache.*init.*error/i,
|
|
34
34
|
level: 'error', code: 'INFRA_PROCESS_CRASH' },
|
|
@@ -45,7 +45,6 @@ registerEnvVars({
|
|
|
45
45
|
providers_file_path: { env: 'PROVIDERS_FILE_PATH', type: 'string', default: '', desc: 'stream-quote providers.json 绝对路径;留空则仅写 Redis' },
|
|
46
46
|
token_price_refresh_interval_seconds: { env: 'TOKEN_PRICE_REFRESH_INTERVAL_SECONDS', type: 'number', default: 600, desc: 'TokenPriceSyncer 刷价周期(s):market-data 通过 force_fetch 拉外部价(DefiLlama→Gecko→...)并直接批量写入 Redis + 发 TOKEN_CONFIG_CHANGE 事件的频率' },
|
|
47
47
|
fixed_symbol_address_file: { env: 'FIXED_SYMBOL_ADDRESS_FILE', type: 'string', default: '', desc: '固定 symbol/address 映射文件路径(覆盖默认按 CHAIN_ID 推断的路径)' },
|
|
48
|
-
zh_pinyin_map_file: { env: 'ZH_PINYIN_MAP_FILE', type: 'string', default: '', desc: '中文拼音映射文件路径(覆盖默认路径)' },
|
|
49
48
|
server_ip_list: { env: 'SERVER_IP_LIST', type: 'string', default: '', desc: '服务器可用 IP 列表(逗号分隔);配置后优先使用;为空则从网卡探测并结合 IP_EXCLUDE_PREFIX 过滤' },
|
|
50
49
|
ip_exclude_prefix: { env: 'IP_EXCLUDE_PREFIX', type: 'string', default: '192.168', desc: 'IP 前缀排除列表(逗号分隔)' },
|
|
51
50
|
alert_analyze_host: { env: 'ALERT_ANALYZE_HOST', type: 'string', default: '', desc: 'alert ingest 地址(IP);为空则不上报' },
|
|
@@ -29,16 +29,21 @@ export declare class ArbCache {
|
|
|
29
29
|
refresh_local_cache_group_map(trade_config: TradeServiceConfigType): void;
|
|
30
30
|
cache_token_list(): Promise<void>;
|
|
31
31
|
update_token_list(input_token_list: StandardTokenInfoType[]): Promise<void>;
|
|
32
|
-
get_token_list(): Promise<StandardTokenInfoType[]>;
|
|
33
|
-
get_token_list_no_cache(): Promise<StandardTokenInfoType[]>;
|
|
32
|
+
get_token_list(force_load?: boolean): Promise<StandardTokenInfoType[]>;
|
|
34
33
|
get_one_token_info_by_symbol(symbol: string): Promise<StandardTokenInfoType>;
|
|
35
34
|
publish_token_change_event(): Promise<void>;
|
|
36
35
|
cache_pool_list(): Promise<void>;
|
|
37
|
-
|
|
36
|
+
scan_duplicate_address(token_list: StandardTokenInfoType[]): void;
|
|
38
37
|
resolve_duplicate_address(authoritative_mappings: Array<{
|
|
39
38
|
address: string;
|
|
40
39
|
symbol: string;
|
|
41
40
|
}>): Promise<{
|
|
41
|
+
cleaned_redis_fields: Array<{
|
|
42
|
+
field: string;
|
|
43
|
+
address: string;
|
|
44
|
+
value_symbol: string;
|
|
45
|
+
kept_symbol: string;
|
|
46
|
+
}>;
|
|
42
47
|
cleaned_tokens: Array<{
|
|
43
48
|
address: string;
|
|
44
49
|
dropped_symbols: string[];
|
|
@@ -60,13 +65,17 @@ export declare class ArbCache {
|
|
|
60
65
|
symbol: string;
|
|
61
66
|
reason: string;
|
|
62
67
|
}>;
|
|
68
|
+
invalid_input: Array<{
|
|
69
|
+
address: string;
|
|
70
|
+
symbol: string;
|
|
71
|
+
reason: string;
|
|
72
|
+
}>;
|
|
63
73
|
}>;
|
|
64
74
|
set_pool_token_info(pool: StandardPoolInfoType, token_info_list: StandardTokenInfoType[]): boolean;
|
|
65
75
|
set_pool_extra(pool: StandardPoolInfoType): void;
|
|
66
76
|
update_pool_list(input_dex_pool_list: StandardDexPoolConfigType[]): Promise<void>;
|
|
67
77
|
get_pool_list_by_pair(pair: string): Promise<StandardPoolInfoType[]>;
|
|
68
|
-
get_pool_list(): Promise<StandardPoolInfoType[]>;
|
|
69
|
-
get_pool_list_no_cache(): Promise<StandardPoolInfoType[]>;
|
|
78
|
+
get_pool_list(force_load?: boolean): Promise<StandardPoolInfoType[]>;
|
|
70
79
|
get_one_pool_info(pool_address: string, refresh_cache_if_not_found?: boolean): Promise<StandardPoolInfoType>;
|
|
71
80
|
publish_pool_change_event(): Promise<void>;
|
|
72
81
|
get_one_pair(input_pair: string): Promise<StandardPairType>;
|
package/dist/cache/arb_cache.js
CHANGED
|
@@ -42,8 +42,8 @@ class ArbCache {
|
|
|
42
42
|
this.redis_event_publisher = (0, index_1.getArbEventPublisher)(this);
|
|
43
43
|
(0, index_1.mkdirSync)(path_1.default.join('config', this.chain_id).toLowerCase(), true);
|
|
44
44
|
yield Promise.all([
|
|
45
|
-
this.
|
|
46
|
-
this.
|
|
45
|
+
this.get_token_list(true),
|
|
46
|
+
this.get_pool_list(true)
|
|
47
47
|
]);
|
|
48
48
|
if ((_a = (0, core_env_1.getCoreEnv)().app_name) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('config-center')) {
|
|
49
49
|
yield this.init_configs();
|
|
@@ -91,12 +91,19 @@ class ArbCache {
|
|
|
91
91
|
return path_1.default.join('config', chain_id, file_name);
|
|
92
92
|
}
|
|
93
93
|
refresh_local_cache_token_list(token_list) {
|
|
94
|
-
const
|
|
94
|
+
const prev_by_id = new Map();
|
|
95
|
+
for (const t of this.token_address_map.values()) {
|
|
96
|
+
const id = t._id || (t.address || '').toLowerCase();
|
|
97
|
+
if (id)
|
|
98
|
+
prev_by_id.set(id, t);
|
|
99
|
+
}
|
|
95
100
|
this.token_symbol_map.clear();
|
|
96
101
|
this.token_address_map.clear();
|
|
97
102
|
const merged = [];
|
|
98
103
|
for (const fresh of token_list) {
|
|
99
|
-
|
|
104
|
+
if (!fresh._id)
|
|
105
|
+
fresh._id = (fresh.address || '').toLowerCase();
|
|
106
|
+
const existing = prev_by_id.get(fresh._id);
|
|
100
107
|
let token_ref;
|
|
101
108
|
if (existing) {
|
|
102
109
|
Object.assign(existing, fresh);
|
|
@@ -106,7 +113,7 @@ class ArbCache {
|
|
|
106
113
|
token_ref = fresh;
|
|
107
114
|
}
|
|
108
115
|
this.token_symbol_map.set(token_ref.symbol, token_ref);
|
|
109
|
-
this.token_address_map.set(token_ref.
|
|
116
|
+
this.token_address_map.set(token_ref._id, token_ref);
|
|
110
117
|
merged.push(token_ref);
|
|
111
118
|
}
|
|
112
119
|
this.token_list = merged;
|
|
@@ -114,28 +121,21 @@ class ArbCache {
|
|
|
114
121
|
(0, index_1.log_trace)('refresh_local_cache_token_list, success', {
|
|
115
122
|
token_list_len: this.token_list.length,
|
|
116
123
|
token_symbol_map_size: this.token_symbol_map.size,
|
|
117
|
-
|
|
124
|
+
token_address_map_size: this.token_address_map.size,
|
|
118
125
|
});
|
|
119
126
|
}
|
|
120
127
|
getTokenByAddress(address) {
|
|
121
|
-
var _a;
|
|
122
128
|
if (!address)
|
|
123
129
|
return undefined;
|
|
124
|
-
|
|
125
|
-
if (exact)
|
|
126
|
-
return exact;
|
|
127
|
-
const lc = address.toLowerCase();
|
|
128
|
-
for (const m of this.token_address_map.values()) {
|
|
129
|
-
if (((_a = m.address) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === lc)
|
|
130
|
-
return m;
|
|
131
|
-
}
|
|
132
|
-
return undefined;
|
|
130
|
+
return this.token_address_map.get(address.toLowerCase());
|
|
133
131
|
}
|
|
134
132
|
refresh_local_cache_pool_list(pool_list) {
|
|
135
133
|
this.pool_list = pool_list;
|
|
136
134
|
this.pool_address_map.clear();
|
|
137
135
|
for (let pool of pool_list) {
|
|
138
|
-
|
|
136
|
+
if (!pool._id)
|
|
137
|
+
pool._id = (pool.pool_address || '').toLowerCase();
|
|
138
|
+
this.pool_address_map.set(pool._id, pool);
|
|
139
139
|
}
|
|
140
140
|
this.pool_list_cahce_last_update_time = (0, index_1.getCurDateTime)();
|
|
141
141
|
(0, index_1.log_trace)('refresh_local_cache_pool_list, success', {
|
|
@@ -170,7 +170,10 @@ class ArbCache {
|
|
|
170
170
|
}
|
|
171
171
|
let config = (0, index_1.readFile)(filepath);
|
|
172
172
|
let token_list = config.token_list.filter(e => e.enable);
|
|
173
|
-
|
|
173
|
+
for (const t of token_list) {
|
|
174
|
+
if (!t._id)
|
|
175
|
+
t._id = (t.address || '').toLowerCase();
|
|
176
|
+
}
|
|
174
177
|
for (let token of token_list) {
|
|
175
178
|
let field = token.symbol;
|
|
176
179
|
let value = JSON.stringify(token);
|
|
@@ -196,18 +199,27 @@ class ArbCache {
|
|
|
196
199
|
throw new Error(`update_token_list failed, config file not exist! filepath=${filepath}`);
|
|
197
200
|
}
|
|
198
201
|
let config = (0, index_1.readFile)(filepath);
|
|
199
|
-
|
|
200
|
-
|
|
202
|
+
const input_symbols_upper = new Set();
|
|
203
|
+
const upserts = [];
|
|
204
|
+
const hdels = [];
|
|
205
|
+
for (const token of input_token_list) {
|
|
206
|
+
if (!token._id)
|
|
207
|
+
token._id = (token.address || '').toLowerCase();
|
|
208
|
+
input_symbols_upper.add(token.symbol.toUpperCase());
|
|
201
209
|
if (token.enable) {
|
|
202
|
-
|
|
210
|
+
upserts.push(token);
|
|
203
211
|
}
|
|
204
212
|
else {
|
|
205
213
|
(0, index_1.log_warn)(`update_token_list, token not enable, delete`, token);
|
|
206
|
-
|
|
207
|
-
yield this.loading_cache.hdel(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST, field);
|
|
214
|
+
hdels.push(token.symbol);
|
|
208
215
|
}
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
}
|
|
217
|
+
const others = config.token_list.filter(e => !input_symbols_upper.has(e.symbol.toUpperCase()));
|
|
218
|
+
others.push(...upserts);
|
|
219
|
+
others.sort((a, b) => a.symbol.localeCompare(b.symbol));
|
|
220
|
+
config.token_list = others;
|
|
221
|
+
for (const field of hdels) {
|
|
222
|
+
yield this.loading_cache.hdel(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST, field);
|
|
211
223
|
}
|
|
212
224
|
(0, index_1.writeFile)(filepath, (0, index_1.to_json_str)(config));
|
|
213
225
|
yield this.cache_token_list();
|
|
@@ -215,22 +227,16 @@ class ArbCache {
|
|
|
215
227
|
});
|
|
216
228
|
}
|
|
217
229
|
get_token_list() {
|
|
218
|
-
return __awaiter(this,
|
|
219
|
-
if (!(0, index_1.isEmpty)(this.token_list)) {
|
|
230
|
+
return __awaiter(this, arguments, void 0, function* (force_load = false) {
|
|
231
|
+
if (!force_load && !(0, index_1.isEmpty)(this.token_list)) {
|
|
220
232
|
return this.token_list;
|
|
221
233
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
227
|
-
let token_list = [];
|
|
228
|
-
let res = yield this.loading_cache.hget_all(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST);
|
|
229
|
-
let { key, value } = res;
|
|
230
|
-
for (let name of Object.keys(value)) {
|
|
231
|
-
token_list.push(JSON.parse(value[name]));
|
|
234
|
+
const res = yield this.loading_cache.hget_all(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST);
|
|
235
|
+
const token_list = [];
|
|
236
|
+
for (const name of Object.keys(res.value)) {
|
|
237
|
+
token_list.push(JSON.parse(res.value[name]));
|
|
232
238
|
}
|
|
233
|
-
(0, index_1.
|
|
239
|
+
(0, index_1.log_trace)(`[get_token_list] reload from redis, key=${res.key}, len=${token_list.length}`);
|
|
234
240
|
this.refresh_local_cache_token_list(token_list);
|
|
235
241
|
return token_list;
|
|
236
242
|
});
|
|
@@ -272,6 +278,10 @@ class ArbCache {
|
|
|
272
278
|
const skipped = [];
|
|
273
279
|
for (let { dex_id, pool_list } of config.dex_list) {
|
|
274
280
|
pool_list = pool_list.filter(e => e.enable);
|
|
281
|
+
for (const p of pool_list) {
|
|
282
|
+
if (!p._id)
|
|
283
|
+
p._id = (p.pool_address || '').toLowerCase();
|
|
284
|
+
}
|
|
275
285
|
(0, index_1.log_trace)(`cache_pool_list`, { dex_id, pool_list_len: pool_list.length });
|
|
276
286
|
const valid_pools = [];
|
|
277
287
|
for (let pool of pool_list) {
|
|
@@ -309,12 +319,12 @@ class ArbCache {
|
|
|
309
319
|
var _a;
|
|
310
320
|
const by_addr = new Map();
|
|
311
321
|
for (const t of token_list) {
|
|
312
|
-
const
|
|
313
|
-
if (!
|
|
322
|
+
const id = t._id || (t.address || '').toLowerCase();
|
|
323
|
+
if (!id)
|
|
314
324
|
continue;
|
|
315
|
-
if (!by_addr.has(
|
|
316
|
-
by_addr.set(
|
|
317
|
-
by_addr.get(
|
|
325
|
+
if (!by_addr.has(id))
|
|
326
|
+
by_addr.set(id, []);
|
|
327
|
+
by_addr.get(id).push(t);
|
|
318
328
|
}
|
|
319
329
|
const fixed_by_addr = new Map();
|
|
320
330
|
for (const f of (0, fixed_symbol_address_1.get_fixed_symbol_address)()) {
|
|
@@ -340,21 +350,67 @@ class ArbCache {
|
|
|
340
350
|
}
|
|
341
351
|
resolve_duplicate_address(authoritative_mappings) {
|
|
342
352
|
return __awaiter(this, void 0, void 0, function* () {
|
|
343
|
-
const
|
|
353
|
+
const authMap = new Map();
|
|
354
|
+
const invalid_input = [];
|
|
355
|
+
for (const m of authoritative_mappings) {
|
|
356
|
+
const addr = (m.address || '').toLowerCase();
|
|
357
|
+
const sym = m.symbol || '';
|
|
358
|
+
if (!addr) {
|
|
359
|
+
invalid_input.push({ address: addr, symbol: sym, reason: 'address 为空' });
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (!/^[A-Z0-9]+$/.test(sym)) {
|
|
363
|
+
invalid_input.push({ address: addr, symbol: sym, reason: 'symbol 非 [A-Z0-9]+' });
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
authMap.set(addr, sym);
|
|
367
|
+
}
|
|
368
|
+
const cleaned_redis_fields = [];
|
|
369
|
+
const dropped_value_symbols = new Set();
|
|
370
|
+
const tokenHashRes = yield this.loading_cache.hget_all(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST);
|
|
371
|
+
const fields_by_addr = new Map();
|
|
372
|
+
for (const fieldName of Object.keys(tokenHashRes.value)) {
|
|
373
|
+
let v;
|
|
374
|
+
try {
|
|
375
|
+
v = JSON.parse(tokenHashRes.value[fieldName]);
|
|
376
|
+
}
|
|
377
|
+
catch (_a) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const addr = (v.address || '').toLowerCase();
|
|
381
|
+
if (!addr)
|
|
382
|
+
continue;
|
|
383
|
+
if (!fields_by_addr.has(addr))
|
|
384
|
+
fields_by_addr.set(addr, []);
|
|
385
|
+
fields_by_addr.get(addr).push({ field: fieldName, v });
|
|
386
|
+
}
|
|
387
|
+
for (const [addr, authSym] of authMap) {
|
|
388
|
+
const fields = fields_by_addr.get(addr) || [];
|
|
389
|
+
for (const { field, v } of fields) {
|
|
390
|
+
if (field === authSym && v.symbol === authSym)
|
|
391
|
+
continue;
|
|
392
|
+
yield this.loading_cache.hdel(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_TOKEN_LIST, field);
|
|
393
|
+
cleaned_redis_fields.push({ field, address: addr, value_symbol: v.symbol || '', kept_symbol: authSym });
|
|
394
|
+
if (v.symbol)
|
|
395
|
+
dropped_value_symbols.add(v.symbol);
|
|
396
|
+
if (field !== v.symbol)
|
|
397
|
+
dropped_value_symbols.add(field);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
const token_list = yield this.get_token_list(true);
|
|
344
401
|
const by_addr = new Map();
|
|
345
402
|
for (const t of token_list) {
|
|
346
|
-
const
|
|
347
|
-
if (!
|
|
403
|
+
const id = t._id || (t.address || '').toLowerCase();
|
|
404
|
+
if (!id)
|
|
348
405
|
continue;
|
|
349
|
-
if (!by_addr.has(
|
|
350
|
-
by_addr.set(
|
|
351
|
-
by_addr.get(
|
|
406
|
+
if (!by_addr.has(id))
|
|
407
|
+
by_addr.set(id, []);
|
|
408
|
+
by_addr.get(id).push(t);
|
|
352
409
|
}
|
|
353
410
|
const tokens_to_disable = [];
|
|
354
411
|
const cleaned_tokens = [];
|
|
355
412
|
const not_found = [];
|
|
356
|
-
for (const
|
|
357
|
-
const addr = (address || '').toLowerCase();
|
|
413
|
+
for (const [addr, symbol] of authMap) {
|
|
358
414
|
const tokens = by_addr.get(addr) || [];
|
|
359
415
|
if (tokens.length === 0) {
|
|
360
416
|
not_found.push({ address: addr, symbol, reason: `address 在 token-list 中未找到` });
|
|
@@ -370,6 +426,7 @@ class ArbCache {
|
|
|
370
426
|
continue;
|
|
371
427
|
for (const t of dropped) {
|
|
372
428
|
tokens_to_disable.push(Object.assign(Object.assign({}, t), { enable: false }));
|
|
429
|
+
dropped_value_symbols.add(t.symbol);
|
|
373
430
|
}
|
|
374
431
|
cleaned_tokens.push({
|
|
375
432
|
address: addr,
|
|
@@ -382,13 +439,14 @@ class ArbCache {
|
|
|
382
439
|
const skipped_trading_pools = [];
|
|
383
440
|
if (dropped_symbols.size > 0) {
|
|
384
441
|
const pool_list = yield this.get_pool_list();
|
|
385
|
-
const trade_pool_set = new Set((yield this.get_all_trade_pools()).map(p => p.pool_address));
|
|
442
|
+
const trade_pool_set = new Set((yield this.get_all_trade_pools()).map(p => p._id || (p.pool_address || '').toLowerCase()));
|
|
386
443
|
const pools_to_disable_by_dex = new Map();
|
|
387
444
|
for (const p of pool_list) {
|
|
388
445
|
const [t0, t1] = (p.pool_name || '').split('/');
|
|
389
446
|
if (!dropped_symbols.has(t0) && !dropped_symbols.has(t1))
|
|
390
447
|
continue;
|
|
391
|
-
|
|
448
|
+
const pid = p._id || (p.pool_address || '').toLowerCase();
|
|
449
|
+
if (trade_pool_set.has(pid)) {
|
|
392
450
|
skipped_trading_pools.push({
|
|
393
451
|
pool_address: p.pool_address,
|
|
394
452
|
pool_name: p.pool_name,
|
|
@@ -413,8 +471,8 @@ class ArbCache {
|
|
|
413
471
|
if (tokens_to_disable.length > 0) {
|
|
414
472
|
yield this.update_token_list(tokens_to_disable);
|
|
415
473
|
}
|
|
416
|
-
(0, index_1.log_warn)(`[resolve-duplicate] 完成: disabled ${tokens_to_disable.length} 个 symbol, 删 ${cleaned_pools.length} 个 pool, 跳过交易中 pool ${skipped_trading_pools.length} 个,
|
|
417
|
-
return { cleaned_tokens, cleaned_pools, skipped_trading_pools, not_found };
|
|
474
|
+
(0, index_1.log_warn)(`[resolve-duplicate] 完成: redis stale field ${cleaned_redis_fields.length}, file disabled ${tokens_to_disable.length} 个 symbol, 删 ${cleaned_pools.length} 个 pool, 跳过交易中 pool ${skipped_trading_pools.length} 个, not_found ${not_found.length}, invalid_input ${invalid_input.length}`);
|
|
475
|
+
return { cleaned_redis_fields, cleaned_tokens, cleaned_pools, skipped_trading_pools, not_found, invalid_input };
|
|
418
476
|
});
|
|
419
477
|
}
|
|
420
478
|
set_pool_token_info(pool, token_info_list) {
|
|
@@ -496,43 +554,45 @@ class ArbCache {
|
|
|
496
554
|
});
|
|
497
555
|
}
|
|
498
556
|
get_pool_list() {
|
|
499
|
-
return __awaiter(this,
|
|
500
|
-
if (!(0, index_1.isEmpty)(this.pool_list)) {
|
|
557
|
+
return __awaiter(this, arguments, void 0, function* (force_load = false) {
|
|
558
|
+
if (!force_load && !(0, index_1.isEmpty)(this.pool_list)) {
|
|
501
559
|
return this.pool_list;
|
|
502
560
|
}
|
|
503
|
-
(0, index_1.log_warn)(`get_pool_list, local cache is empty, try get_pool_list_no_cache...`);
|
|
504
|
-
return yield this.get_pool_list_no_cache();
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
get_pool_list_no_cache() {
|
|
508
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
509
561
|
try {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
pool_list.push(JSON.parse(value[name]));
|
|
562
|
+
const res = yield this.loading_cache.hget_all(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_POOL_LIST);
|
|
563
|
+
const pool_list = [];
|
|
564
|
+
for (const name of Object.keys(res.value)) {
|
|
565
|
+
pool_list.push(JSON.parse(res.value[name]));
|
|
515
566
|
}
|
|
516
|
-
(0, index_1.
|
|
567
|
+
(0, index_1.log_trace)(`[get_pool_list] reload from redis, key=${res.key}, len=${pool_list.length}`);
|
|
517
568
|
this.refresh_local_cache_pool_list(pool_list);
|
|
518
569
|
return pool_list;
|
|
519
570
|
}
|
|
520
571
|
catch (err) {
|
|
521
|
-
(0, index_1.log_error)('
|
|
522
|
-
throw new Error(`
|
|
572
|
+
(0, index_1.log_error)('get_pool_list reload error!!!', err);
|
|
573
|
+
throw new Error(`get_pool_list error! err=${err.message}`);
|
|
523
574
|
}
|
|
524
575
|
});
|
|
525
576
|
}
|
|
526
577
|
get_one_pool_info(pool_address_1) {
|
|
527
578
|
return __awaiter(this, arguments, void 0, function* (pool_address, refresh_cache_if_not_found = true) {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
pool_info = this.pool_address_map.get(pool_address);
|
|
531
|
-
}
|
|
579
|
+
const target = (pool_address || '').toLowerCase();
|
|
580
|
+
let pool_info = this.pool_address_map.get(target) || null;
|
|
532
581
|
if (!pool_info && refresh_cache_if_not_found) {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
582
|
+
for (const field of [pool_address, target]) {
|
|
583
|
+
if (!field)
|
|
584
|
+
continue;
|
|
585
|
+
const res = yield this.loading_cache.hget(this.chain_id, index_1.CACHE_KEY_TYPE.CONFIG_POOL_LIST, field);
|
|
586
|
+
if (res === null || res === void 0 ? void 0 : res.value) {
|
|
587
|
+
pool_info = JSON.parse(res.value);
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (!pool_info) {
|
|
592
|
+
(0, index_1.log_warn)(`get_one_pool_info, hget miss, try full reload`);
|
|
593
|
+
const pool_list = yield this.get_pool_list(true);
|
|
594
|
+
pool_info = pool_list.find(e => (e._id || (e.pool_address || '').toLowerCase()) === target);
|
|
595
|
+
}
|
|
536
596
|
}
|
|
537
597
|
if (!pool_info) {
|
|
538
598
|
throw new Error(`get_one_pool_info failed, not exist! pool_address=${pool_address}`);
|
|
@@ -89,7 +89,7 @@ class ArbEventSubscriber {
|
|
|
89
89
|
on_config_token_change_event(message) {
|
|
90
90
|
return __awaiter(this, void 0, void 0, function* () {
|
|
91
91
|
(0, index_1.log_debug)(`on_config_token_change_event, refresh local token cache, start`, { message });
|
|
92
|
-
yield this.arb_cache.
|
|
92
|
+
yield this.arb_cache.get_token_list(true);
|
|
93
93
|
(0, index_1.log_debug)(`on_config_token_change_event, refresh local token cache, success`);
|
|
94
94
|
return true;
|
|
95
95
|
});
|
|
@@ -97,7 +97,7 @@ class ArbEventSubscriber {
|
|
|
97
97
|
on_config_pool_change_event(message) {
|
|
98
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
99
99
|
(0, index_1.log_debug)(`on_config_pool_change_event, refresh local pool cache, start`, { message });
|
|
100
|
-
yield this.arb_cache.
|
|
100
|
+
yield this.arb_cache.get_pool_list(true);
|
|
101
101
|
(0, index_1.log_debug)(`on_config_pool_change_event, refresh local pool cache, success`);
|
|
102
102
|
return true;
|
|
103
103
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -128,7 +128,7 @@ export declare enum LOCAL_EVENT_NAME {
|
|
|
128
128
|
EVENT_WALLET_TRANSACTION = "EVENT_WALLET_TRANSACTION",
|
|
129
129
|
EVENT_WALLET_TRANSACTION_NEW_TXID = "EVENT_WALLET_TRANSACTION_NEW_TXID"
|
|
130
130
|
}
|
|
131
|
-
export declare const
|
|
131
|
+
export declare const format_token_symbol: (symbol: string) => string;
|
|
132
132
|
export declare const format_pair_symbol: (symbol: string) => string;
|
|
133
133
|
export declare const format_unique_orderbook_id: (chain_id: CHAIN_ID, dex_id: DEX_ID, pool_id: string, fee_rate: number) => string;
|
|
134
134
|
export declare const parse_unique_orderbook_id: (unique_orderbook_id: string) => UniqueOrderbookIdType;
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ 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.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_new_block_channel_name = 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.getLoadingCache = exports.getRedisClient = exports.format_order_lock_key = exports.format_unique_order_msg_id = exports.parse_unique_orderbook_id = exports.format_unique_orderbook_id = exports.format_pair_symbol = exports.
|
|
51
|
+
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_new_block_channel_name = 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.getLoadingCache = exports.getRedisClient = exports.format_order_lock_key = exports.format_unique_order_msg_id = exports.parse_unique_orderbook_id = exports.format_unique_orderbook_id = exports.format_pair_symbol = exports.format_token_symbol = 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
52
|
exports.inspect_arb_local_cache = exports.save_trade_execution_logs = exports.get_input_out_token_fix = exports.get_input_out_token = exports.calc_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 = exports.DATE_TIME_FORMAT_NO_WHITESPACE = void 0;
|
|
53
53
|
exports._caller = _caller;
|
|
54
54
|
exports.log_trace = log_trace;
|
|
@@ -220,19 +220,17 @@ var LOCAL_EVENT_NAME;
|
|
|
220
220
|
LOCAL_EVENT_NAME["EVENT_WALLET_TRANSACTION"] = "EVENT_WALLET_TRANSACTION";
|
|
221
221
|
LOCAL_EVENT_NAME["EVENT_WALLET_TRANSACTION_NEW_TXID"] = "EVENT_WALLET_TRANSACTION_NEW_TXID";
|
|
222
222
|
})(LOCAL_EVENT_NAME || (exports.LOCAL_EVENT_NAME = LOCAL_EVENT_NAME = {}));
|
|
223
|
-
const
|
|
223
|
+
const format_token_symbol = (symbol) => {
|
|
224
224
|
if (!symbol)
|
|
225
|
-
return
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
.replace(/\s+/g, '')
|
|
229
|
-
.toUpperCase();
|
|
225
|
+
return '';
|
|
226
|
+
const cleaned = symbol.replace(/[^A-Za-z0-9]/g, '').toUpperCase();
|
|
227
|
+
return /^[A-Z0-9]+$/.test(cleaned) ? cleaned : '';
|
|
230
228
|
};
|
|
231
|
-
exports.
|
|
229
|
+
exports.format_token_symbol = format_token_symbol;
|
|
232
230
|
const format_pair_symbol = (symbol) => {
|
|
233
231
|
if (!symbol)
|
|
234
232
|
return symbol;
|
|
235
|
-
return (0, exports.
|
|
233
|
+
return (0, exports.format_token_symbol)(symbol)
|
|
236
234
|
.replace('USDC', 'USDT').replace('USD1', 'USDT')
|
|
237
235
|
.replace('WTRX', 'TRX').replace('WSOL', 'SOL').replace('WBTC', 'BTC')
|
|
238
236
|
.replace('WETH', 'ETH').replace('WBNB', 'BNB').replace('WOKB', 'OKB');
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { CHAIN_ID, DEX_ID, FormattedPoolInfo, FormattedTokenInfo } from "../index";
|
|
2
|
-
export declare const cache_pool_config: (chain_id: CHAIN_ID,
|
|
2
|
+
export declare const cache_pool_config: (chain_id: CHAIN_ID, tokens_map: Map<string, FormattedTokenInfo>, pools_map: Map<DEX_ID, FormattedPoolInfo[]>) => Promise<void>;
|
|
@@ -18,7 +18,7 @@ const core_env_1 = require("../appconfig/core_env");
|
|
|
18
18
|
const index_1 = require("../index");
|
|
19
19
|
const service_ports_1 = require("../constants/service_ports");
|
|
20
20
|
const is_not_arb_token_1 = require("../token/is_not_arb_token");
|
|
21
|
-
const cache_pool_config = (chain_id,
|
|
21
|
+
const cache_pool_config = (chain_id, tokens_map, pools_map) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
22
|
(0, index_1.log_info)(`cache_pool_config start`);
|
|
23
23
|
let count = 0;
|
|
24
24
|
let skip_pool_list = [];
|
|
@@ -26,15 +26,17 @@ const cache_pool_config = (chain_id, valid_tokens_map, sol_pools_cache) => __awa
|
|
|
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
27
|
const config_pool_url = `${ccBase}/pools`;
|
|
28
28
|
const body = [];
|
|
29
|
-
for (const [dex_id, pool_list] of
|
|
29
|
+
for (const [dex_id, pool_list] of pools_map) {
|
|
30
30
|
const valid_pool_list = [];
|
|
31
31
|
for (const pool of pool_list) {
|
|
32
|
-
const
|
|
33
|
-
|
|
32
|
+
const tokenAExists = tokens_map.has(pool.tokenA._id);
|
|
33
|
+
const tokenBExists = tokens_map.has(pool.tokenB._id);
|
|
34
|
+
if (!tokenAExists || !tokenBExists || (0, is_not_arb_token_1.is_not_arb_token)(pool.pool_name)) {
|
|
34
35
|
skip_pool_list.push(pool);
|
|
35
36
|
continue;
|
|
36
37
|
}
|
|
37
38
|
valid_pool_list.push({
|
|
39
|
+
_id: (pool.pool_address || '').toLowerCase(),
|
|
38
40
|
program_id: pool.program_id,
|
|
39
41
|
authority: pool.authority,
|
|
40
42
|
subscribe_type: 'grpc',
|
|
@@ -42,7 +44,6 @@ const cache_pool_config = (chain_id, valid_tokens_map, sol_pools_cache) => __awa
|
|
|
42
44
|
dex_id,
|
|
43
45
|
pool_name: pool.pool_name,
|
|
44
46
|
pool_address: pool.pool_address,
|
|
45
|
-
pool_address_hex: '',
|
|
46
47
|
tokenA: null,
|
|
47
48
|
tokenB: null,
|
|
48
49
|
vaultA: pool.vaultA,
|
package/dist/pool/types.d.ts
CHANGED
|
@@ -72,17 +72,17 @@ function to_price_message(appConfig_1, quote_amount_usd_1, tx_price_1, quote_ask
|
|
|
72
72
|
unique_orderbook_id,
|
|
73
73
|
is_reverse_token,
|
|
74
74
|
tokenA: {
|
|
75
|
+
_id: tokenA._id || (tokenA.address || '').toLowerCase(),
|
|
75
76
|
symbol: tokenA.symbol,
|
|
76
77
|
address: tokenA.address,
|
|
77
|
-
address_hex: tokenA.address_hex,
|
|
78
78
|
decimals: tokenA.decimals,
|
|
79
79
|
name: tokenA.name,
|
|
80
80
|
enable: true,
|
|
81
81
|
},
|
|
82
82
|
tokenB: {
|
|
83
|
+
_id: tokenB._id || (tokenB.address || '').toLowerCase(),
|
|
83
84
|
symbol: tokenB.symbol,
|
|
84
85
|
address: tokenB.address,
|
|
85
|
-
address_hex: tokenB.address_hex,
|
|
86
86
|
decimals: tokenB.decimals,
|
|
87
87
|
name: tokenB.name,
|
|
88
88
|
enable: true,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { CHAIN_ID, FormattedTokenInfo } from "../index";
|
|
2
|
-
export declare const cache_token_config: (chain_id: CHAIN_ID,
|
|
2
|
+
export declare const cache_token_config: (chain_id: CHAIN_ID, tokens_map: Map<string, FormattedTokenInfo>) => Promise<void>;
|
|
@@ -18,20 +18,22 @@ const core_env_1 = require("../appconfig/core_env");
|
|
|
18
18
|
const index_1 = require("../index");
|
|
19
19
|
const service_ports_1 = require("../constants/service_ports");
|
|
20
20
|
const is_not_arb_token_1 = require("./is_not_arb_token");
|
|
21
|
-
const cache_token_config = (chain_id,
|
|
21
|
+
const cache_token_config = (chain_id, tokens_map) => __awaiter(void 0, void 0, void 0, function* () {
|
|
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
25
|
const config_token_url = `${ccBase}/tokens`;
|
|
26
26
|
const valid_tokens = [];
|
|
27
|
-
for (const
|
|
28
|
-
if (!
|
|
27
|
+
for (const token of tokens_map.values()) {
|
|
28
|
+
if (!(token === null || token === void 0 ? void 0 : token.symbol) || !token.address)
|
|
29
29
|
continue;
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if ((0, is_not_arb_token_1.is_not_arb_token)(token.symbol))
|
|
31
|
+
continue;
|
|
32
|
+
valid_tokens.push({
|
|
33
|
+
_id: (token.address || '').toLowerCase(),
|
|
32
34
|
symbol: token.symbol,
|
|
35
|
+
raw_symbol: token.raw_symbol,
|
|
33
36
|
address: token.address,
|
|
34
|
-
address_hex: '',
|
|
35
37
|
decimals: token.decimals,
|
|
36
38
|
name: token.name,
|
|
37
39
|
is_token2022: token.is_token_2022,
|
|
@@ -39,10 +41,7 @@ const cache_token_config = (chain_id, valid_tokens_map) => __awaiter(void 0, voi
|
|
|
39
41
|
update_time: (0, index_1.getCurDateTime)(),
|
|
40
42
|
alias: (0, index_1.get_token_symbol_alias)(token.address),
|
|
41
43
|
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);
|
|
44
|
+
});
|
|
46
45
|
}
|
|
47
46
|
if (valid_tokens.length > 0) {
|
|
48
47
|
const res = (yield axios_1.default.post(config_token_url, valid_tokens, {
|
package/dist/token/index.d.ts
CHANGED
package/dist/token/index.js
CHANGED
|
@@ -20,6 +20,9 @@ export declare class TokenPriceSyncer {
|
|
|
20
20
|
constructor(opts: TokenPriceSyncerOpts);
|
|
21
21
|
start(): Promise<void>;
|
|
22
22
|
stop(): void;
|
|
23
|
+
private _is_running;
|
|
24
|
+
get is_running(): boolean;
|
|
23
25
|
runOnce(): Promise<void>;
|
|
26
|
+
private _runOnceInner;
|
|
24
27
|
private loadTradeTokensFromCache;
|
|
25
28
|
}
|
|
@@ -15,6 +15,7 @@ class TokenPriceSyncer {
|
|
|
15
15
|
constructor(opts) {
|
|
16
16
|
this.timer = null;
|
|
17
17
|
this.trade_token_map = new Map();
|
|
18
|
+
this._is_running = false;
|
|
18
19
|
this.opts = opts;
|
|
19
20
|
}
|
|
20
21
|
start() {
|
|
@@ -36,7 +37,23 @@ class TokenPriceSyncer {
|
|
|
36
37
|
this.timer = null;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
40
|
+
get is_running() { return this._is_running; }
|
|
39
41
|
runOnce() {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
if (this._is_running) {
|
|
44
|
+
(0, __1.log_warn)(`[TokenPriceSyncer] previous run still in flight, skip this tick`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this._is_running = true;
|
|
48
|
+
try {
|
|
49
|
+
yield this._runOnceInner();
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
this._is_running = false;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
_runOnceInner() {
|
|
40
57
|
return __awaiter(this, void 0, void 0, function* () {
|
|
41
58
|
var _a;
|
|
42
59
|
yield this.loadTradeTokensFromCache();
|
package/dist/token/token_util.js
CHANGED
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.is_valid_symbol =
|
|
3
|
+
exports.is_valid_symbol = void 0;
|
|
4
4
|
exports.get_token_symbol_alias = get_token_symbol_alias;
|
|
5
5
|
const __1 = require("..");
|
|
6
|
-
const formate_token_symbol = (symbol) => {
|
|
7
|
-
return symbol.toUpperCase()
|
|
8
|
-
.replace('$', '')
|
|
9
|
-
.replace('WSOL', 'SOL')
|
|
10
|
-
.replace('WBTC', 'BTC')
|
|
11
|
-
.replace('WETH', 'ETH').replace('WHETH', 'ETH')
|
|
12
|
-
.replace('WBNB', 'BNB')
|
|
13
|
-
.replace('WTRX', 'TRX')
|
|
14
|
-
.replace('WAVAX', 'AVAX')
|
|
15
|
-
.replace('WOKB', 'OKB')
|
|
16
|
-
.trim();
|
|
17
|
-
};
|
|
18
|
-
exports.formate_token_symbol = formate_token_symbol;
|
|
19
6
|
const is_valid_symbol = (symbol) => {
|
|
20
|
-
return !(0, __1.isEmpty)(symbol) && /^[
|
|
7
|
+
return !(0, __1.isEmpty)(symbol) && /^[A-Z0-9]+$/.test(symbol);
|
|
21
8
|
};
|
|
22
9
|
exports.is_valid_symbol = is_valid_symbol;
|
|
23
10
|
function get_token_symbol_alias(token_address) {
|
|
24
|
-
|
|
11
|
+
const lc = (token_address || '').toLowerCase();
|
|
12
|
+
let token = (0, __1.get_fixed_symbol_address)().find(e => (e.address || '').toLowerCase() === lc);
|
|
25
13
|
return (token === null || token === void 0 ? void 0 : token.alias) || '';
|
|
26
14
|
}
|
package/dist/token/types.d.ts
CHANGED
|
@@ -11,16 +11,14 @@ export interface TokenFixedSymbolAddress {
|
|
|
11
11
|
address: string;
|
|
12
12
|
is_token2022?: boolean;
|
|
13
13
|
}
|
|
14
|
-
export interface ZhPinyinRow {
|
|
15
|
-
zh: string;
|
|
16
|
-
pinyin: string;
|
|
17
|
-
}
|
|
18
14
|
export interface FormattedTokenInfo {
|
|
19
15
|
chainId: number;
|
|
16
|
+
_id: string;
|
|
20
17
|
address: string;
|
|
21
18
|
programId: string;
|
|
22
19
|
logoURI: string;
|
|
23
20
|
symbol: string;
|
|
21
|
+
raw_symbol?: string;
|
|
24
22
|
name: string;
|
|
25
23
|
decimals: number;
|
|
26
24
|
is_token_2022: boolean;
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -9,9 +9,18 @@ export interface StandardTokenConfigType {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface StandardTokenInfoType {
|
|
12
|
+
/**
|
|
13
|
+
* 内部对比/Map key 专用:address.toLowerCase()
|
|
14
|
+
* 任何 token 比较、Map 索引、fixed_symbol 匹配都用这个;
|
|
15
|
+
* 链上调用(RPC / tx encoding)必须用 `address` 原值。
|
|
16
|
+
*/
|
|
17
|
+
_id: string
|
|
18
|
+
/** 标准化后的 symbol:格式 [A-Z0-9]+,所有缓存/查询/比较都用这个字段 */
|
|
12
19
|
symbol: string
|
|
20
|
+
/** 原始来源 symbol(Gecko / on-chain ERC20):用于排查问题、UI 显示,不参与匹配 */
|
|
21
|
+
raw_symbol?: string
|
|
22
|
+
/** 链上原始地址(Tron/Solana 区分大小写,必须保留原值) */
|
|
13
23
|
address: string
|
|
14
|
-
address_hex: string
|
|
15
24
|
decimals: number
|
|
16
25
|
name: string
|
|
17
26
|
is_token2022?: boolean
|
|
@@ -37,6 +46,11 @@ export interface StandardDexPoolConfigType {
|
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
export interface StandardPoolInfoType {
|
|
49
|
+
/**
|
|
50
|
+
* 内部对比/Map key 专用:pool_address.toLowerCase()
|
|
51
|
+
* 任何 pool 比较、Map 索引都用这个;链上交互必须用 `pool_address` 原值。
|
|
52
|
+
*/
|
|
53
|
+
_id: string
|
|
40
54
|
program_id?: string // Raydium Liquidity Pool V4
|
|
41
55
|
authority?: string // Vault owner
|
|
42
56
|
subscribe_type?: string // ws, grpc
|
|
@@ -44,7 +58,6 @@ export interface StandardPoolInfoType {
|
|
|
44
58
|
dex_id: string
|
|
45
59
|
pool_name: string
|
|
46
60
|
pool_address: string
|
|
47
|
-
pool_address_hex: string
|
|
48
61
|
tokenA: StandardTokenInfoType
|
|
49
62
|
tokenB: StandardTokenInfoType
|
|
50
63
|
vaultA?: string
|