dexbot 1.6.2 → 1.6.4
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/CHANGELOG.md +53 -3
- package/README.md +11 -7
- package/analysis/README.md +20 -14
- package/analysis/account_resolver.ts +171 -0
- package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +2 -5
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/bot_usage/discover_bot_accounts.ts +20 -27
- package/analysis/chain_pool.ts +47 -0
- package/analysis/chart_utils.ts +33 -20
- package/analysis/derivative_chart_generator.ts +2 -3
- package/analysis/fills_source.ts +234 -0
- package/analysis/grid_correction_check.ts +104 -244
- package/analysis/results/ama_sweep_results_lp_pool_133_1h.json +2455 -0
- package/analysis/results/bot_fitting_results_lp_pool_133_1h.json +218 -0
- package/analysis/trade_profitability.ts +169 -304
- package/analysis/tradingview/README.md +2 -2
- package/analysis/tradingview/h-bts_tradingview.html +1570 -0
- package/analysis/tradingview/t-bts_tradingview.html +1570 -0
- package/analysis/tradingview/tradingview_uplot_chart_generator.ts +3 -4
- package/analysis/trend_detection/dynamic_weight_chart_generator.ts +2 -3
- package/analysis/trend_detection/kalman_chart_generator.ts +2 -3
- package/analysis/trend_detection/package.json +1 -1
- package/analysis/trend_detection/regime_chart_generator.ts +2 -3
- package/analysis/trend_detection/volatility_chart_generator.ts +2 -3
- package/claw/package.json +1 -1
- package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
- package/claw/runtimes/openclaw-plugin/package.json +1 -1
- package/claw/tests/test_claw_mcp_transport.ts +2 -2
- package/dist/analysis/account_resolver.d.ts +43 -0
- package/dist/analysis/account_resolver.d.ts.map +1 -0
- package/dist/analysis/account_resolver.js +137 -0
- package/dist/analysis/account_resolver.js.map +1 -0
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts.map +1 -1
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +2 -4
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -1
- package/dist/analysis/bot_usage/discover_bot_accounts.js +20 -28
- package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -1
- package/dist/analysis/chain_pool.d.ts +10 -0
- package/dist/analysis/chain_pool.d.ts.map +1 -0
- package/dist/analysis/chain_pool.js +47 -0
- package/dist/analysis/chain_pool.js.map +1 -0
- package/dist/analysis/chart_utils.d.ts +14 -1
- package/dist/analysis/chart_utils.d.ts.map +1 -1
- package/dist/analysis/chart_utils.js +32 -22
- package/dist/analysis/chart_utils.js.map +1 -1
- package/dist/analysis/derivative_chart_generator.d.ts.map +1 -1
- package/dist/analysis/derivative_chart_generator.js +2 -3
- package/dist/analysis/derivative_chart_generator.js.map +1 -1
- package/dist/analysis/fills_source.d.ts +79 -0
- package/dist/analysis/fills_source.d.ts.map +1 -0
- package/dist/analysis/fills_source.js +186 -0
- package/dist/analysis/fills_source.js.map +1 -0
- package/dist/analysis/grid_correction_check.d.ts +4 -20
- package/dist/analysis/grid_correction_check.d.ts.map +1 -1
- package/dist/analysis/grid_correction_check.js +95 -248
- package/dist/analysis/grid_correction_check.js.map +1 -1
- package/dist/analysis/trade_profitability.d.ts +18 -19
- package/dist/analysis/trade_profitability.d.ts.map +1 -1
- package/dist/analysis/trade_profitability.js +136 -280
- package/dist/analysis/trade_profitability.js.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +3 -4
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/kalman_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/regime_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/volatility_chart_generator.js.map +1 -1
- package/dist/market_adapter/lp_chart_core.d.ts.map +1 -1
- package/dist/market_adapter/lp_chart_core.js +2 -3
- package/dist/market_adapter/lp_chart_core.js.map +1 -1
- package/dist/modules/account_bots.d.ts +1 -18
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +1 -1
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/bitshares-native/serial/operations.d.ts +1 -84
- package/dist/modules/bitshares-native/serial/operations.d.ts.map +1 -1
- package/dist/modules/bitshares-native/serial/operations.js +1 -38
- package/dist/modules/bitshares-native/serial/operations.js.map +1 -1
- package/dist/modules/cli_colors.d.ts +0 -1
- package/dist/modules/cli_colors.d.ts.map +1 -1
- package/dist/modules/constants.js +5 -5
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/credential_policy.d.ts +1 -25
- package/dist/modules/credential_policy.d.ts.map +1 -1
- package/dist/modules/credential_policy.js +1 -1
- package/dist/modules/credential_policy.js.map +1 -1
- package/dist/modules/credential_runtime.d.ts +1 -6
- package/dist/modules/credential_runtime.d.ts.map +1 -1
- package/dist/modules/credential_runtime.js +1 -1
- package/dist/modules/credential_runtime.js.map +1 -1
- package/dist/modules/credential_session_cache.d.ts +1 -5
- package/dist/modules/credential_session_cache.d.ts.map +1 -1
- package/dist/modules/credential_session_cache.js +1 -1
- package/dist/modules/credential_session_cache.js.map +1 -1
- package/dist/modules/crypto/pure_secp256k1.d.ts +1 -2
- package/dist/modules/crypto/pure_secp256k1.d.ts.map +1 -1
- package/dist/modules/crypto/pure_secp256k1.js +1 -1
- package/dist/modules/crypto/pure_secp256k1.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts +9 -8
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +9 -8
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_cow_runtime.d.ts +87 -7
- package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.js +489 -14
- package/dist/modules/dexbot_cow_runtime.js.map +1 -1
- package/dist/modules/dexbot_fill_runtime.d.ts +1 -17
- package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_fill_runtime.js +1 -1
- package/dist/modules/dexbot_fill_runtime.js.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.js +21 -5
- package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
- package/dist/modules/dexbot_state_recovery.d.ts +1 -7
- package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
- package/dist/modules/dexbot_state_recovery.js +1 -1
- package/dist/modules/dexbot_state_recovery.js.map +1 -1
- package/dist/modules/launcher/adapter_requirement.d.ts +1 -5
- package/dist/modules/launcher/adapter_requirement.d.ts.map +1 -1
- package/dist/modules/launcher/adapter_requirement.js +1 -1
- package/dist/modules/launcher/adapter_requirement.js.map +1 -1
- package/dist/modules/launcher/bot_supervisor.d.ts +1 -6
- package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
- package/dist/modules/launcher/bot_supervisor.js +1 -1
- package/dist/modules/launcher/bot_supervisor.js.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.d.ts +1 -3
- package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
- package/dist/modules/launcher/launch_modes.d.ts +1 -2
- package/dist/modules/launcher/launch_modes.d.ts.map +1 -1
- package/dist/modules/launcher/launch_modes.js +1 -1
- package/dist/modules/launcher/launch_modes.js.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.d.ts +1 -3
- package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.d.ts +1 -5
- package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.js +1 -1
- package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
- package/dist/modules/launcher/status_reporting.d.ts +1 -2
- package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
- package/dist/modules/launcher/status_reporting.js +1 -1
- package/dist/modules/launcher/status_reporting.js.map +1 -1
- package/dist/modules/order/export.d.ts +1 -8
- package/dist/modules/order/export.d.ts.map +1 -1
- package/dist/modules/order/export.js +1 -1
- package/dist/modules/order/export.js.map +1 -1
- package/dist/modules/order/grid.d.ts +7 -0
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +52 -98
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.d.ts +1 -10
- package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.js +2 -2
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
- package/dist/modules/order/manager.d.ts +10 -2
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +20 -7
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +25 -20
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +1 -10
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +1 -1
- package/dist/modules/order/utils/math.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts +45 -7
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +160 -15
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/order/utils/system.d.ts +0 -15
- package/dist/modules/order/utils/system.d.ts.map +1 -1
- package/dist/modules/order/utils/system.js +2 -2
- package/dist/modules/order/utils/system.js.map +1 -1
- package/dist/modules/process_discovery.d.ts +0 -3
- package/dist/modules/process_discovery.d.ts.map +1 -1
- package/dist/modules/process_discovery.js +1 -1
- package/dist/modules/process_discovery.js.map +1 -1
- package/dist/modules/utils/chain_logs.d.ts +1 -2
- package/dist/modules/utils/chain_logs.d.ts.map +1 -1
- package/dist/modules/utils/chain_logs.js +1 -1
- package/dist/modules/utils/chain_logs.js.map +1 -1
- package/dist/scripts/analyze-git.js +2 -2
- package/dist/scripts/analyze-git.js.map +1 -1
- package/dist/scripts/update.js +46 -31
- package/dist/scripts/update.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +110 -40
- package/docs/COPY_ON_WRITE_MASTER_PLAN.md +10 -207
- package/docs/COW_INVARIANTS.md +16 -10
- package/docs/DEXBOT_COMPARISON.md +3 -3
- package/docs/EVOLUTION.md +75 -29
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +6 -6
- package/docs/GRID_RECALCULATION.md +14 -6
- package/docs/GRID_RECONCILE.md +28 -25
- package/docs/LIFECYCLE.md +12 -11
- package/docs/README.md +48 -42
- package/docs/architecture.md +19 -30
- package/docs/developer_guide.md +3 -3
- package/package.json +1 -1
- package/scripts/git-viewer.sh +1 -1
- package/tests/README.md +10 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SHARED CHAIN POOL (analysis)
|
|
5
|
+
*
|
|
6
|
+
* Single source of truth for the node list and the ephemeral read-only
|
|
7
|
+
* connection used by analysis tools for small on-chain lookups (account name
|
|
8
|
+
* resolution, asset precision resolution).
|
|
9
|
+
*
|
|
10
|
+
* Analysis tools deliberately do NOT use the production singleton client
|
|
11
|
+
* (modules/bitshares_client.ts): they are short-lived processes and must never
|
|
12
|
+
* disturb a running bot's connection state. Instead each lookup opens a fresh
|
|
13
|
+
* read-only client over the built-in node pool, which the native transport
|
|
14
|
+
* races in parallel and then retries sequentially — so one dead node is not
|
|
15
|
+
* fatal.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import * as C from '../modules/constants.js';
|
|
19
|
+
|
|
20
|
+
/** Nodes for ephemeral read-only analysis connections (node management pool). */
|
|
21
|
+
function defaultNodePool(): string[] {
|
|
22
|
+
return [...C.NODE_MANAGEMENT.DEFAULT_NODES];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Run `fn` against a fresh read-only client connected over the built-in pool.
|
|
27
|
+
* Transport INFO logging is silenced for the duration of the short-lived
|
|
28
|
+
* connection and the client is always disconnected afterwards.
|
|
29
|
+
*/
|
|
30
|
+
async function withReadOnlyClient<T>(fn: (client: any) => Promise<T>): Promise<T> {
|
|
31
|
+
const { createReadOnlyClient } = await import('../modules/bitshares-native/index.js');
|
|
32
|
+
const client = createReadOnlyClient({ nodes: defaultNodePool() });
|
|
33
|
+
// Suppress transport INFO logs during ephemeral connection:
|
|
34
|
+
// bitshares-native transport logger (new Logger('Transport')) writes
|
|
35
|
+
// "[timestamp] [INFO] [Transport] ..." — silence by raising log level.
|
|
36
|
+
const prevLevel = process.env.LOG_LEVEL;
|
|
37
|
+
process.env.LOG_LEVEL = 'warn';
|
|
38
|
+
try {
|
|
39
|
+
await client.connect();
|
|
40
|
+
return await fn(client);
|
|
41
|
+
} finally {
|
|
42
|
+
try { client.disconnect(); } catch (_) { /* best-effort cleanup */ }
|
|
43
|
+
process.env.LOG_LEVEL = prevLevel;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { defaultNodePool, withReadOnlyClient };
|
package/analysis/chart_utils.ts
CHANGED
|
@@ -10,26 +10,39 @@ const { ensureDir } = getStorage();
|
|
|
10
10
|
* Chart utilities for analysis HTML generators.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
|
|
13
|
+
// Vendored uPlot runtime assets are inlined directly into every generated chart
|
|
14
|
+
// (see uplotInlineTags below), so each chart is a single self-contained file
|
|
15
|
+
// that renders anywhere: no DEXBot2 install, no sibling uplot/ dir, no CDN, no
|
|
16
|
+
// network. The vendored originals always live with the code under the analysis
|
|
17
|
+
// assets dir.
|
|
18
|
+
let _uplotRuntime: { css: string; js: string } | null = null;
|
|
19
|
+
|
|
20
|
+
function getUplotRuntime() {
|
|
21
|
+
if (!_uplotRuntime) {
|
|
22
|
+
const dir = PATHS.ANALYSIS.ASSETS_DIR;
|
|
23
|
+
_uplotRuntime = {
|
|
24
|
+
css: fs.readFileSync(path.join(dir, 'uPlot.min.css'), 'utf8'),
|
|
25
|
+
js: fs.readFileSync(path.join(dir, 'uPlot.iife.min.js'), 'utf8'),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return _uplotRuntime;
|
|
29
|
+
}
|
|
16
30
|
|
|
17
31
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
32
|
+
* Inline <style>/<script> tags carrying the vendored uPlot runtime. Embedding
|
|
33
|
+
* the source (not a relative <script src>) makes a chart portable: it keeps
|
|
34
|
+
* rendering after being copied, mailed, or reopened on a machine without a
|
|
35
|
+
* DEXBot2 installation. The inline script must be the first script that runs,
|
|
36
|
+
* placed before any chart-initialization code, since uPlot must exist first.
|
|
37
|
+
* Both the minified JS (no `</script>`) and CSS (no `</style>`) are safe to
|
|
38
|
+
* embed verbatim.
|
|
22
39
|
*/
|
|
23
|
-
function
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
30
|
-
for (const f of UPLOT_RUNTIME_FILES) {
|
|
31
|
-
fs.copyFileSync(path.join(sourceDir, f), path.join(targetDir, f));
|
|
32
|
-
}
|
|
40
|
+
function uplotInlineTags({ css = true, js = true } = {}) {
|
|
41
|
+
const { css: cssCode, js: jsCode } = getUplotRuntime();
|
|
42
|
+
const parts: string[] = [];
|
|
43
|
+
if (css && cssCode) parts.push(`<style>\n${cssCode}\n</style>`);
|
|
44
|
+
if (js && jsCode) parts.push(`<script>\n${jsCode}\n</script>`);
|
|
45
|
+
return parts.join('\n ');
|
|
33
46
|
}
|
|
34
47
|
|
|
35
48
|
|
|
@@ -58,9 +71,9 @@ function toFileUrl(filePath: any): string {
|
|
|
58
71
|
return `file://${path.resolve(String(filePath))}`;
|
|
59
72
|
}
|
|
60
73
|
|
|
61
|
-
function writeChartFile(filePath: any, html: any) {
|
|
74
|
+
function writeChartFile(filePath: any, html: any) {
|
|
75
|
+
const chartDir = path.dirname(filePath);
|
|
62
76
|
if (!fs.existsSync(chartDir)) ensureDir(chartDir);
|
|
63
|
-
ensureSiblingUplotAssets(chartDir);
|
|
64
77
|
// Atomic write (tmp + rename, matching the production storage adapter
|
|
65
78
|
// pattern) so a crash mid-write can never leave a truncated chart file.
|
|
66
79
|
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 10)}.tmp`;
|
|
@@ -193,5 +206,5 @@ function bindPan(chart) {
|
|
|
193
206
|
}
|
|
194
207
|
`;
|
|
195
208
|
|
|
196
|
-
export { escapeHtml, serializeJsonForScript, toEpochSeconds, writeChartFile, toFileUrl, embedFunctionSources, UPLOT_SHARED_SCRIPT }
|
|
209
|
+
export { escapeHtml, serializeJsonForScript, toEpochSeconds, writeChartFile, toFileUrl, embedFunctionSources, UPLOT_SHARED_SCRIPT, uplotInlineTags }
|
|
197
210
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { pathToFileURL } from 'node:url';
|
|
7
|
-
import { escapeHtml, serializeJsonForScript, toEpochSeconds, UPLOT_SHARED_SCRIPT } from './chart_utils.js';
|
|
7
|
+
import { escapeHtml, serializeJsonForScript, toEpochSeconds, UPLOT_SHARED_SCRIPT, uplotInlineTags } from './chart_utils.js';
|
|
8
8
|
import { getStorage } from '../modules/storage/index.js';
|
|
9
9
|
const { ensureDir, readJSON } = getStorage();
|
|
10
10
|
import { fixedTo } from '../modules/order/utils/math.js';
|
|
@@ -225,8 +225,7 @@ function generateHTML(data: any, title: string) {
|
|
|
225
225
|
<meta name="darkreader-lock">
|
|
226
226
|
<meta name="color-scheme" content="dark">
|
|
227
227
|
<title>${escapeHtml(title)}</title>
|
|
228
|
-
|
|
229
|
-
<script src="../uplot/uPlot.iife.min.js"></script>
|
|
228
|
+
${uplotInlineTags()}
|
|
230
229
|
<style>
|
|
231
230
|
:root { color-scheme: dark; }
|
|
232
231
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SHARED FILLS SOURCE (analysis)
|
|
5
|
+
*
|
|
6
|
+
* Single implementation of the Kibana `fill_order` pipeline and the asset
|
|
7
|
+
* precision table/cache used by the fill-based analysis tools. Both
|
|
8
|
+
* trade_profitability.ts and grid_correction_check.ts carried verbatim copies
|
|
9
|
+
* of this (43-entry ASSETS table, toReal/assetPrec helpers, on-chain precision
|
|
10
|
+
* resolution, query builder and paginated fetch); all of it lives here now.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as KC from '../market_adapter/core/kibana_client.js';
|
|
14
|
+
import { withReadOnlyClient } from './chain_pool.js';
|
|
15
|
+
|
|
16
|
+
const { kibanaSearch, DEFAULT_CONFIG: BASE_CONFIG } = KC;
|
|
17
|
+
|
|
18
|
+
/** operation_type of a fill_order operation in the chain history index. */
|
|
19
|
+
const OP_FILL_ORDER = 4;
|
|
20
|
+
const BTS_ID = '1.3.0';
|
|
21
|
+
|
|
22
|
+
interface AssetInfo {
|
|
23
|
+
symbol: string;
|
|
24
|
+
precision: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface AssetAmount {
|
|
28
|
+
amount: number;
|
|
29
|
+
asset_id: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface FillRecord {
|
|
33
|
+
time: string;
|
|
34
|
+
blockNum: number;
|
|
35
|
+
opNum: number;
|
|
36
|
+
orderId: string;
|
|
37
|
+
accountId: string;
|
|
38
|
+
pays: AssetAmount;
|
|
39
|
+
receives: AssetAmount;
|
|
40
|
+
fee: AssetAmount;
|
|
41
|
+
isMaker: boolean;
|
|
42
|
+
sort: any[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ASSETS: Record<string, AssetInfo> = {
|
|
46
|
+
'1.3.0': { symbol: 'BTS', precision: 5 },
|
|
47
|
+
'1.3.118': { symbol: 'GBP', precision: 4 },
|
|
48
|
+
'1.3.119': { symbol: 'JPY', precision: 2 },
|
|
49
|
+
'1.3.120': { symbol: 'EUR', precision: 4 },
|
|
50
|
+
'1.3.1325': { symbol: 'RUBLE', precision: 5 },
|
|
51
|
+
'1.3.2512': { symbol: 'EVRAZ', precision: 4 },
|
|
52
|
+
'1.3.3291': { symbol: 'TWENTIX', precision: 5 },
|
|
53
|
+
'1.3.4099': { symbol: 'XBTSX.STH', precision: 6 },
|
|
54
|
+
'1.3.4156': { symbol: 'XBTSX.DOGE', precision: 5 },
|
|
55
|
+
'1.3.4157': { symbol: 'XBTSX.BTC', precision: 8 },
|
|
56
|
+
'1.3.4159': { symbol: 'XBTSX.LTC', precision: 8 },
|
|
57
|
+
'1.3.4176': { symbol: 'XBTSX.DASH', precision: 8 },
|
|
58
|
+
'1.3.4274': { symbol: 'XBTSX.BCH', precision: 8 },
|
|
59
|
+
'1.3.4760': { symbol: 'XBTSX.ETH', precision: 7 },
|
|
60
|
+
'1.3.5537': { symbol: 'IOB.XRP', precision: 4 },
|
|
61
|
+
'1.3.5541': { symbol: 'XBTSX.BNB', precision: 7 },
|
|
62
|
+
'1.3.5589': { symbol: 'XBTSX.USDT', precision: 6 },
|
|
63
|
+
'1.3.5641': { symbol: 'HONEST.CNY', precision: 4 },
|
|
64
|
+
'1.3.5649': { symbol: 'HONEST.USD', precision: 4 },
|
|
65
|
+
'1.3.5650': { symbol: 'HONEST.BTC', precision: 8 },
|
|
66
|
+
'1.3.5659': { symbol: 'HONEST.ETH', precision: 6 },
|
|
67
|
+
'1.3.5870': { symbol: 'XBTSX.FIL', precision: 6 },
|
|
68
|
+
'1.3.5887': { symbol: 'XBTSX.RUB', precision: 4 },
|
|
69
|
+
'1.3.5902': { symbol: 'XBTSX.USDC', precision: 6 },
|
|
70
|
+
'1.3.6013': { symbol: 'XBTSX.HIVE', precision: 6 },
|
|
71
|
+
'1.3.6124': { symbol: 'XBTSX.AVAX', precision: 6 },
|
|
72
|
+
'1.3.6139': { symbol: 'XBTSX.XAUT', precision: 6 },
|
|
73
|
+
'1.3.6166': { symbol: 'XBTSX.MATIC', precision: 5 },
|
|
74
|
+
'1.3.6241': { symbol: 'XBTSX.ETC', precision: 7 },
|
|
75
|
+
'1.3.6268': { symbol: 'BTWTY.EOS', precision: 4 },
|
|
76
|
+
'1.3.6301': { symbol: 'HONEST.MONEY', precision: 8 },
|
|
77
|
+
'1.3.6304': { symbol: 'HONEST.ADA', precision: 8 },
|
|
78
|
+
'1.3.6305': { symbol: 'HONEST.DOT', precision: 8 },
|
|
79
|
+
'1.3.6309': { symbol: 'HONEST.ATOM', precision: 8 },
|
|
80
|
+
'1.3.6311': { symbol: 'HONEST.ALGO', precision: 8 },
|
|
81
|
+
'1.3.6312': { symbol: 'HONEST.FIL', precision: 8 },
|
|
82
|
+
'1.3.6313': { symbol: 'HONEST.EOS', precision: 8 },
|
|
83
|
+
'1.3.6315': { symbol: 'HONEST.EUR', precision: 4 },
|
|
84
|
+
'1.3.6316': { symbol: 'HONEST.GBP', precision: 4 },
|
|
85
|
+
'1.3.6317': { symbol: 'HONEST.JPY', precision: 4 },
|
|
86
|
+
'1.3.6444': { symbol: 'IOB.XLM', precision: 4 },
|
|
87
|
+
'1.3.6573': { symbol: 'XBTSX.DAI', precision: 6 },
|
|
88
|
+
'1.3.6620': { symbol: 'XBTSX.A', precision: 6 },
|
|
89
|
+
'1.3.6627': { symbol: 'XBTSX.LINK', precision: 6 },
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/** Precisions learned on-chain this run (populated by resolveAssetPrecisions). */
|
|
93
|
+
const resolvedPrecisions: Record<string, number> = {};
|
|
94
|
+
|
|
95
|
+
function assetSymbol(id: string): string {
|
|
96
|
+
return ASSETS[id]?.symbol ?? id;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function assetPrec(id: string): number | undefined {
|
|
100
|
+
return ASSETS[id]?.precision ?? resolvedPrecisions[id];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function toReal(amount: number, assetId: string): number {
|
|
104
|
+
const p = assetPrec(assetId);
|
|
105
|
+
if (p === undefined) return NaN;
|
|
106
|
+
return amount / Math.pow(10, p);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Collect all unique non-BTS asset IDs from fills, resolve unknown precisions
|
|
111
|
+
* from the blockchain, and populate the runtime cache.
|
|
112
|
+
*/
|
|
113
|
+
async function resolveAssetPrecisions(fills: FillRecord[]): Promise<void> {
|
|
114
|
+
const unknownIds = new Set<string>();
|
|
115
|
+
for (const f of fills) {
|
|
116
|
+
for (const id of [f.pays.asset_id, f.receives.asset_id, f.fee.asset_id]) {
|
|
117
|
+
if (id !== BTS_ID && !(id in ASSETS) && !(id in resolvedPrecisions)) {
|
|
118
|
+
unknownIds.add(id);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (unknownIds.size === 0) return;
|
|
123
|
+
|
|
124
|
+
const ids = [...unknownIds];
|
|
125
|
+
console.log(` Resolving ${ids.length} unknown asset(s) from blockchain...`);
|
|
126
|
+
try {
|
|
127
|
+
await withReadOnlyClient(async (client) => {
|
|
128
|
+
const assets = await client.db('get_assets', [ids]);
|
|
129
|
+
if (Array.isArray(assets)) {
|
|
130
|
+
for (const asset of assets) {
|
|
131
|
+
if (asset?.id && asset.precision != null) {
|
|
132
|
+
resolvedPrecisions[asset.id] = asset.precision;
|
|
133
|
+
console.log(` ${asset.id} → ${asset.symbol || '?'} (precision ${asset.precision})`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const missing = ids.filter(id => !(id in resolvedPrecisions));
|
|
138
|
+
if (missing.length > 0) {
|
|
139
|
+
console.warn(` [warn] ${missing.length} asset(s) not found on chain: ${missing.join(', ')}. Fills referencing them will be skipped.`);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
} catch (e: any) {
|
|
143
|
+
console.warn(` [warn] Asset resolution failed: ${e.message}. Fills with unknown assets will be skipped.`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function buildFillQuery(accountId: string, gte: string, lte: string, size: number) {
|
|
148
|
+
return {
|
|
149
|
+
size,
|
|
150
|
+
track_total_hits: false,
|
|
151
|
+
_source: [
|
|
152
|
+
'block_data.block_time',
|
|
153
|
+
'block_data.block_num',
|
|
154
|
+
'operation_id_num',
|
|
155
|
+
'operation_history.op_object.pays',
|
|
156
|
+
'operation_history.op_object.receives',
|
|
157
|
+
'operation_history.op_object.fee',
|
|
158
|
+
'operation_history.op_object.order_id',
|
|
159
|
+
'operation_history.op_object.account_id',
|
|
160
|
+
'operation_history.op_object.is_maker',
|
|
161
|
+
],
|
|
162
|
+
query: {
|
|
163
|
+
bool: {
|
|
164
|
+
filter: [
|
|
165
|
+
{ term: { operation_type: OP_FILL_ORDER } },
|
|
166
|
+
{ term: { 'operation_history.op_object.account_id.keyword': accountId } },
|
|
167
|
+
{ range: { 'block_data.block_time': { gte, lte } } },
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
sort: [
|
|
172
|
+
{ 'block_data.block_time': { order: 'asc' } },
|
|
173
|
+
{ operation_id_num: { order: 'asc' } },
|
|
174
|
+
],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Fetch every fill_order for an account in [gte, lte], paginated via search_after. */
|
|
179
|
+
async function fetchAllFills(config: any, accountId: string, gte: string, lte: string): Promise<FillRecord[]> {
|
|
180
|
+
const pageSize = 10000;
|
|
181
|
+
const fills: FillRecord[] = [];
|
|
182
|
+
let searchAfter: any[] | null = null;
|
|
183
|
+
const cfg = { ...BASE_CONFIG, timeout: 60000, ...config };
|
|
184
|
+
|
|
185
|
+
while (true) {
|
|
186
|
+
const query = buildFillQuery(accountId, gte, lte, pageSize);
|
|
187
|
+
if (searchAfter) (query as any).search_after = searchAfter;
|
|
188
|
+
|
|
189
|
+
const result: any = await kibanaSearch(cfg, query);
|
|
190
|
+
const hits = result?.hits?.hits ?? [];
|
|
191
|
+
if (!hits.length) break;
|
|
192
|
+
|
|
193
|
+
for (const hit of hits) {
|
|
194
|
+
const src = hit?._source;
|
|
195
|
+
const op = src?.operation_history?.op_object;
|
|
196
|
+
if (!op || !op.pays || !op.receives) continue;
|
|
197
|
+
|
|
198
|
+
fills.push({
|
|
199
|
+
time: src.block_data?.block_time ?? '',
|
|
200
|
+
blockNum: src.block_data?.block_num ?? 0,
|
|
201
|
+
opNum: Number(src.operation_id_num ?? 0),
|
|
202
|
+
orderId: op.order_id ?? '',
|
|
203
|
+
accountId: op.account_id ?? '',
|
|
204
|
+
pays: { amount: Number(op.pays.amount ?? 0), asset_id: op.pays.asset_id ?? '' },
|
|
205
|
+
receives: { amount: Number(op.receives.amount ?? 0), asset_id: op.receives.asset_id ?? '' },
|
|
206
|
+
fee: { amount: Number(op.fee?.amount ?? 0), asset_id: op.fee?.asset_id ?? '' },
|
|
207
|
+
isMaker: op.is_maker ?? false,
|
|
208
|
+
sort: hit.sort,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (hits.length < pageSize) break;
|
|
213
|
+
searchAfter = hits[hits.length - 1].sort;
|
|
214
|
+
if (!Array.isArray(searchAfter)) break;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return fills;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export {
|
|
221
|
+
BTS_ID,
|
|
222
|
+
OP_FILL_ORDER,
|
|
223
|
+
ASSETS,
|
|
224
|
+
resolvedPrecisions,
|
|
225
|
+
assetSymbol,
|
|
226
|
+
assetPrec,
|
|
227
|
+
toReal,
|
|
228
|
+
resolveAssetPrecisions,
|
|
229
|
+
buildFillQuery,
|
|
230
|
+
fetchAllFills,
|
|
231
|
+
AssetInfo,
|
|
232
|
+
AssetAmount,
|
|
233
|
+
FillRecord,
|
|
234
|
+
};
|