openbroker 1.3.2 → 1.5.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 +23 -0
- package/dist/auto/audit.d.ts +57 -0
- package/dist/auto/audit.d.ts.map +1 -0
- package/dist/auto/audit.js +407 -0
- package/dist/auto/cli.d.ts +2 -0
- package/dist/auto/cli.d.ts.map +1 -0
- package/dist/auto/cli.js +423 -0
- package/dist/auto/events.d.ts +11 -0
- package/dist/auto/events.d.ts.map +1 -0
- package/dist/auto/events.js +36 -0
- package/dist/auto/examples/dca.d.ts +4 -0
- package/dist/auto/examples/dca.d.ts.map +1 -0
- package/dist/auto/examples/dca.js +60 -0
- package/dist/auto/examples/funding-arb.d.ts +4 -0
- package/dist/auto/examples/funding-arb.d.ts.map +1 -0
- package/dist/auto/examples/funding-arb.js +81 -0
- package/dist/auto/examples/grid.d.ts +4 -0
- package/dist/auto/examples/grid.d.ts.map +1 -0
- package/dist/auto/examples/grid.js +114 -0
- package/dist/auto/examples/mm-maker.d.ts +4 -0
- package/dist/auto/examples/mm-maker.d.ts.map +1 -0
- package/dist/auto/examples/mm-maker.js +131 -0
- package/dist/auto/examples/mm-spread.d.ts +4 -0
- package/dist/auto/examples/mm-spread.d.ts.map +1 -0
- package/dist/auto/examples/mm-spread.js +119 -0
- package/dist/auto/examples/price-alert.d.ts +4 -0
- package/dist/auto/examples/price-alert.d.ts.map +1 -0
- package/dist/auto/examples/price-alert.js +85 -0
- package/dist/auto/keep-awake.d.ts +11 -0
- package/dist/auto/keep-awake.d.ts.map +1 -0
- package/dist/auto/keep-awake.js +70 -0
- package/dist/auto/loader.d.ts +22 -0
- package/dist/auto/loader.d.ts.map +1 -0
- package/dist/auto/loader.js +127 -0
- package/dist/auto/prune.d.ts +40 -0
- package/dist/auto/prune.d.ts.map +1 -0
- package/dist/auto/prune.js +204 -0
- package/dist/auto/registry.d.ts +24 -0
- package/dist/auto/registry.d.ts.map +1 -0
- package/dist/auto/registry.js +93 -0
- package/dist/auto/report.d.ts +3 -0
- package/dist/auto/report.d.ts.map +1 -0
- package/dist/auto/report.js +385 -0
- package/dist/auto/runtime.d.ts +33 -0
- package/dist/auto/runtime.d.ts.map +1 -0
- package/dist/auto/runtime.js +844 -0
- package/dist/auto/types.d.ts +236 -0
- package/dist/auto/types.d.ts.map +1 -0
- package/dist/auto/types.js +3 -0
- package/dist/core/client.d.ts +691 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +2061 -0
- package/dist/core/config.d.ts +22 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +143 -0
- package/dist/core/types.d.ts +228 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/utils.d.ts +61 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +142 -0
- package/dist/core/ws.d.ts +121 -0
- package/dist/core/ws.d.ts.map +1 -0
- package/dist/core/ws.js +222 -0
- package/dist/info/account.d.ts +3 -0
- package/dist/info/account.d.ts.map +1 -0
- package/dist/info/account.js +198 -0
- package/dist/info/all-markets.d.ts +3 -0
- package/dist/info/all-markets.d.ts.map +1 -0
- package/dist/info/all-markets.js +272 -0
- package/dist/info/candles.d.ts +3 -0
- package/dist/info/candles.d.ts.map +1 -0
- package/dist/info/candles.js +120 -0
- package/dist/info/fees.d.ts +3 -0
- package/dist/info/fees.d.ts.map +1 -0
- package/dist/info/fees.js +87 -0
- package/dist/info/fills.d.ts +3 -0
- package/dist/info/fills.d.ts.map +1 -0
- package/dist/info/fills.js +105 -0
- package/dist/info/funding-history.d.ts +3 -0
- package/dist/info/funding-history.d.ts.map +1 -0
- package/dist/info/funding-history.js +98 -0
- package/dist/info/funding-scan.d.ts +3 -0
- package/dist/info/funding-scan.d.ts.map +1 -0
- package/dist/info/funding-scan.js +178 -0
- package/dist/info/funding.d.ts +3 -0
- package/dist/info/funding.d.ts.map +1 -0
- package/dist/info/funding.js +158 -0
- package/dist/info/markets.d.ts +3 -0
- package/dist/info/markets.d.ts.map +1 -0
- package/dist/info/markets.js +178 -0
- package/dist/info/order-status.d.ts +3 -0
- package/dist/info/order-status.d.ts.map +1 -0
- package/dist/info/order-status.js +85 -0
- package/dist/info/orders.d.ts +3 -0
- package/dist/info/orders.d.ts.map +1 -0
- package/dist/info/orders.js +162 -0
- package/dist/info/outcomes.d.ts +3 -0
- package/dist/info/outcomes.d.ts.map +1 -0
- package/dist/info/outcomes.js +175 -0
- package/dist/info/positions.d.ts +3 -0
- package/dist/info/positions.d.ts.map +1 -0
- package/dist/info/positions.js +127 -0
- package/dist/info/rate-limit.d.ts +3 -0
- package/dist/info/rate-limit.d.ts.map +1 -0
- package/dist/info/rate-limit.js +58 -0
- package/dist/info/search-markets.d.ts +3 -0
- package/dist/info/search-markets.d.ts.map +1 -0
- package/dist/info/search-markets.js +296 -0
- package/dist/info/spot.d.ts +3 -0
- package/dist/info/spot.d.ts.map +1 -0
- package/dist/info/spot.js +192 -0
- package/dist/info/trades.d.ts +3 -0
- package/dist/info/trades.d.ts.map +1 -0
- package/dist/info/trades.js +97 -0
- package/dist/lib.d.ts +14 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +17 -0
- package/dist/operations/bracket.d.ts +28 -0
- package/dist/operations/bracket.d.ts.map +1 -0
- package/dist/operations/bracket.js +266 -0
- package/dist/operations/cancel.d.ts +3 -0
- package/dist/operations/cancel.d.ts.map +1 -0
- package/dist/operations/cancel.js +107 -0
- package/dist/operations/chase.d.ts +25 -0
- package/dist/operations/chase.d.ts.map +1 -0
- package/dist/operations/chase.js +215 -0
- package/dist/operations/limit-order.d.ts +3 -0
- package/dist/operations/limit-order.d.ts.map +1 -0
- package/dist/operations/limit-order.js +144 -0
- package/dist/operations/market-order.d.ts +3 -0
- package/dist/operations/market-order.d.ts.map +1 -0
- package/dist/operations/market-order.js +153 -0
- package/dist/operations/outcome-order.d.ts +3 -0
- package/dist/operations/outcome-order.d.ts.map +1 -0
- package/dist/operations/outcome-order.js +171 -0
- package/dist/operations/scale.d.ts +3 -0
- package/dist/operations/scale.d.ts.map +1 -0
- package/dist/operations/scale.js +212 -0
- package/dist/operations/set-tpsl.d.ts +3 -0
- package/dist/operations/set-tpsl.d.ts.map +1 -0
- package/dist/operations/set-tpsl.js +277 -0
- package/dist/operations/spot-order.d.ts +3 -0
- package/dist/operations/spot-order.d.ts.map +1 -0
- package/dist/operations/spot-order.js +173 -0
- package/dist/operations/trigger-order.d.ts +3 -0
- package/dist/operations/trigger-order.d.ts.map +1 -0
- package/dist/operations/trigger-order.js +177 -0
- package/dist/operations/twap-cancel.d.ts +3 -0
- package/dist/operations/twap-cancel.d.ts.map +1 -0
- package/dist/operations/twap-cancel.js +57 -0
- package/dist/operations/twap-status.d.ts +3 -0
- package/dist/operations/twap-status.d.ts.map +1 -0
- package/dist/operations/twap-status.js +81 -0
- package/dist/operations/twap.d.ts +3 -0
- package/dist/operations/twap.d.ts.map +1 -0
- package/dist/operations/twap.js +124 -0
- package/dist/setup/approve-builder.d.ts +3 -0
- package/dist/setup/approve-builder.d.ts.map +1 -0
- package/dist/setup/approve-builder.js +155 -0
- package/dist/setup/env.d.ts +4 -0
- package/dist/setup/env.d.ts.map +1 -0
- package/dist/setup/env.js +8 -0
- package/dist/setup/onboard.d.ts +10 -0
- package/dist/setup/onboard.d.ts.map +1 -0
- package/dist/setup/onboard.js +462 -0
- package/package.json +10 -4
- package/scripts/core/client.ts +19 -1
- package/scripts/core/types.ts +7 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { OpenBrokerConfig } from './types.js';
|
|
2
|
+
export declare const GLOBAL_CONFIG_DIR: string;
|
|
3
|
+
export declare const GLOBAL_ENV_PATH: string;
|
|
4
|
+
export declare const LOCAL_ENV_PATH: string;
|
|
5
|
+
export declare const PROJECT_ROOT: string;
|
|
6
|
+
export declare const OPEN_BROKER_BUILDER_ADDRESS = "0xbb67021fA3e62ab4DA985bb5a55c5c1884381068";
|
|
7
|
+
/**
|
|
8
|
+
* Ensure the global config directory exists
|
|
9
|
+
*/
|
|
10
|
+
export declare function ensureConfigDir(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Get the path where config was loaded from, or where it should be saved
|
|
13
|
+
*/
|
|
14
|
+
export declare function getConfigPath(): string;
|
|
15
|
+
export declare function loadConfig(): OpenBrokerConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Check if the current config is read-only (no trading capability)
|
|
18
|
+
*/
|
|
19
|
+
export declare function isConfigured(): boolean;
|
|
20
|
+
export declare function getNetwork(): 'mainnet' | 'testnet';
|
|
21
|
+
export declare function isMainnet(): boolean;
|
|
22
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../scripts/core/config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAOnD,eAAO,MAAM,iBAAiB,QAAiC,CAAC;AAChE,eAAO,MAAM,eAAe,QAAkC,CAAC;AAG/D,eAAO,MAAM,cAAc,QAA2B,CAAC;AAGvD,eAAO,MAAM,YAAY,QAAwC,CAAC;AAMlE,eAAO,MAAM,2BAA2B,+CAA+C,CAAC;AA0DxF;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAKxC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,UAAU,IAAI,gBAAgB,CAyD7C;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,UAAU,IAAI,SAAS,GAAG,SAAS,CAGlD;AAED,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Configuration loader for Open Broker
|
|
2
|
+
import { config as loadDotenv } from 'dotenv';
|
|
3
|
+
import { resolve, join } from 'path';
|
|
4
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
7
|
+
// Config locations (in order of priority)
|
|
8
|
+
// 1. Environment variables (always checked first by process.env)
|
|
9
|
+
// 2. Local .env in current working directory
|
|
10
|
+
// 3. Global config at ~/.openbroker/.env
|
|
11
|
+
export const GLOBAL_CONFIG_DIR = join(homedir(), '.openbroker');
|
|
12
|
+
export const GLOBAL_ENV_PATH = join(GLOBAL_CONFIG_DIR, '.env');
|
|
13
|
+
// Use OPENBROKER_CWD if set (from CLI wrapper), otherwise use process.cwd()
|
|
14
|
+
const userCwd = process.env.OPENBROKER_CWD || process.cwd();
|
|
15
|
+
export const LOCAL_ENV_PATH = resolve(userCwd, '.env');
|
|
16
|
+
// Package root (for reference, not config loading)
|
|
17
|
+
export const PROJECT_ROOT = resolve(import.meta.dirname, '../..');
|
|
18
|
+
const MAINNET_URL = 'https://api.hyperliquid.xyz';
|
|
19
|
+
const TESTNET_URL = 'https://api.hyperliquid-testnet.xyz';
|
|
20
|
+
// Open Broker builder address - receives builder fees on all trades
|
|
21
|
+
export const OPEN_BROKER_BUILDER_ADDRESS = '0xbb67021fA3e62ab4DA985bb5a55c5c1884381068';
|
|
22
|
+
// Default read-only key (for info commands that don't need authentication)
|
|
23
|
+
// This is a valid but essentially useless private key
|
|
24
|
+
const DEFAULT_READ_ONLY_KEY = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
25
|
+
// Track if we've shown the read-only warning
|
|
26
|
+
let readOnlyWarningShown = false;
|
|
27
|
+
/**
|
|
28
|
+
* Find and load the config file from multiple locations
|
|
29
|
+
* Priority: env vars > local .env > global ~/.openbroker/.env > project .env
|
|
30
|
+
*/
|
|
31
|
+
function loadEnvFile() {
|
|
32
|
+
const verbose = process.env.VERBOSE === '1' || process.env.VERBOSE === 'true';
|
|
33
|
+
process.env.DOTENV_CONFIG_QUIET = 'true';
|
|
34
|
+
// Explicit config path via -c / --config (highest priority — overrides shell env vars)
|
|
35
|
+
const explicitPath = process.env.OPENBROKER_CONFIG;
|
|
36
|
+
if (explicitPath) {
|
|
37
|
+
if (existsSync(explicitPath)) {
|
|
38
|
+
loadDotenv({ path: explicitPath, override: true });
|
|
39
|
+
if (verbose) {
|
|
40
|
+
console.log(`[DEBUG] Loaded config from -c flag: ${explicitPath}`);
|
|
41
|
+
}
|
|
42
|
+
return explicitPath;
|
|
43
|
+
}
|
|
44
|
+
console.error(`Config file not found: ${explicitPath}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
// Check locations in order of priority
|
|
48
|
+
const locations = [
|
|
49
|
+
{ path: LOCAL_ENV_PATH, name: 'local (.env)' },
|
|
50
|
+
{ path: GLOBAL_ENV_PATH, name: 'global (~/.openbroker/.env)' },
|
|
51
|
+
];
|
|
52
|
+
for (const { path, name } of locations) {
|
|
53
|
+
if (existsSync(path)) {
|
|
54
|
+
const result = loadDotenv({ path });
|
|
55
|
+
if (verbose) {
|
|
56
|
+
console.log(`[DEBUG] Loaded config from ${name}: ${path}`);
|
|
57
|
+
}
|
|
58
|
+
return path;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (verbose) {
|
|
62
|
+
console.log('[DEBUG] No config file found in any location');
|
|
63
|
+
console.log('[DEBUG] Run "openbroker setup" to configure');
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
// Load config on module import
|
|
68
|
+
const loadedConfigPath = loadEnvFile();
|
|
69
|
+
/**
|
|
70
|
+
* Ensure the global config directory exists
|
|
71
|
+
*/
|
|
72
|
+
export function ensureConfigDir() {
|
|
73
|
+
if (!existsSync(GLOBAL_CONFIG_DIR)) {
|
|
74
|
+
mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
75
|
+
}
|
|
76
|
+
return GLOBAL_CONFIG_DIR;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get the path where config was loaded from, or where it should be saved
|
|
80
|
+
*/
|
|
81
|
+
export function getConfigPath() {
|
|
82
|
+
return loadedConfigPath || GLOBAL_ENV_PATH;
|
|
83
|
+
}
|
|
84
|
+
export function loadConfig() {
|
|
85
|
+
let privateKey = process.env.HYPERLIQUID_PRIVATE_KEY;
|
|
86
|
+
let isReadOnly = false;
|
|
87
|
+
if (!privateKey) {
|
|
88
|
+
// Use default read-only key for info commands
|
|
89
|
+
privateKey = DEFAULT_READ_ONLY_KEY;
|
|
90
|
+
isReadOnly = true;
|
|
91
|
+
// Show warning once
|
|
92
|
+
if (!readOnlyWarningShown) {
|
|
93
|
+
readOnlyWarningShown = true;
|
|
94
|
+
console.error('\x1b[33m⚠️ Not configured for trading. Run "openbroker setup" to enable trades.\x1b[0m\n');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!privateKey.startsWith('0x') || privateKey.length !== 66) {
|
|
98
|
+
throw new Error('HYPERLIQUID_PRIVATE_KEY must be a 64-character hex string with 0x prefix');
|
|
99
|
+
}
|
|
100
|
+
const network = process.env.HYPERLIQUID_NETWORK || 'mainnet';
|
|
101
|
+
const baseUrl = network === 'testnet' ? TESTNET_URL : MAINNET_URL;
|
|
102
|
+
// Builder fee is hardcoded — set by OpenBroker, not configurable by users
|
|
103
|
+
const builderAddress = OPEN_BROKER_BUILDER_ADDRESS.toLowerCase();
|
|
104
|
+
const builderFee = 10; // 10 tenths-of-bps = 1 bps = 0.01%
|
|
105
|
+
const slippageBps = parseInt(process.env.SLIPPAGE_BPS || '50', 10); // default 0.5%
|
|
106
|
+
// Derive the wallet address from private key
|
|
107
|
+
const wallet = privateKeyToAccount(privateKey);
|
|
108
|
+
const walletAddress = wallet.address.toLowerCase();
|
|
109
|
+
// Account address can be different if using an API wallet
|
|
110
|
+
const accountAddress = process.env.HYPERLIQUID_ACCOUNT_ADDRESS?.toLowerCase();
|
|
111
|
+
// Determine if this is an API wallet setup
|
|
112
|
+
const isApiWallet = accountAddress !== undefined && accountAddress !== walletAddress;
|
|
113
|
+
// Vault address — only for vault trading (ERC4626 contracts / native vaults via CoreWriter).
|
|
114
|
+
// Standard API wallets (approved via approveAgent) do NOT need this.
|
|
115
|
+
const vaultAddress = process.env.HYPERLIQUID_VAULT_ADDRESS?.toLowerCase();
|
|
116
|
+
const verbose = process.env.VERBOSE === '1' || process.env.VERBOSE === 'true';
|
|
117
|
+
return {
|
|
118
|
+
baseUrl,
|
|
119
|
+
privateKey: privateKey,
|
|
120
|
+
walletAddress,
|
|
121
|
+
accountAddress: accountAddress || walletAddress,
|
|
122
|
+
isApiWallet,
|
|
123
|
+
isReadOnly,
|
|
124
|
+
builderAddress,
|
|
125
|
+
builderFee,
|
|
126
|
+
slippageBps,
|
|
127
|
+
vaultAddress,
|
|
128
|
+
verbose,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if the current config is read-only (no trading capability)
|
|
133
|
+
*/
|
|
134
|
+
export function isConfigured() {
|
|
135
|
+
return !!process.env.HYPERLIQUID_PRIVATE_KEY;
|
|
136
|
+
}
|
|
137
|
+
export function getNetwork() {
|
|
138
|
+
const network = process.env.HYPERLIQUID_NETWORK || 'mainnet';
|
|
139
|
+
return network === 'testnet' ? 'testnet' : 'mainnet';
|
|
140
|
+
}
|
|
141
|
+
export function isMainnet() {
|
|
142
|
+
return getNetwork() === 'mainnet';
|
|
143
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
export interface OpenBrokerConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
privateKey: `0x${string}`;
|
|
4
|
+
walletAddress: string;
|
|
5
|
+
accountAddress: string;
|
|
6
|
+
isApiWallet: boolean;
|
|
7
|
+
isReadOnly: boolean;
|
|
8
|
+
builderAddress: string;
|
|
9
|
+
builderFee: number;
|
|
10
|
+
slippageBps: number;
|
|
11
|
+
vaultAddress?: string;
|
|
12
|
+
verbose: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface BuilderInfo {
|
|
15
|
+
b: string;
|
|
16
|
+
f: number;
|
|
17
|
+
}
|
|
18
|
+
export type OrderType = {
|
|
19
|
+
limit: {
|
|
20
|
+
tif: 'Gtc' | 'Ioc' | 'Alo';
|
|
21
|
+
};
|
|
22
|
+
} | {
|
|
23
|
+
trigger: {
|
|
24
|
+
triggerPx: string;
|
|
25
|
+
isMarket: boolean;
|
|
26
|
+
tpsl: 'tp' | 'sl';
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export interface OrderRequest {
|
|
30
|
+
coin: string;
|
|
31
|
+
is_buy: boolean;
|
|
32
|
+
sz: number;
|
|
33
|
+
limit_px: number;
|
|
34
|
+
order_type: OrderType;
|
|
35
|
+
reduce_only?: boolean;
|
|
36
|
+
cloid?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface OrderWire {
|
|
39
|
+
a: number;
|
|
40
|
+
b: boolean;
|
|
41
|
+
p: string;
|
|
42
|
+
s: string;
|
|
43
|
+
r: boolean;
|
|
44
|
+
t: OrderType;
|
|
45
|
+
c?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface OrderResponse {
|
|
48
|
+
status: 'ok' | 'err';
|
|
49
|
+
response?: {
|
|
50
|
+
type: 'order';
|
|
51
|
+
data: {
|
|
52
|
+
statuses: Array<{
|
|
53
|
+
resting?: {
|
|
54
|
+
oid: number;
|
|
55
|
+
};
|
|
56
|
+
filled?: {
|
|
57
|
+
totalSz: string;
|
|
58
|
+
avgPx: string;
|
|
59
|
+
oid: number;
|
|
60
|
+
};
|
|
61
|
+
error?: string;
|
|
62
|
+
[key: string]: unknown;
|
|
63
|
+
}>;
|
|
64
|
+
};
|
|
65
|
+
} | string;
|
|
66
|
+
error?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface CancelRequest {
|
|
69
|
+
coin: string;
|
|
70
|
+
oid: number;
|
|
71
|
+
}
|
|
72
|
+
export interface CancelResponse {
|
|
73
|
+
status: 'ok' | 'err';
|
|
74
|
+
response?: {
|
|
75
|
+
type: 'cancel';
|
|
76
|
+
data: {
|
|
77
|
+
statuses: string[];
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export interface AssetMeta {
|
|
82
|
+
name: string;
|
|
83
|
+
szDecimals: number;
|
|
84
|
+
maxLeverage: number;
|
|
85
|
+
onlyIsolated?: boolean;
|
|
86
|
+
isDelisted?: boolean;
|
|
87
|
+
marginTableId?: number;
|
|
88
|
+
[key: string]: unknown;
|
|
89
|
+
}
|
|
90
|
+
export interface AssetCtx {
|
|
91
|
+
funding: string;
|
|
92
|
+
openInterest: string;
|
|
93
|
+
prevDayPx: string;
|
|
94
|
+
dayNtlVlm: string;
|
|
95
|
+
premium: string | null;
|
|
96
|
+
oraclePx: string;
|
|
97
|
+
markPx: string;
|
|
98
|
+
midPx?: string | null;
|
|
99
|
+
impactPxs?: [string, string] | string[] | null;
|
|
100
|
+
dayBaseVlm?: string;
|
|
101
|
+
[key: string]: unknown;
|
|
102
|
+
}
|
|
103
|
+
export interface Meta {
|
|
104
|
+
universe: AssetMeta[];
|
|
105
|
+
}
|
|
106
|
+
export interface MetaAndAssetCtxs {
|
|
107
|
+
meta: Meta;
|
|
108
|
+
assetCtxs: AssetCtx[];
|
|
109
|
+
}
|
|
110
|
+
export interface OutcomeSideSpec {
|
|
111
|
+
name: string;
|
|
112
|
+
token?: number;
|
|
113
|
+
}
|
|
114
|
+
export interface OutcomeMetaEntry {
|
|
115
|
+
outcome: number;
|
|
116
|
+
name: string;
|
|
117
|
+
description: string;
|
|
118
|
+
sideSpecs: OutcomeSideSpec[];
|
|
119
|
+
}
|
|
120
|
+
export interface OutcomeQuestion {
|
|
121
|
+
question: number;
|
|
122
|
+
name: string;
|
|
123
|
+
description: string;
|
|
124
|
+
fallbackOutcome: number;
|
|
125
|
+
namedOutcomes: number[];
|
|
126
|
+
settledNamedOutcomes?: number[];
|
|
127
|
+
}
|
|
128
|
+
export interface OutcomeMetaResponse {
|
|
129
|
+
outcomes: OutcomeMetaEntry[];
|
|
130
|
+
questions?: OutcomeQuestion[];
|
|
131
|
+
}
|
|
132
|
+
export interface OutcomeMarket {
|
|
133
|
+
outcome: number;
|
|
134
|
+
name: string;
|
|
135
|
+
description: string;
|
|
136
|
+
parsedDescription: Record<string, string>;
|
|
137
|
+
sides: Array<{
|
|
138
|
+
side: 0 | 1;
|
|
139
|
+
name: string;
|
|
140
|
+
encoding: number;
|
|
141
|
+
coin: string;
|
|
142
|
+
tokenName: string;
|
|
143
|
+
assetId: number;
|
|
144
|
+
token?: number;
|
|
145
|
+
szDecimals?: number;
|
|
146
|
+
midPx?: string;
|
|
147
|
+
markPx?: string;
|
|
148
|
+
prevDayPx?: string;
|
|
149
|
+
dayNtlVlm?: string;
|
|
150
|
+
}>;
|
|
151
|
+
question?: OutcomeQuestion;
|
|
152
|
+
}
|
|
153
|
+
export interface Position {
|
|
154
|
+
coin: string;
|
|
155
|
+
/**
|
|
156
|
+
* Canonical Hyperliquid asset index (native: meta index; HIP-3:
|
|
157
|
+
* 100000 + perp_dex_index*10000 + index_in_meta). Stamped by `getUserStateAll`
|
|
158
|
+
* so consumers can key positions by a unique integer rather than the coin string
|
|
159
|
+
* (whose HIP-3 prefix may differ between endpoints). Undefined if unresolvable.
|
|
160
|
+
*/
|
|
161
|
+
assetId?: number;
|
|
162
|
+
szi: string;
|
|
163
|
+
entryPx: string;
|
|
164
|
+
positionValue: string;
|
|
165
|
+
unrealizedPnl: string;
|
|
166
|
+
returnOnEquity: string;
|
|
167
|
+
liquidationPx: string | null;
|
|
168
|
+
leverage: {
|
|
169
|
+
type: 'cross' | 'isolated';
|
|
170
|
+
value: number;
|
|
171
|
+
rawUsd?: string;
|
|
172
|
+
};
|
|
173
|
+
marginUsed: string;
|
|
174
|
+
maxLeverage: number;
|
|
175
|
+
}
|
|
176
|
+
export interface AssetPosition {
|
|
177
|
+
position: Position;
|
|
178
|
+
type: 'oneWay';
|
|
179
|
+
}
|
|
180
|
+
export interface MarginSummary {
|
|
181
|
+
accountValue: string;
|
|
182
|
+
totalNtlPos: string;
|
|
183
|
+
totalRawUsd: string;
|
|
184
|
+
totalMarginUsed: string;
|
|
185
|
+
withdrawable: string;
|
|
186
|
+
}
|
|
187
|
+
export interface ClearinghouseState {
|
|
188
|
+
assetPositions: AssetPosition[];
|
|
189
|
+
crossMarginSummary: MarginSummary;
|
|
190
|
+
marginSummary: MarginSummary;
|
|
191
|
+
crossMaintenanceMarginUsed: string;
|
|
192
|
+
}
|
|
193
|
+
export interface FundingInfo {
|
|
194
|
+
coin: string;
|
|
195
|
+
fundingRate: string;
|
|
196
|
+
annualizedRate: number;
|
|
197
|
+
premium: string;
|
|
198
|
+
openInterest: string;
|
|
199
|
+
markPx: string;
|
|
200
|
+
oraclePx: string;
|
|
201
|
+
}
|
|
202
|
+
export interface OpenOrder {
|
|
203
|
+
coin: string;
|
|
204
|
+
oid: number;
|
|
205
|
+
cloid?: string;
|
|
206
|
+
side: 'B' | 'A';
|
|
207
|
+
sz: string;
|
|
208
|
+
limitPx: string;
|
|
209
|
+
orderType: string;
|
|
210
|
+
origSz: string;
|
|
211
|
+
timestamp: number;
|
|
212
|
+
}
|
|
213
|
+
export interface InfoRequest {
|
|
214
|
+
type: string;
|
|
215
|
+
user?: string;
|
|
216
|
+
[key: string]: unknown;
|
|
217
|
+
}
|
|
218
|
+
export interface ExchangeRequest {
|
|
219
|
+
action: Record<string, unknown>;
|
|
220
|
+
nonce: number;
|
|
221
|
+
signature: {
|
|
222
|
+
r: string;
|
|
223
|
+
s: string;
|
|
224
|
+
v: number;
|
|
225
|
+
};
|
|
226
|
+
vaultAddress?: string | null;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../scripts/core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { OrderWire, OrderRequest } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Round price to 5 significant figures and appropriate decimals
|
|
4
|
+
* Perps: max 6 decimals, Spot: max 8 decimals
|
|
5
|
+
*/
|
|
6
|
+
export declare function roundPrice(price: number, szDecimals: number, isSpot?: boolean): string;
|
|
7
|
+
/**
|
|
8
|
+
* Round size to asset's szDecimals
|
|
9
|
+
*/
|
|
10
|
+
export declare function roundSize(size: number, szDecimals: number): string;
|
|
11
|
+
/**
|
|
12
|
+
* Calculate slippage-adjusted price for market orders
|
|
13
|
+
*/
|
|
14
|
+
export declare function getSlippagePrice(midPrice: number, isBuy: boolean, slippageBps: number): number;
|
|
15
|
+
/**
|
|
16
|
+
* Convert order request to wire format
|
|
17
|
+
*/
|
|
18
|
+
export declare function orderToWire(order: OrderRequest, assetIndex: number, szDecimals: number): OrderWire;
|
|
19
|
+
/**
|
|
20
|
+
* Get current timestamp in milliseconds
|
|
21
|
+
*/
|
|
22
|
+
export declare function getTimestampMs(): number;
|
|
23
|
+
/**
|
|
24
|
+
* Format USD amount for display
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatUsd(amount: number | string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Format percentage for display
|
|
29
|
+
*/
|
|
30
|
+
export declare function formatPercent(value: number | string, decimals?: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* Format funding rate (hourly to annualized)
|
|
33
|
+
*/
|
|
34
|
+
export declare function annualizeFundingRate(hourlyRate: number | string): number;
|
|
35
|
+
/**
|
|
36
|
+
* Parse CLI arguments into key-value pairs
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseArgs(args: string[]): Record<string, string | boolean>;
|
|
39
|
+
/**
|
|
40
|
+
* Normalize a coin name: uppercase the asset, keep dex prefix lowercase.
|
|
41
|
+
* "eth" → "ETH", "xyz:cl" → "xyz:CL", "xyz:CL" → "xyz:CL"
|
|
42
|
+
*/
|
|
43
|
+
export declare function normalizeCoin(coin: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Sleep for specified milliseconds
|
|
46
|
+
*/
|
|
47
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Generate a random client order ID
|
|
50
|
+
*/
|
|
51
|
+
export declare function generateCloid(): string;
|
|
52
|
+
/**
|
|
53
|
+
* Check if builder fee is approved and print warning if not
|
|
54
|
+
* Returns true if approved, false if not
|
|
55
|
+
*/
|
|
56
|
+
export declare function checkBuilderFeeApproval(client: {
|
|
57
|
+
getMaxBuilderFee: () => Promise<string | null>;
|
|
58
|
+
builderAddress: string;
|
|
59
|
+
isTestnet: boolean;
|
|
60
|
+
}): Promise<boolean>;
|
|
61
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../scripts/core/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAa,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAErE;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,OAAe,GAAG,MAAM,CAM7F;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,MAAM,GAClB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,SAAS,CAeX;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAQzD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,MAAM,CAGlF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGxE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAmB1E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE;IAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GACrG,OAAO,CAAC,OAAO,CAAC,CAYlB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Utility functions for Open Broker
|
|
2
|
+
/**
|
|
3
|
+
* Round price to 5 significant figures and appropriate decimals
|
|
4
|
+
* Perps: max 6 decimals, Spot: max 8 decimals
|
|
5
|
+
*/
|
|
6
|
+
export function roundPrice(price, szDecimals, isSpot = false) {
|
|
7
|
+
// Round to 5 significant figures first
|
|
8
|
+
const sigFigs = parseFloat(price.toPrecision(5));
|
|
9
|
+
// Then round to max decimals (6 for perps - szDecimals adjustment, 8 for spot)
|
|
10
|
+
const maxDecimals = isSpot ? 8 : Math.max(0, 6 - szDecimals);
|
|
11
|
+
return sigFigs.toFixed(maxDecimals);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Round size to asset's szDecimals
|
|
15
|
+
*/
|
|
16
|
+
export function roundSize(size, szDecimals) {
|
|
17
|
+
return size.toFixed(szDecimals);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Calculate slippage-adjusted price for market orders
|
|
21
|
+
*/
|
|
22
|
+
export function getSlippagePrice(midPrice, isBuy, slippageBps) {
|
|
23
|
+
const slippageMultiplier = slippageBps / 10000;
|
|
24
|
+
return isBuy
|
|
25
|
+
? midPrice * (1 + slippageMultiplier)
|
|
26
|
+
: midPrice * (1 - slippageMultiplier);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Convert order request to wire format
|
|
30
|
+
*/
|
|
31
|
+
export function orderToWire(order, assetIndex, szDecimals) {
|
|
32
|
+
const wire = {
|
|
33
|
+
a: assetIndex,
|
|
34
|
+
b: order.is_buy,
|
|
35
|
+
p: roundPrice(order.limit_px, szDecimals),
|
|
36
|
+
s: roundSize(order.sz, szDecimals),
|
|
37
|
+
r: order.reduce_only ?? false,
|
|
38
|
+
t: order.order_type,
|
|
39
|
+
};
|
|
40
|
+
if (order.cloid) {
|
|
41
|
+
wire.c = order.cloid;
|
|
42
|
+
}
|
|
43
|
+
return wire;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get current timestamp in milliseconds
|
|
47
|
+
*/
|
|
48
|
+
export function getTimestampMs() {
|
|
49
|
+
return Date.now();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Format USD amount for display
|
|
53
|
+
*/
|
|
54
|
+
export function formatUsd(amount) {
|
|
55
|
+
const num = typeof amount === 'string' ? parseFloat(amount) : amount;
|
|
56
|
+
return new Intl.NumberFormat('en-US', {
|
|
57
|
+
style: 'currency',
|
|
58
|
+
currency: 'USD',
|
|
59
|
+
minimumFractionDigits: 2,
|
|
60
|
+
maximumFractionDigits: 2,
|
|
61
|
+
}).format(num);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Format percentage for display
|
|
65
|
+
*/
|
|
66
|
+
export function formatPercent(value, decimals = 2) {
|
|
67
|
+
const num = typeof value === 'string' ? parseFloat(value) : value;
|
|
68
|
+
return `${(num * 100).toFixed(decimals)}%`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format funding rate (hourly to annualized)
|
|
72
|
+
*/
|
|
73
|
+
export function annualizeFundingRate(hourlyRate) {
|
|
74
|
+
const rate = typeof hourlyRate === 'string' ? parseFloat(hourlyRate) : hourlyRate;
|
|
75
|
+
return rate * 8760; // 24 * 365 hours
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Parse CLI arguments into key-value pairs
|
|
79
|
+
*/
|
|
80
|
+
export function parseArgs(args) {
|
|
81
|
+
const result = {};
|
|
82
|
+
for (let i = 0; i < args.length; i++) {
|
|
83
|
+
const arg = args[i];
|
|
84
|
+
if (arg.startsWith('--')) {
|
|
85
|
+
const key = arg.slice(2);
|
|
86
|
+
const nextArg = args[i + 1];
|
|
87
|
+
if (nextArg && !nextArg.startsWith('--')) {
|
|
88
|
+
result[key] = nextArg;
|
|
89
|
+
i++;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
result[key] = true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Normalize a coin name: uppercase the asset, keep dex prefix lowercase.
|
|
100
|
+
* "eth" → "ETH", "xyz:cl" → "xyz:CL", "xyz:CL" → "xyz:CL"
|
|
101
|
+
*/
|
|
102
|
+
export function normalizeCoin(coin) {
|
|
103
|
+
const colonIdx = coin.indexOf(':');
|
|
104
|
+
if (colonIdx >= 0) {
|
|
105
|
+
return coin.slice(0, colonIdx).toLowerCase() + ':' + coin.slice(colonIdx + 1).toUpperCase();
|
|
106
|
+
}
|
|
107
|
+
return coin.toUpperCase();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Sleep for specified milliseconds
|
|
111
|
+
*/
|
|
112
|
+
export function sleep(ms) {
|
|
113
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Generate a random client order ID
|
|
117
|
+
*/
|
|
118
|
+
export function generateCloid() {
|
|
119
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
120
|
+
let result = '';
|
|
121
|
+
for (let i = 0; i < 16; i++) {
|
|
122
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check if builder fee is approved and print warning if not
|
|
128
|
+
* Returns true if approved, false if not
|
|
129
|
+
*/
|
|
130
|
+
export async function checkBuilderFeeApproval(client) {
|
|
131
|
+
// Skip builder fee check on testnet — builder may not have balance
|
|
132
|
+
if (client.isTestnet)
|
|
133
|
+
return true;
|
|
134
|
+
const approval = await client.getMaxBuilderFee();
|
|
135
|
+
if (!approval) {
|
|
136
|
+
console.log('⚠️ Builder fee not approved!');
|
|
137
|
+
console.log(` Run: npx tsx scripts/setup/approve-builder.ts`);
|
|
138
|
+
console.log(` Builder: ${client.builderAddress}\n`);
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
}
|