@clonegod/ttd-sol-common 2.0.79 → 2.0.80
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/quote/index.d.ts
CHANGED
package/dist/quote/index.js
CHANGED
|
@@ -15,7 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./pricing"), exports);
|
|
18
|
-
__exportStar(require("./pool_subscription_registry"), exports);
|
|
19
18
|
__exportStar(require("./pool_event"), exports);
|
|
20
19
|
__exportStar(require("./chain_ops"), exports);
|
|
21
20
|
__exportStar(require("./abstract_dex_quote"), exports);
|
|
@@ -52,11 +52,18 @@ async function attachPoolSubscriptionLifecycle(appConfig, pools) {
|
|
|
52
52
|
+ '询价进程必须由 PM2/trade-mgt 以确定进程名启动,否则订阅会被 reconcile 当孤儿清除。');
|
|
53
53
|
}
|
|
54
54
|
await registerPoolSubscriptions(appConfig, pools, quote_app_id);
|
|
55
|
+
const heartbeatMs = Math.max(5000, parseInt(process.env.SUBSCRIPTION_HEARTBEAT_MS || '30000', 10) || 30000);
|
|
56
|
+
const heartbeat = setInterval(() => {
|
|
57
|
+
registerPoolSubscriptions(appConfig, pools, quote_app_id)
|
|
58
|
+
.catch(e => (0, dist_1.log_warn)(`[pool/subscriptions] heartbeat re-register failed: ${e.message}`));
|
|
59
|
+
}, heartbeatMs);
|
|
60
|
+
heartbeat.unref?.();
|
|
55
61
|
let cleaned = false;
|
|
56
62
|
const cleanup = async (sig) => {
|
|
57
63
|
if (cleaned)
|
|
58
64
|
return;
|
|
59
65
|
cleaned = true;
|
|
66
|
+
clearInterval(heartbeat);
|
|
60
67
|
(0, dist_1.log_info)(`[pool/subscriptions] ${sig} → unregister ${quote_app_id}`);
|
|
61
68
|
await unregisterPoolSubscriptions(appConfig, quote_app_id);
|
|
62
69
|
process.exit(0);
|
package/package.json
CHANGED
package/src/quote/index.ts
CHANGED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { AppConfig, HttpUtil, log_info, log_warn, SERVICE_PORT, StandardPoolInfoType } from '@clonegod/ttd-core/dist'
|
|
2
|
-
import { resolveGrpcProvider } from '../grpc/grpc_provider_registry'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 按需订阅 —— 生产端(询价进程调用)。对齐 BSC/BASE/SUI:询价进程通过 config-center 声明所需池子,
|
|
6
|
-
* config-center 写 `${chain}:pool:subscriptions` Hash + 广播 `:change`,stream-quote 消费后订阅 Helius。
|
|
7
|
-
*
|
|
8
|
-
* Solana 适配(与 BSC 的差异):
|
|
9
|
-
* - **单 Helius provider,且对齐 SUI 由运维在 analyze Config/RPC 页配(type=grpc, endpoint=laserstream URL, auth_token=API key)**。
|
|
10
|
-
* 本 helper **不自动种 provider**;register 用 `resolveGrpcProvider` 解析出 analyze 配的 provider id(无配 fail-loud)。
|
|
11
|
-
* - **base58 地址大小写敏感**:依赖 config-center `lower()` 已改为 0x 感知(非 0x 原样保留),不破坏地址。
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
function configCenterBase(appConfig: AppConfig): string {
|
|
15
|
-
const chain = appConfig.env_args.chain_id // SOLANA
|
|
16
|
-
let host = String(appConfig.env_args.config_center_host || '127.0.0.1').trim()
|
|
17
|
-
// host 可能含端口(127.0.0.1:4000)或不含(127.0.0.1);不含则补 CONFIG_CENTER_HTTP
|
|
18
|
-
if (!host.includes(':')) host = `${host}:${SERVICE_PORT.CONFIG_CENTER_HTTP}`
|
|
19
|
-
return `http://${host}/${chain}/config`
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** 注册一批池子订阅(每池 POST config-center /quote/register),provider_ids 用 analyze 配的 grpc provider。 */
|
|
23
|
-
export async function registerPoolSubscriptions(
|
|
24
|
-
appConfig: AppConfig,
|
|
25
|
-
pools: StandardPoolInfoType[],
|
|
26
|
-
quote_app_id: string,
|
|
27
|
-
): Promise<void> {
|
|
28
|
-
// provider 由运维在 analyze Config/RPC 配(type=grpc);解析其 id 供 register 引用,无配 fail-loud
|
|
29
|
-
const provider = await resolveGrpcProvider(appConfig.arb_cache.redis_cmd, appConfig.env_args.chain_id)
|
|
30
|
-
const provider_ids = [provider.id]
|
|
31
|
-
|
|
32
|
-
const base = configCenterBase(appConfig)
|
|
33
|
-
let ok = 0
|
|
34
|
-
for (const p of pools) {
|
|
35
|
-
try {
|
|
36
|
-
await HttpUtil.post(`${base}/quote/register`, {
|
|
37
|
-
pool_address: p.pool_address,
|
|
38
|
-
provider_ids,
|
|
39
|
-
quote_app_id,
|
|
40
|
-
pair: p.pair,
|
|
41
|
-
dex_id: p.dex_id,
|
|
42
|
-
pool_name: p.pool_name,
|
|
43
|
-
fee_rate: p.fee_rate,
|
|
44
|
-
})
|
|
45
|
-
ok++
|
|
46
|
-
} catch (e: any) {
|
|
47
|
-
log_warn(`[pool/subscriptions] register ${p.pool_address} failed: ${e.message}`)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
log_info(`[pool/subscriptions] registered ${ok}/${pools.length} pools by ${quote_app_id} → provider=${provider.id}`)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** 注销本进程注册的所有池子订阅(按 quote_app_id)。 */
|
|
54
|
-
export async function unregisterPoolSubscriptions(appConfig: AppConfig, quote_app_id: string): Promise<void> {
|
|
55
|
-
try {
|
|
56
|
-
await HttpUtil.post(`${configCenterBase(appConfig)}/quote/unregister`, { quote_app_id })
|
|
57
|
-
log_info(`[pool/subscriptions] unregistered all pools by ${quote_app_id}`)
|
|
58
|
-
} catch (e: any) {
|
|
59
|
-
log_warn(`[pool/subscriptions] unregister failed: ${e.message}`)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 询价进程启动后调用一次:确保 helius provider + 注册全部池子 + 装退出时自动 unregister。
|
|
65
|
-
* quote_app_id **必须 = PM2 进程名**(pm2 注入 process.env.name),与 trade-mgt register/reconcile 用的 app_id 一致。
|
|
66
|
-
* 否则 trade-mgt 的 60s reconcile 按 PM2 进程名核对,会把本进程自注册的订阅当"孤儿"注销 → 订阅消失、收不到事件。
|
|
67
|
-
* **取不到则 fail-loud(绝不兜底)**:塌成 'sol-quote' 这类 PM2 里不存在的名字 = 必被 reconcile 清掉,等于没注册还掩盖问题。
|
|
68
|
-
*/
|
|
69
|
-
export async function attachPoolSubscriptionLifecycle(appConfig: AppConfig, pools: StandardPoolInfoType[]): Promise<void> {
|
|
70
|
-
const quote_app_id = process.env.name || String(appConfig.env_args.app_name || '')
|
|
71
|
-
if (!quote_app_id) {
|
|
72
|
-
throw new Error('[pool/subscriptions] 无法确定 quote_app_id:process.env.name(PM2 进程名) 与 APP_NAME 均为空。'
|
|
73
|
-
+ '询价进程必须由 PM2/trade-mgt 以确定进程名启动,否则订阅会被 reconcile 当孤儿清除。')
|
|
74
|
-
}
|
|
75
|
-
await registerPoolSubscriptions(appConfig, pools, quote_app_id)
|
|
76
|
-
|
|
77
|
-
let cleaned = false
|
|
78
|
-
const cleanup = async (sig: string) => {
|
|
79
|
-
if (cleaned) return
|
|
80
|
-
cleaned = true
|
|
81
|
-
log_info(`[pool/subscriptions] ${sig} → unregister ${quote_app_id}`)
|
|
82
|
-
await unregisterPoolSubscriptions(appConfig, quote_app_id)
|
|
83
|
-
process.exit(0)
|
|
84
|
-
}
|
|
85
|
-
process.on('SIGINT', () => void cleanup('SIGINT'))
|
|
86
|
-
process.on('SIGTERM', () => void cleanup('SIGTERM'))
|
|
87
|
-
}
|