@raintree-technology/perps 0.1.0
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 +33 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/adapters/aevo.d.ts +64 -0
- package/dist/adapters/aevo.js +899 -0
- package/dist/adapters/certification.d.ts +33 -0
- package/dist/adapters/certification.js +99 -0
- package/dist/adapters/decibel/order-manager.d.ts +45 -0
- package/dist/adapters/decibel/order-manager.js +140 -0
- package/dist/adapters/decibel/rest-client.d.ts +176 -0
- package/dist/adapters/decibel/rest-client.js +155 -0
- package/dist/adapters/decibel/ws-feed.d.ts +28 -0
- package/dist/adapters/decibel/ws-feed.js +166 -0
- package/dist/adapters/decibel.d.ts +108 -0
- package/dist/adapters/decibel.js +1377 -0
- package/dist/adapters/hyperliquid.d.ts +63 -0
- package/dist/adapters/hyperliquid.js +797 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.js +12 -0
- package/dist/adapters/interface.d.ts +310 -0
- package/dist/adapters/interface.js +15 -0
- package/dist/adapters/orderly.d.ts +70 -0
- package/dist/adapters/orderly.js +936 -0
- package/dist/adapters/paradex.d.ts +69 -0
- package/dist/adapters/paradex.js +862 -0
- package/dist/adapters/utils.d.ts +17 -0
- package/dist/adapters/utils.js +122 -0
- package/dist/cli/command-metadata.d.ts +2 -0
- package/dist/cli/command-metadata.js +44 -0
- package/dist/cli/context.d.ts +14 -0
- package/dist/cli/context.js +59 -0
- package/dist/cli/experience.d.ts +48 -0
- package/dist/cli/experience.js +243 -0
- package/dist/cli/ink/app/AppShell.d.ts +12 -0
- package/dist/cli/ink/app/AppShell.js +32 -0
- package/dist/cli/ink/app/MetricStrip.d.ts +6 -0
- package/dist/cli/ink/app/MetricStrip.js +14 -0
- package/dist/cli/ink/app/Panel.d.ts +9 -0
- package/dist/cli/ink/app/Panel.js +7 -0
- package/dist/cli/ink/app/ascii.d.ts +2 -0
- package/dist/cli/ink/app/ascii.js +46 -0
- package/dist/cli/ink/app/index.d.ts +5 -0
- package/dist/cli/ink/app/index.js +4 -0
- package/dist/cli/ink/app/types.d.ts +15 -0
- package/dist/cli/ink/app/types.js +1 -0
- package/dist/cli/ink/components/PnL.d.ts +12 -0
- package/dist/cli/ink/components/PnL.js +23 -0
- package/dist/cli/ink/components/Spinner.d.ts +13 -0
- package/dist/cli/ink/components/Spinner.js +13 -0
- package/dist/cli/ink/components/Table.d.ts +14 -0
- package/dist/cli/ink/components/Table.js +42 -0
- package/dist/cli/ink/components/WatchHeader.d.ts +10 -0
- package/dist/cli/ink/components/WatchHeader.js +18 -0
- package/dist/cli/ink/components/index.d.ts +4 -0
- package/dist/cli/ink/components/index.js +4 -0
- package/dist/cli/ink/index.d.ts +4 -0
- package/dist/cli/ink/index.js +4 -0
- package/dist/cli/ink/render.d.ts +12 -0
- package/dist/cli/ink/render.js +21 -0
- package/dist/cli/ink/theme.d.ts +29 -0
- package/dist/cli/ink/theme.js +40 -0
- package/dist/cli/network-defaults.d.ts +10 -0
- package/dist/cli/network-defaults.js +35 -0
- package/dist/cli/output.d.ts +11 -0
- package/dist/cli/output.js +115 -0
- package/dist/cli/program.d.ts +18 -0
- package/dist/cli/program.js +164 -0
- package/dist/cli/watch.d.ts +19 -0
- package/dist/cli/watch.js +35 -0
- package/dist/client/index.d.ts +55 -0
- package/dist/client/index.js +157 -0
- package/dist/commands/account/add.d.ts +2 -0
- package/dist/commands/account/add.js +510 -0
- package/dist/commands/account/balances-simple.d.ts +5 -0
- package/dist/commands/account/balances-simple.js +63 -0
- package/dist/commands/account/index.d.ts +2 -0
- package/dist/commands/account/index.js +17 -0
- package/dist/commands/account/ls.d.ts +2 -0
- package/dist/commands/account/ls.js +95 -0
- package/dist/commands/account/positions-simple.d.ts +5 -0
- package/dist/commands/account/positions-simple.js +77 -0
- package/dist/commands/account/remove.d.ts +2 -0
- package/dist/commands/account/remove.js +47 -0
- package/dist/commands/account/set-default.d.ts +2 -0
- package/dist/commands/account/set-default.js +47 -0
- package/dist/commands/agent/index.d.ts +2 -0
- package/dist/commands/agent/index.js +126 -0
- package/dist/commands/arb/alert.d.ts +6 -0
- package/dist/commands/arb/alert.js +88 -0
- package/dist/commands/arb/basis-execute.d.ts +6 -0
- package/dist/commands/arb/basis-execute.js +332 -0
- package/dist/commands/arb/basis.d.ts +6 -0
- package/dist/commands/arb/basis.js +181 -0
- package/dist/commands/arb/compare.d.ts +6 -0
- package/dist/commands/arb/compare.js +216 -0
- package/dist/commands/arb/execute.d.ts +6 -0
- package/dist/commands/arb/execute.js +467 -0
- package/dist/commands/arb/funding.d.ts +6 -0
- package/dist/commands/arb/funding.js +201 -0
- package/dist/commands/arb/history.d.ts +6 -0
- package/dist/commands/arb/history.js +153 -0
- package/dist/commands/arb/index.d.ts +6 -0
- package/dist/commands/arb/index.js +29 -0
- package/dist/commands/arb/positions.d.ts +6 -0
- package/dist/commands/arb/positions.js +158 -0
- package/dist/commands/arb/spread.d.ts +6 -0
- package/dist/commands/arb/spread.js +253 -0
- package/dist/commands/arb/track.d.ts +6 -0
- package/dist/commands/arb/track.js +259 -0
- package/dist/commands/asset/book-simple.d.ts +5 -0
- package/dist/commands/asset/book-simple.js +77 -0
- package/dist/commands/asset/index.d.ts +2 -0
- package/dist/commands/asset/index.js +5 -0
- package/dist/commands/completion.d.ts +2 -0
- package/dist/commands/completion.js +161 -0
- package/dist/commands/config/index.d.ts +5 -0
- package/dist/commands/config/index.js +109 -0
- package/dist/commands/data/index.d.ts +31 -0
- package/dist/commands/data/index.js +1466 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +201 -0
- package/dist/commands/exchange/index.d.ts +2 -0
- package/dist/commands/exchange/index.js +107 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +48 -0
- package/dist/commands/markets/index.d.ts +2 -0
- package/dist/commands/markets/index.js +5 -0
- package/dist/commands/markets/ls-simple.d.ts +7 -0
- package/dist/commands/markets/ls-simple.js +277 -0
- package/dist/commands/operator/index.d.ts +2 -0
- package/dist/commands/operator/index.js +146 -0
- package/dist/commands/order/cancel-simple.d.ts +5 -0
- package/dist/commands/order/cancel-simple.js +104 -0
- package/dist/commands/order/index.d.ts +2 -0
- package/dist/commands/order/index.js +13 -0
- package/dist/commands/order/limit-simple.d.ts +5 -0
- package/dist/commands/order/limit-simple.js +195 -0
- package/dist/commands/order/market-simple.d.ts +5 -0
- package/dist/commands/order/market-simple.js +190 -0
- package/dist/commands/order/shared.d.ts +17 -0
- package/dist/commands/order/shared.js +51 -0
- package/dist/commands/order/trigger-simple.d.ts +5 -0
- package/dist/commands/order/trigger-simple.js +246 -0
- package/dist/commands/referral/index.d.ts +2 -0
- package/dist/commands/referral/index.js +7 -0
- package/dist/commands/referral/set.d.ts +2 -0
- package/dist/commands/referral/set.js +26 -0
- package/dist/commands/referral/status.d.ts +2 -0
- package/dist/commands/referral/status.js +31 -0
- package/dist/commands/replay/index.d.ts +2 -0
- package/dist/commands/replay/index.js +152 -0
- package/dist/commands/risk/analytics.d.ts +2 -0
- package/dist/commands/risk/analytics.js +64 -0
- package/dist/commands/risk/audit.d.ts +2 -0
- package/dist/commands/risk/audit.js +52 -0
- package/dist/commands/risk/index.d.ts +2 -0
- package/dist/commands/risk/index.js +9 -0
- package/dist/commands/risk/rules.d.ts +2 -0
- package/dist/commands/risk/rules.js +102 -0
- package/dist/commands/server.d.ts +2 -0
- package/dist/commands/server.js +208 -0
- package/dist/commands/setup/index.d.ts +2 -0
- package/dist/commands/setup/index.js +478 -0
- package/dist/commands/signal/index.d.ts +2 -0
- package/dist/commands/signal/index.js +129 -0
- package/dist/commands/state/index.d.ts +2 -0
- package/dist/commands/state/index.js +5 -0
- package/dist/commands/state/show.d.ts +2 -0
- package/dist/commands/state/show.js +105 -0
- package/dist/commands/strategy/index.d.ts +4 -0
- package/dist/commands/strategy/index.js +73 -0
- package/dist/commands/traces/index.d.ts +2 -0
- package/dist/commands/traces/index.js +76 -0
- package/dist/commands/ui/demo.d.ts +9 -0
- package/dist/commands/ui/demo.js +195 -0
- package/dist/commands/ui/index.d.ts +2 -0
- package/dist/commands/ui/index.js +7 -0
- package/dist/commands/ui/terminal.d.ts +2 -0
- package/dist/commands/ui/terminal.js +255 -0
- package/dist/commands/upgrade.d.ts +2 -0
- package/dist/commands/upgrade.js +98 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/lib/agent/audit.d.ts +12 -0
- package/dist/lib/agent/audit.js +13 -0
- package/dist/lib/agent/gateway.d.ts +13 -0
- package/dist/lib/agent/gateway.js +598 -0
- package/dist/lib/agent/metrics.d.ts +33 -0
- package/dist/lib/agent/metrics.js +175 -0
- package/dist/lib/agent/signature.d.ts +8 -0
- package/dist/lib/agent/signature.js +28 -0
- package/dist/lib/agent/tools.d.ts +28 -0
- package/dist/lib/agent/tools.js +453 -0
- package/dist/lib/agent/x402.d.ts +23 -0
- package/dist/lib/agent/x402.js +62 -0
- package/dist/lib/api-wallet.d.ts +69 -0
- package/dist/lib/api-wallet.js +101 -0
- package/dist/lib/balance-watcher.d.ts +25 -0
- package/dist/lib/balance-watcher.js +83 -0
- package/dist/lib/book-watcher.d.ts +25 -0
- package/dist/lib/book-watcher.js +48 -0
- package/dist/lib/config.d.ts +88 -0
- package/dist/lib/config.js +427 -0
- package/dist/lib/constants.d.ts +50 -0
- package/dist/lib/constants.js +84 -0
- package/dist/lib/contracts.d.ts +7 -0
- package/dist/lib/contracts.js +8 -0
- package/dist/lib/credential-vault.d.ts +22 -0
- package/dist/lib/credential-vault.js +109 -0
- package/dist/lib/db/accounts.d.ts +83 -0
- package/dist/lib/db/accounts.js +203 -0
- package/dist/lib/db/funding-history.d.ts +69 -0
- package/dist/lib/db/funding-history.js +183 -0
- package/dist/lib/db/index.d.ts +11 -0
- package/dist/lib/db/index.js +272 -0
- package/dist/lib/events/bus.d.ts +10 -0
- package/dist/lib/events/bus.js +17 -0
- package/dist/lib/events/types.d.ts +51 -0
- package/dist/lib/events/types.js +1 -0
- package/dist/lib/exchange.d.ts +30 -0
- package/dist/lib/exchange.js +84 -0
- package/dist/lib/execution/journal.d.ts +25 -0
- package/dist/lib/execution/journal.js +158 -0
- package/dist/lib/execution/safety.d.ts +34 -0
- package/dist/lib/execution/safety.js +197 -0
- package/dist/lib/exit-codes.d.ts +18 -0
- package/dist/lib/exit-codes.js +60 -0
- package/dist/lib/fetch.d.ts +18 -0
- package/dist/lib/fetch.js +66 -0
- package/dist/lib/fs-security.d.ts +10 -0
- package/dist/lib/fs-security.js +26 -0
- package/dist/lib/funding-tracker.d.ts +40 -0
- package/dist/lib/funding-tracker.js +118 -0
- package/dist/lib/logger.d.ts +27 -0
- package/dist/lib/logger.js +82 -0
- package/dist/lib/network-model.d.ts +13 -0
- package/dist/lib/network-model.js +30 -0
- package/dist/lib/onboarding.d.ts +133 -0
- package/dist/lib/onboarding.js +1459 -0
- package/dist/lib/operator-state.d.ts +25 -0
- package/dist/lib/operator-state.js +82 -0
- package/dist/lib/orders-watcher.d.ts +24 -0
- package/dist/lib/orders-watcher.js +74 -0
- package/dist/lib/paths.d.ts +20 -0
- package/dist/lib/paths.js +23 -0
- package/dist/lib/portfolio-watcher.d.ts +33 -0
- package/dist/lib/portfolio-watcher.js +95 -0
- package/dist/lib/position-watcher.d.ts +16 -0
- package/dist/lib/position-watcher.js +44 -0
- package/dist/lib/price-watcher.d.ts +15 -0
- package/dist/lib/price-watcher.js +84 -0
- package/dist/lib/prompts.d.ts +32 -0
- package/dist/lib/prompts.js +105 -0
- package/dist/lib/rate-limit.d.ts +32 -0
- package/dist/lib/rate-limit.js +88 -0
- package/dist/lib/risk/analytics.d.ts +39 -0
- package/dist/lib/risk/analytics.js +98 -0
- package/dist/lib/risk/drawdown.d.ts +18 -0
- package/dist/lib/risk/drawdown.js +49 -0
- package/dist/lib/risk/evaluation-log.d.ts +29 -0
- package/dist/lib/risk/evaluation-log.js +61 -0
- package/dist/lib/risk/index.d.ts +4 -0
- package/dist/lib/risk/index.js +4 -0
- package/dist/lib/risk/limits.d.ts +23 -0
- package/dist/lib/risk/limits.js +27 -0
- package/dist/lib/risk/manager.d.ts +32 -0
- package/dist/lib/risk/manager.js +85 -0
- package/dist/lib/risk/policy-middleware.d.ts +33 -0
- package/dist/lib/risk/policy-middleware.js +267 -0
- package/dist/lib/risk/position-sizer.d.ts +9 -0
- package/dist/lib/risk/position-sizer.js +14 -0
- package/dist/lib/risk/rules-store.d.ts +16 -0
- package/dist/lib/risk/rules-store.js +47 -0
- package/dist/lib/schema.d.ts +254 -0
- package/dist/lib/schema.js +199 -0
- package/dist/lib/secrets.d.ts +3 -0
- package/dist/lib/secrets.js +62 -0
- package/dist/lib/settings.d.ts +24 -0
- package/dist/lib/settings.js +86 -0
- package/dist/lib/signals.d.ts +73 -0
- package/dist/lib/signals.js +136 -0
- package/dist/lib/stable-stringify.d.ts +6 -0
- package/dist/lib/stable-stringify.js +17 -0
- package/dist/lib/state-context.d.ts +44 -0
- package/dist/lib/state-context.js +133 -0
- package/dist/lib/strategy/basis-trade.d.ts +2 -0
- package/dist/lib/strategy/basis-trade.js +24 -0
- package/dist/lib/strategy/funding-arb.d.ts +2 -0
- package/dist/lib/strategy/funding-arb.js +23 -0
- package/dist/lib/strategy/interface.d.ts +23 -0
- package/dist/lib/strategy/interface.js +1 -0
- package/dist/lib/strategy/registry.d.ts +4 -0
- package/dist/lib/strategy/registry.js +10 -0
- package/dist/lib/telemetry.d.ts +25 -0
- package/dist/lib/telemetry.js +101 -0
- package/dist/lib/trace-queries.d.ts +20 -0
- package/dist/lib/trace-queries.js +133 -0
- package/dist/lib/trace.d.ts +1 -0
- package/dist/lib/trace.js +4 -0
- package/dist/lib/trade-reputation.d.ts +6 -0
- package/dist/lib/trade-reputation.js +99 -0
- package/dist/lib/ui-tokens.d.ts +21 -0
- package/dist/lib/ui-tokens.js +26 -0
- package/dist/lib/validate.d.ts +39 -0
- package/dist/lib/validate.js +108 -0
- package/dist/lib/validation.d.ts +9 -0
- package/dist/lib/validation.js +64 -0
- package/dist/server/cache.d.ts +38 -0
- package/dist/server/cache.js +56 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +89 -0
- package/dist/server/ipc.d.ts +18 -0
- package/dist/server/ipc.js +159 -0
- package/dist/server/subscriptions.d.ts +18 -0
- package/dist/server/subscriptions.js +114 -0
- package/package.json +124 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation Utilities
|
|
3
|
+
* Validates and sanitizes CLI inputs
|
|
4
|
+
*/
|
|
5
|
+
export declare class ValidationError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Validate and parse a positive number
|
|
10
|
+
*/
|
|
11
|
+
export declare function parsePositiveNumber(value: string | undefined, name: string, defaultValue?: number): number;
|
|
12
|
+
/**
|
|
13
|
+
* Validate and parse a positive integer
|
|
14
|
+
*/
|
|
15
|
+
export declare function parsePositiveInt(value: string | undefined, name: string, defaultValue?: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* Validate and parse a number within a range
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseNumberInRange(value: string | undefined, name: string, min: number, max: number, defaultValue?: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* Validate asset symbol
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateAsset(asset: string | undefined, defaultAsset?: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Validate market symbol
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateMarket(market: string | undefined, defaultMarket?: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Parse comma-separated list of assets
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseAssetList(value: string | undefined, defaultAssets: readonly string[]): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Validate exchange ID
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateExchange(exchangeId: string, validExchanges: string[]): string;
|
|
36
|
+
/**
|
|
37
|
+
* Validate USD size
|
|
38
|
+
*/
|
|
39
|
+
export declare function validateSize(value: string | undefined, defaultSize?: number): number;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input Validation Utilities
|
|
3
|
+
* Validates and sanitizes CLI inputs
|
|
4
|
+
*/
|
|
5
|
+
export class ValidationError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "ValidationError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validate and parse a positive number
|
|
13
|
+
*/
|
|
14
|
+
export function parsePositiveNumber(value, name, defaultValue) {
|
|
15
|
+
if (value === undefined || value === "") {
|
|
16
|
+
if (defaultValue !== undefined)
|
|
17
|
+
return defaultValue;
|
|
18
|
+
throw new ValidationError(`${name} is required`);
|
|
19
|
+
}
|
|
20
|
+
const num = parseFloat(value);
|
|
21
|
+
if (isNaN(num)) {
|
|
22
|
+
throw new ValidationError(`${name} must be a valid number, got: ${value}`);
|
|
23
|
+
}
|
|
24
|
+
if (num <= 0) {
|
|
25
|
+
throw new ValidationError(`${name} must be positive, got: ${num}`);
|
|
26
|
+
}
|
|
27
|
+
return num;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate and parse a positive integer
|
|
31
|
+
*/
|
|
32
|
+
export function parsePositiveInt(value, name, defaultValue) {
|
|
33
|
+
const num = parsePositiveNumber(value, name, defaultValue);
|
|
34
|
+
if (!Number.isInteger(num)) {
|
|
35
|
+
throw new ValidationError(`${name} must be an integer, got: ${num}`);
|
|
36
|
+
}
|
|
37
|
+
return num;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validate and parse a number within a range
|
|
41
|
+
*/
|
|
42
|
+
export function parseNumberInRange(value, name, min, max, defaultValue) {
|
|
43
|
+
const num = parsePositiveNumber(value, name, defaultValue);
|
|
44
|
+
if (num < min || num > max) {
|
|
45
|
+
throw new ValidationError(`${name} must be between ${min} and ${max}, got: ${num}`);
|
|
46
|
+
}
|
|
47
|
+
return num;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Validate asset symbol
|
|
51
|
+
*/
|
|
52
|
+
export function validateAsset(asset, defaultAsset = "BTC") {
|
|
53
|
+
if (!asset)
|
|
54
|
+
return defaultAsset;
|
|
55
|
+
const normalized = asset.toUpperCase().trim();
|
|
56
|
+
// Basic validation: 1-10 alphanumeric characters
|
|
57
|
+
if (!/^[A-Z0-9]{1,10}$/.test(normalized)) {
|
|
58
|
+
throw new ValidationError(`Invalid asset symbol: ${asset}`);
|
|
59
|
+
}
|
|
60
|
+
return normalized;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validate market symbol
|
|
64
|
+
*/
|
|
65
|
+
export function validateMarket(market, defaultMarket = "BTC-PERP") {
|
|
66
|
+
if (!market)
|
|
67
|
+
return defaultMarket;
|
|
68
|
+
const normalized = market.toUpperCase().trim();
|
|
69
|
+
// Format: ASSET-PERP or ASSET-USD-PERP
|
|
70
|
+
if (!/^[A-Z0-9]{1,10}(-USD)?-PERP$/.test(normalized)) {
|
|
71
|
+
throw new ValidationError(`Invalid market symbol: ${market}. Expected format: ASSET-PERP`);
|
|
72
|
+
}
|
|
73
|
+
return normalized;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Parse comma-separated list of assets
|
|
77
|
+
*/
|
|
78
|
+
export function parseAssetList(value, defaultAssets) {
|
|
79
|
+
if (!value)
|
|
80
|
+
return [...defaultAssets];
|
|
81
|
+
return value
|
|
82
|
+
.split(",")
|
|
83
|
+
.map(a => validateAsset(a.trim()))
|
|
84
|
+
.filter((a, i, arr) => arr.indexOf(a) === i); // dedupe
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Validate exchange ID
|
|
88
|
+
*/
|
|
89
|
+
export function validateExchange(exchangeId, validExchanges) {
|
|
90
|
+
const normalized = exchangeId.toLowerCase().trim();
|
|
91
|
+
if (!validExchanges.includes(normalized)) {
|
|
92
|
+
throw new ValidationError(`Invalid exchange: ${exchangeId}. Valid options: ${validExchanges.join(", ")}`);
|
|
93
|
+
}
|
|
94
|
+
return normalized;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Validate USD size
|
|
98
|
+
*/
|
|
99
|
+
export function validateSize(value, defaultSize = 1000) {
|
|
100
|
+
const size = parsePositiveNumber(value, "size", defaultSize);
|
|
101
|
+
if (size < 10) {
|
|
102
|
+
throw new ValidationError("Position size must be at least $10");
|
|
103
|
+
}
|
|
104
|
+
if (size > 10_000_000) {
|
|
105
|
+
throw new ValidationError("Position size cannot exceed $10M");
|
|
106
|
+
}
|
|
107
|
+
return size;
|
|
108
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Address, Hex } from "viem";
|
|
2
|
+
export declare function validateAddress(value: string): Address;
|
|
3
|
+
export declare function validateAptosLikeAddress(value: string): string;
|
|
4
|
+
export declare function validateAddressForExchange(value: string, exchangeId: string): string;
|
|
5
|
+
export declare function validatePrivateKey(value: string): Hex;
|
|
6
|
+
export declare function validatePositiveNumber(value: string, name: string): number;
|
|
7
|
+
export declare function validatePositiveInteger(value: string, name: string): number;
|
|
8
|
+
export declare function validateSide(value: string): "buy" | "sell";
|
|
9
|
+
export declare function validateTif(value: string): "Gtc" | "Ioc" | "Alo";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function validateAddress(value) {
|
|
2
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(value)) {
|
|
3
|
+
throw new Error(`Invalid address: ${value}`);
|
|
4
|
+
}
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
export function validateAptosLikeAddress(value) {
|
|
8
|
+
if (!/^0x[a-fA-F0-9]{1,64}$/.test(value)) {
|
|
9
|
+
throw new Error(`Invalid address: ${value}`);
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
export function validateAddressForExchange(value, exchangeId) {
|
|
14
|
+
const normalized = exchangeId.trim().toLowerCase();
|
|
15
|
+
if (normalized === "decibel" || normalized === "paradex") {
|
|
16
|
+
return validateAptosLikeAddress(value);
|
|
17
|
+
}
|
|
18
|
+
if (normalized === "orderly") {
|
|
19
|
+
if (!value.trim()) {
|
|
20
|
+
throw new Error("Invalid account identifier: value cannot be empty");
|
|
21
|
+
}
|
|
22
|
+
return value.trim();
|
|
23
|
+
}
|
|
24
|
+
return validateAddress(value);
|
|
25
|
+
}
|
|
26
|
+
export function validatePrivateKey(value) {
|
|
27
|
+
if (!/^0x[a-fA-F0-9]{64}$/.test(value)) {
|
|
28
|
+
throw new Error("Invalid private key format");
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
export function validatePositiveNumber(value, name) {
|
|
33
|
+
const num = parseFloat(value);
|
|
34
|
+
if (isNaN(num) || num <= 0) {
|
|
35
|
+
throw new Error(`${name} must be a positive number`);
|
|
36
|
+
}
|
|
37
|
+
return num;
|
|
38
|
+
}
|
|
39
|
+
export function validatePositiveInteger(value, name) {
|
|
40
|
+
const num = parseInt(value, 10);
|
|
41
|
+
if (isNaN(num) || num <= 0) {
|
|
42
|
+
throw new Error(`${name} must be a positive integer`);
|
|
43
|
+
}
|
|
44
|
+
return num;
|
|
45
|
+
}
|
|
46
|
+
export function validateSide(value) {
|
|
47
|
+
const lower = value.toLowerCase();
|
|
48
|
+
if (lower !== "buy" && lower !== "sell") {
|
|
49
|
+
throw new Error('Side must be "buy" or "sell"');
|
|
50
|
+
}
|
|
51
|
+
return lower;
|
|
52
|
+
}
|
|
53
|
+
export function validateTif(value) {
|
|
54
|
+
const mapping = {
|
|
55
|
+
gtc: "Gtc",
|
|
56
|
+
ioc: "Ioc",
|
|
57
|
+
alo: "Alo",
|
|
58
|
+
};
|
|
59
|
+
const result = mapping[value.toLowerCase()];
|
|
60
|
+
if (!result) {
|
|
61
|
+
throw new Error('Time-in-force must be "Gtc", "Ioc", or "Alo"');
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AllPerpMetasResponse, SpotMetaResponse } from "@nktkas/hyperliquid";
|
|
2
|
+
import { AllDexsAssetCtxsEvent, SpotAssetCtxsEvent } from "@nktkas/hyperliquid/api/subscription";
|
|
3
|
+
export interface CacheEntry<T> {
|
|
4
|
+
data: T;
|
|
5
|
+
updatedAt: number;
|
|
6
|
+
}
|
|
7
|
+
export interface AllMidsData {
|
|
8
|
+
[coin: string]: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class ServerCache {
|
|
11
|
+
private allMids;
|
|
12
|
+
private allDexsAssetCtxs;
|
|
13
|
+
private allPerpMetas;
|
|
14
|
+
private spotMeta;
|
|
15
|
+
private spotAssetCtxs;
|
|
16
|
+
setAllMids(data: AllMidsData): void;
|
|
17
|
+
setAllDexsAssetCtxs(data: AllDexsAssetCtxsEvent): void;
|
|
18
|
+
setAllPerpMetas(data: AllPerpMetasResponse): void;
|
|
19
|
+
setSpotMeta(data: SpotMetaResponse): void;
|
|
20
|
+
setSpotAssetCtxs(data: SpotAssetCtxsEvent): void;
|
|
21
|
+
getAllMids(): CacheEntry<AllMidsData> | null;
|
|
22
|
+
getAllDexsAssetCtxs(): CacheEntry<AllDexsAssetCtxsEvent> | null;
|
|
23
|
+
getAllPerpMetas(): CacheEntry<AllPerpMetasResponse> | null;
|
|
24
|
+
getSpotMeta(): CacheEntry<SpotMetaResponse> | null;
|
|
25
|
+
getSpotAssetCtxs(): CacheEntry<SpotAssetCtxsEvent> | null;
|
|
26
|
+
getStatus(): {
|
|
27
|
+
hasMids: boolean;
|
|
28
|
+
hasAssetCtxs: boolean;
|
|
29
|
+
hasPerpMetas: boolean;
|
|
30
|
+
hasSpotMeta: boolean;
|
|
31
|
+
hasSpotAssetCtxs: boolean;
|
|
32
|
+
midsAge?: number;
|
|
33
|
+
assetCtxsAge?: number;
|
|
34
|
+
perpMetasAge?: number;
|
|
35
|
+
spotMetaAge?: number;
|
|
36
|
+
spotAssetCtxsAge?: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// In-memory cache for real-time data from WebSocket subscriptions
|
|
2
|
+
export class ServerCache {
|
|
3
|
+
allMids = null;
|
|
4
|
+
allDexsAssetCtxs = null;
|
|
5
|
+
allPerpMetas = null;
|
|
6
|
+
spotMeta = null;
|
|
7
|
+
spotAssetCtxs = null;
|
|
8
|
+
// Update methods - called from subscription handlers
|
|
9
|
+
setAllMids(data) {
|
|
10
|
+
this.allMids = { data, updatedAt: Date.now() };
|
|
11
|
+
}
|
|
12
|
+
setAllDexsAssetCtxs(data) {
|
|
13
|
+
this.allDexsAssetCtxs = { data, updatedAt: Date.now() };
|
|
14
|
+
}
|
|
15
|
+
setAllPerpMetas(data) {
|
|
16
|
+
this.allPerpMetas = { data, updatedAt: Date.now() };
|
|
17
|
+
}
|
|
18
|
+
setSpotMeta(data) {
|
|
19
|
+
this.spotMeta = { data, updatedAt: Date.now() };
|
|
20
|
+
}
|
|
21
|
+
setSpotAssetCtxs(data) {
|
|
22
|
+
this.spotAssetCtxs = { data, updatedAt: Date.now() };
|
|
23
|
+
}
|
|
24
|
+
// Get methods - return data with cache timestamp
|
|
25
|
+
getAllMids() {
|
|
26
|
+
return this.allMids;
|
|
27
|
+
}
|
|
28
|
+
getAllDexsAssetCtxs() {
|
|
29
|
+
return this.allDexsAssetCtxs;
|
|
30
|
+
}
|
|
31
|
+
getAllPerpMetas() {
|
|
32
|
+
return this.allPerpMetas;
|
|
33
|
+
}
|
|
34
|
+
getSpotMeta() {
|
|
35
|
+
return this.spotMeta;
|
|
36
|
+
}
|
|
37
|
+
getSpotAssetCtxs() {
|
|
38
|
+
return this.spotAssetCtxs;
|
|
39
|
+
}
|
|
40
|
+
// Get status info
|
|
41
|
+
getStatus() {
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
return {
|
|
44
|
+
hasMids: this.allMids !== null,
|
|
45
|
+
hasAssetCtxs: this.allDexsAssetCtxs !== null,
|
|
46
|
+
hasPerpMetas: this.allPerpMetas !== null,
|
|
47
|
+
hasSpotMeta: this.spotMeta !== null,
|
|
48
|
+
hasSpotAssetCtxs: this.spotAssetCtxs !== null,
|
|
49
|
+
midsAge: this.allMids ? now - this.allMids.updatedAt : undefined,
|
|
50
|
+
assetCtxsAge: this.allDexsAssetCtxs ? now - this.allDexsAssetCtxs.updatedAt : undefined,
|
|
51
|
+
perpMetasAge: this.allPerpMetas ? now - this.allPerpMetas.updatedAt : undefined,
|
|
52
|
+
spotMetaAge: this.spotMeta ? now - this.spotMeta.updatedAt : undefined,
|
|
53
|
+
spotAssetCtxsAge: this.spotAssetCtxs ? now - this.spotAssetCtxs.updatedAt : undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { writeFileSync, appendFileSync, unlinkSync, existsSync } from "node:fs";
|
|
3
|
+
import { HL_DIR, SERVER_PID_PATH, SERVER_LOG_PATH, SERVER_CONFIG_PATH, SERVER_SOCKET_PATH, } from "../lib/paths.js";
|
|
4
|
+
import { ServerCache } from "./cache.js";
|
|
5
|
+
import { SubscriptionManager } from "./subscriptions.js";
|
|
6
|
+
import { IPCServer } from "./ipc.js";
|
|
7
|
+
import { ensurePrivateDir, hardenPrivateFile, PRIVATE_FILE_MODE, } from "../lib/fs-security.js";
|
|
8
|
+
// Parse command line args
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
const isTestnet = args.includes("--testnet");
|
|
11
|
+
// Ensure runtime directory exists and remains owner-only.
|
|
12
|
+
ensurePrivateDir(HL_DIR);
|
|
13
|
+
// Logging
|
|
14
|
+
function log(msg) {
|
|
15
|
+
const timestamp = new Date().toISOString();
|
|
16
|
+
const line = `[${timestamp}] ${msg}\n`;
|
|
17
|
+
appendFileSync(SERVER_LOG_PATH, line);
|
|
18
|
+
hardenPrivateFile(SERVER_LOG_PATH);
|
|
19
|
+
}
|
|
20
|
+
// Initialize
|
|
21
|
+
const startedAt = Date.now();
|
|
22
|
+
log(`Starting server (testnet: ${isTestnet}, pid: ${process.pid})`);
|
|
23
|
+
// Write PID file
|
|
24
|
+
writeFileSync(SERVER_PID_PATH, String(process.pid), { mode: PRIVATE_FILE_MODE });
|
|
25
|
+
hardenPrivateFile(SERVER_PID_PATH);
|
|
26
|
+
// Write config file
|
|
27
|
+
const config = { testnet: isTestnet, startedAt };
|
|
28
|
+
writeFileSync(SERVER_CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
29
|
+
hardenPrivateFile(SERVER_CONFIG_PATH);
|
|
30
|
+
// Create cache and managers
|
|
31
|
+
const cache = new ServerCache();
|
|
32
|
+
const subscriptions = new SubscriptionManager(cache, isTestnet, log);
|
|
33
|
+
let ipcServer = null;
|
|
34
|
+
// Graceful shutdown
|
|
35
|
+
async function shutdown(reason) {
|
|
36
|
+
log(`Shutting down: ${reason}`);
|
|
37
|
+
try {
|
|
38
|
+
// Stop IPC server first
|
|
39
|
+
if (ipcServer) {
|
|
40
|
+
await ipcServer.stop();
|
|
41
|
+
}
|
|
42
|
+
// Stop subscriptions
|
|
43
|
+
await subscriptions.stop();
|
|
44
|
+
// Clean up files
|
|
45
|
+
if (existsSync(SERVER_PID_PATH)) {
|
|
46
|
+
unlinkSync(SERVER_PID_PATH);
|
|
47
|
+
}
|
|
48
|
+
if (existsSync(SERVER_SOCKET_PATH)) {
|
|
49
|
+
unlinkSync(SERVER_SOCKET_PATH);
|
|
50
|
+
}
|
|
51
|
+
if (existsSync(SERVER_CONFIG_PATH)) {
|
|
52
|
+
unlinkSync(SERVER_CONFIG_PATH);
|
|
53
|
+
}
|
|
54
|
+
log("Shutdown complete");
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
log(`Shutdown error: ${err}`);
|
|
58
|
+
}
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
// Signal handlers
|
|
62
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
63
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
64
|
+
process.on("uncaughtException", (err) => {
|
|
65
|
+
log(`Uncaught exception: ${err.message}`);
|
|
66
|
+
shutdown("uncaught exception").catch(() => process.exit(1));
|
|
67
|
+
});
|
|
68
|
+
process.on("unhandledRejection", (reason) => {
|
|
69
|
+
log(`Unhandled rejection: ${reason}`);
|
|
70
|
+
shutdown("unhandled rejection").catch(() => process.exit(1));
|
|
71
|
+
});
|
|
72
|
+
// Start server
|
|
73
|
+
async function start() {
|
|
74
|
+
try {
|
|
75
|
+
// Start WebSocket subscriptions
|
|
76
|
+
await subscriptions.start();
|
|
77
|
+
// Start IPC server
|
|
78
|
+
ipcServer = new IPCServer(cache, subscriptions, isTestnet, startedAt, log, () => {
|
|
79
|
+
shutdown("shutdown request");
|
|
80
|
+
});
|
|
81
|
+
await ipcServer.start();
|
|
82
|
+
log("Server started successfully");
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
log(`Failed to start server: ${err}`);
|
|
86
|
+
await shutdown("startup error");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
start();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ServerCache } from "./cache.js";
|
|
2
|
+
import type { SubscriptionManager } from "./subscriptions.js";
|
|
3
|
+
export declare class IPCServer {
|
|
4
|
+
private server;
|
|
5
|
+
private cache;
|
|
6
|
+
private subscriptions;
|
|
7
|
+
private isTestnet;
|
|
8
|
+
private startedAt;
|
|
9
|
+
private log;
|
|
10
|
+
private onShutdown;
|
|
11
|
+
constructor(cache: ServerCache, subscriptions: SubscriptionManager, isTestnet: boolean, startedAt: number, log: (msg: string) => void, onShutdown: () => void);
|
|
12
|
+
start(): Promise<void>;
|
|
13
|
+
private handleConnection;
|
|
14
|
+
private handleMessage;
|
|
15
|
+
private handleRequest;
|
|
16
|
+
private sendResponse;
|
|
17
|
+
stop(): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { createServer } from "node:net";
|
|
2
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
3
|
+
import { SERVER_SOCKET_PATH } from "../lib/paths.js";
|
|
4
|
+
export class IPCServer {
|
|
5
|
+
server = null;
|
|
6
|
+
cache;
|
|
7
|
+
subscriptions;
|
|
8
|
+
isTestnet;
|
|
9
|
+
startedAt;
|
|
10
|
+
log;
|
|
11
|
+
onShutdown;
|
|
12
|
+
constructor(cache, subscriptions, isTestnet, startedAt, log, onShutdown) {
|
|
13
|
+
this.cache = cache;
|
|
14
|
+
this.subscriptions = subscriptions;
|
|
15
|
+
this.isTestnet = isTestnet;
|
|
16
|
+
this.startedAt = startedAt;
|
|
17
|
+
this.log = log;
|
|
18
|
+
this.onShutdown = onShutdown;
|
|
19
|
+
}
|
|
20
|
+
async start() {
|
|
21
|
+
// Remove existing socket file if it exists
|
|
22
|
+
if (existsSync(SERVER_SOCKET_PATH)) {
|
|
23
|
+
unlinkSync(SERVER_SOCKET_PATH);
|
|
24
|
+
}
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
this.server = createServer((socket) => {
|
|
27
|
+
this.handleConnection(socket);
|
|
28
|
+
});
|
|
29
|
+
this.server.on("error", (err) => {
|
|
30
|
+
this.log(`IPC server error: ${err.message}`);
|
|
31
|
+
reject(err);
|
|
32
|
+
});
|
|
33
|
+
this.server.listen(SERVER_SOCKET_PATH, () => {
|
|
34
|
+
this.log(`IPC server listening on ${SERVER_SOCKET_PATH}`);
|
|
35
|
+
resolve();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
handleConnection(socket) {
|
|
40
|
+
let buffer = "";
|
|
41
|
+
socket.on("data", (data) => {
|
|
42
|
+
buffer += data.toString();
|
|
43
|
+
// Process complete messages (newline-delimited)
|
|
44
|
+
const lines = buffer.split("\n");
|
|
45
|
+
buffer = lines.pop() || "";
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
if (line.trim()) {
|
|
48
|
+
this.handleMessage(socket, line);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
socket.on("error", (err) => {
|
|
53
|
+
this.log(`Socket error: ${err.message}`);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
handleMessage(socket, message) {
|
|
57
|
+
let request;
|
|
58
|
+
try {
|
|
59
|
+
request = JSON.parse(message);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
this.sendResponse(socket, { id: "0", error: "Invalid JSON" });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const response = this.handleRequest(request);
|
|
66
|
+
this.sendResponse(socket, response);
|
|
67
|
+
}
|
|
68
|
+
handleRequest(request) {
|
|
69
|
+
const { id, method, params } = request;
|
|
70
|
+
switch (method) {
|
|
71
|
+
case "getPrices": {
|
|
72
|
+
const entry = this.cache.getAllMids();
|
|
73
|
+
if (!entry) {
|
|
74
|
+
return { id, error: "No data available" };
|
|
75
|
+
}
|
|
76
|
+
const coin = params?.coin;
|
|
77
|
+
if (coin) {
|
|
78
|
+
const normalizedCoin = coin.trim().toUpperCase();
|
|
79
|
+
const price = entry.data[normalizedCoin];
|
|
80
|
+
if (price === undefined) {
|
|
81
|
+
return { id, error: `Coin not found: ${normalizedCoin}` };
|
|
82
|
+
}
|
|
83
|
+
return { id, result: { [normalizedCoin]: price }, cached_at: entry.updatedAt };
|
|
84
|
+
}
|
|
85
|
+
return { id, result: entry.data, cached_at: entry.updatedAt };
|
|
86
|
+
}
|
|
87
|
+
case "getAssetCtxs": {
|
|
88
|
+
const entry = this.cache.getAllDexsAssetCtxs();
|
|
89
|
+
if (!entry) {
|
|
90
|
+
return { id, error: "No data available" };
|
|
91
|
+
}
|
|
92
|
+
return { id, result: entry.data, cached_at: entry.updatedAt };
|
|
93
|
+
}
|
|
94
|
+
case "getPerpMeta": {
|
|
95
|
+
const entry = this.cache.getAllPerpMetas();
|
|
96
|
+
if (!entry) {
|
|
97
|
+
return { id, error: "No data available" };
|
|
98
|
+
}
|
|
99
|
+
return { id, result: entry.data, cached_at: entry.updatedAt };
|
|
100
|
+
}
|
|
101
|
+
case "getSpotMeta": {
|
|
102
|
+
const entry = this.cache.getSpotMeta();
|
|
103
|
+
if (!entry) {
|
|
104
|
+
return { id, error: "No data available" };
|
|
105
|
+
}
|
|
106
|
+
return { id, result: entry.data, cached_at: entry.updatedAt };
|
|
107
|
+
}
|
|
108
|
+
case "getSpotAssetCtxs": {
|
|
109
|
+
const entry = this.cache.getSpotAssetCtxs();
|
|
110
|
+
if (!entry) {
|
|
111
|
+
return { id, error: "No data available" };
|
|
112
|
+
}
|
|
113
|
+
return { id, result: entry.data, cached_at: entry.updatedAt };
|
|
114
|
+
}
|
|
115
|
+
case "getStatus": {
|
|
116
|
+
const cacheStatus = this.cache.getStatus();
|
|
117
|
+
return {
|
|
118
|
+
id,
|
|
119
|
+
result: {
|
|
120
|
+
running: true,
|
|
121
|
+
testnet: this.isTestnet,
|
|
122
|
+
connected: this.subscriptions.isConnected(),
|
|
123
|
+
startedAt: this.startedAt,
|
|
124
|
+
uptime: Date.now() - this.startedAt,
|
|
125
|
+
cache: cacheStatus,
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
case "shutdown": {
|
|
130
|
+
// Respond first, then shutdown
|
|
131
|
+
setTimeout(() => this.onShutdown(), 100);
|
|
132
|
+
return { id, result: { ok: true } };
|
|
133
|
+
}
|
|
134
|
+
default:
|
|
135
|
+
return { id, error: `Unknown method: ${method}` };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
sendResponse(socket, response) {
|
|
139
|
+
try {
|
|
140
|
+
socket.write(JSON.stringify(response) + "\n");
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Socket may have closed
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async stop() {
|
|
147
|
+
return new Promise((resolve) => {
|
|
148
|
+
if (this.server) {
|
|
149
|
+
this.server.close(() => {
|
|
150
|
+
this.log("IPC server stopped");
|
|
151
|
+
resolve();
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
resolve();
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ServerCache } from "./cache.js";
|
|
2
|
+
export declare class SubscriptionManager {
|
|
3
|
+
private wsTransport;
|
|
4
|
+
private subscriptionClient;
|
|
5
|
+
private infoClient;
|
|
6
|
+
private cache;
|
|
7
|
+
private subscriptions;
|
|
8
|
+
private perpMetaInterval;
|
|
9
|
+
private spotMetaInterval;
|
|
10
|
+
private isTestnet;
|
|
11
|
+
private log;
|
|
12
|
+
constructor(cache: ServerCache, isTestnet: boolean, log: (msg: string) => void);
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
private fetchPerpMetas;
|
|
15
|
+
private fetchSpotMeta;
|
|
16
|
+
stop(): Promise<void>;
|
|
17
|
+
isConnected(): boolean;
|
|
18
|
+
}
|