@yuants/vendor-hyperliquid 0.4.6 → 0.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/dist/account.js +62 -0
- package/dist/account.js.map +1 -0
- package/dist/api/client.js +69 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/private-api.js +35 -0
- package/dist/api/private-api.js.map +1 -0
- package/dist/api/public-api.js +12 -0
- package/dist/api/public-api.js.map +1 -0
- package/dist/api/types.js +13 -0
- package/dist/api/types.js.map +1 -0
- package/dist/index.js +4 -47
- package/dist/index.js.map +1 -1
- package/dist/order-actions/cancelOrder.js +34 -0
- package/dist/order-actions/cancelOrder.js.map +1 -0
- package/dist/order-actions/submitOrder.js +16 -0
- package/dist/order-actions/submitOrder.js.map +1 -0
- package/dist/order-actions-with-credential.js +17 -0
- package/dist/order-actions-with-credential.js.map +1 -0
- package/dist/order-actions.js +36 -0
- package/dist/order-actions.js.map +1 -0
- package/dist/order-utils.js +139 -0
- package/dist/order-utils.js.map +1 -0
- package/dist/public-data/index.js +5 -0
- package/dist/public-data/index.js.map +1 -0
- package/dist/public-data/interest-rate.js +80 -0
- package/dist/public-data/interest-rate.js.map +1 -0
- package/dist/public-data/ohlc.js +106 -0
- package/dist/public-data/ohlc.js.map +1 -0
- package/dist/{product.js → public-data/product.js} +28 -15
- package/dist/public-data/product.js.map +1 -0
- package/dist/public-data/quote.js +49 -0
- package/dist/public-data/quote.js.map +1 -0
- package/lib/account.d.ts +2 -0
- package/lib/account.d.ts.map +1 -0
- package/lib/account.js +65 -0
- package/lib/account.js.map +1 -0
- package/lib/api/client.d.ts +8 -0
- package/lib/api/client.d.ts.map +1 -0
- package/lib/api/client.js +74 -0
- package/lib/api/client.js.map +1 -0
- package/lib/api/private-api.d.ts +39 -0
- package/lib/api/private-api.d.ts.map +1 -0
- package/lib/api/private-api.js +40 -0
- package/lib/api/private-api.js.map +1 -0
- package/lib/api/public-api.d.ts +167 -0
- package/lib/api/public-api.d.ts.map +1 -0
- package/lib/api/public-api.js +25 -0
- package/lib/api/public-api.js.map +1 -0
- package/lib/api/types.d.ts +7 -0
- package/lib/api/types.d.ts.map +1 -0
- package/lib/api/types.js +18 -0
- package/lib/api/types.js.map +1 -0
- package/lib/index.d.ts +4 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -47
- package/lib/index.js.map +1 -1
- package/lib/order-actions/cancelOrder.d.ts +4 -0
- package/lib/order-actions/cancelOrder.d.ts.map +1 -0
- package/lib/order-actions/cancelOrder.js +38 -0
- package/lib/order-actions/cancelOrder.js.map +1 -0
- package/lib/order-actions/submitOrder.d.ts +6 -0
- package/lib/order-actions/submitOrder.d.ts.map +1 -0
- package/lib/order-actions/submitOrder.js +20 -0
- package/lib/order-actions/submitOrder.js.map +1 -0
- package/lib/order-actions-with-credential.d.ts +2 -0
- package/lib/order-actions-with-credential.d.ts.map +1 -0
- package/lib/order-actions-with-credential.js +19 -0
- package/lib/order-actions-with-credential.js.map +1 -0
- package/lib/order-actions.d.ts +2 -0
- package/lib/order-actions.d.ts.map +1 -0
- package/lib/order-actions.js +38 -0
- package/lib/order-actions.js.map +1 -0
- package/lib/order-utils.d.ts +31 -0
- package/lib/order-utils.d.ts.map +1 -0
- package/lib/order-utils.js +146 -0
- package/lib/order-utils.js.map +1 -0
- package/lib/public-data/index.d.ts +5 -0
- package/lib/public-data/index.d.ts.map +1 -0
- package/lib/public-data/index.js +7 -0
- package/lib/public-data/index.js.map +1 -0
- package/lib/public-data/interest-rate.d.ts +2 -0
- package/lib/public-data/interest-rate.d.ts.map +1 -0
- package/lib/public-data/interest-rate.js +82 -0
- package/lib/public-data/interest-rate.js.map +1 -0
- package/lib/public-data/ohlc.d.ts.map +1 -0
- package/lib/public-data/ohlc.js +108 -0
- package/lib/public-data/ohlc.js.map +1 -0
- package/lib/public-data/product.d.ts +2 -0
- package/lib/public-data/product.d.ts.map +1 -0
- package/lib/{product.js → public-data/product.js} +27 -15
- package/lib/public-data/product.js.map +1 -0
- package/lib/{quote.d.ts.map → public-data/quote.d.ts.map} +1 -1
- package/lib/public-data/quote.js +51 -0
- package/lib/public-data/quote.js.map +1 -0
- package/package.json +1 -1
- package/temp/package-deps.json +21 -11
- package/dist/api.js +0 -231
- package/dist/api.js.map +0 -1
- package/dist/interest_rate.js +0 -90
- package/dist/interest_rate.js.map +0 -1
- package/dist/ohlc.js +0 -125
- package/dist/ohlc.js.map +0 -1
- package/dist/order.js +0 -200
- package/dist/order.js.map +0 -1
- package/dist/pending-orders.js +0 -44
- package/dist/pending-orders.js.map +0 -1
- package/dist/product.js.map +0 -1
- package/dist/quote.js +0 -49
- package/dist/quote.js.map +0 -1
- package/lib/api.d.ts +0 -374
- package/lib/api.d.ts.map +0 -1
- package/lib/api.js +0 -235
- package/lib/api.js.map +0 -1
- package/lib/interest_rate.d.ts +0 -2
- package/lib/interest_rate.d.ts.map +0 -1
- package/lib/interest_rate.js +0 -92
- package/lib/interest_rate.js.map +0 -1
- package/lib/ohlc.d.ts.map +0 -1
- package/lib/ohlc.js +0 -127
- package/lib/ohlc.js.map +0 -1
- package/lib/order.d.ts +0 -2
- package/lib/order.d.ts.map +0 -1
- package/lib/order.js +0 -202
- package/lib/order.js.map +0 -1
- package/lib/pending-orders.d.ts +0 -2
- package/lib/pending-orders.d.ts.map +0 -1
- package/lib/pending-orders.js +0 -46
- package/lib/pending-orders.js.map +0 -1
- package/lib/product.d.ts +0 -2
- package/lib/product.d.ts.map +0 -1
- package/lib/product.js.map +0 -1
- package/lib/quote.js +0 -51
- package/lib/quote.js.map +0 -1
- /package/lib/{ohlc.d.ts → public-data/ohlc.d.ts} +0 -0
- /package/lib/{quote.d.ts → public-data/quote.d.ts} +0 -0
package/dist/account.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { addAccountMarket, provideAccountInfoService } from '@yuants/data-account';
|
|
2
|
+
import { providePendingOrdersService } from '@yuants/data-order';
|
|
3
|
+
import { Terminal } from '@yuants/protocol';
|
|
4
|
+
import { encodePath } from '@yuants/utils';
|
|
5
|
+
import { getUserOpenOrders, getUserPerpetualsAccountSummary } from './api/public-api';
|
|
6
|
+
import { getDefaultCredential } from './api/types';
|
|
7
|
+
const terminal = Terminal.fromNodeEnv();
|
|
8
|
+
const credential = getDefaultCredential();
|
|
9
|
+
const walletAddress = credential.address.toLowerCase();
|
|
10
|
+
export const defaultPerpAccountId = `hyperliquid/${walletAddress}/perp/USDC`;
|
|
11
|
+
addAccountMarket(terminal, { account_id: defaultPerpAccountId, market_id: 'HYPERLIQUID/PERP' });
|
|
12
|
+
const mapPosition = (position) => ({
|
|
13
|
+
position_id: `${position.position.coin}-USD`,
|
|
14
|
+
datasource_id: 'HYPERLIQUID',
|
|
15
|
+
product_id: encodePath('PERPETUAL', `${position.position.coin}-USD`),
|
|
16
|
+
direction: +position.position.szi > 0 ? 'LONG' : 'SHORT',
|
|
17
|
+
volume: Math.abs(+position.position.szi),
|
|
18
|
+
free_volume: Math.abs(+position.position.szi),
|
|
19
|
+
position_price: +position.position.entryPx,
|
|
20
|
+
closable_price: Math.abs(+position.position.positionValue / +position.position.szi || 0),
|
|
21
|
+
floating_profit: +position.position.unrealizedPnl,
|
|
22
|
+
valuation: +position.position.positionValue,
|
|
23
|
+
margin: +position.position.marginUsed,
|
|
24
|
+
});
|
|
25
|
+
provideAccountInfoService(terminal, defaultPerpAccountId, async () => {
|
|
26
|
+
const summary = await getUserPerpetualsAccountSummary({ user: credential.address });
|
|
27
|
+
return {
|
|
28
|
+
money: {
|
|
29
|
+
currency: 'USDC',
|
|
30
|
+
equity: +summary.crossMarginSummary.accountValue,
|
|
31
|
+
free: +summary.withdrawable,
|
|
32
|
+
},
|
|
33
|
+
positions: summary.assetPositions.map(mapPosition),
|
|
34
|
+
};
|
|
35
|
+
}, { auto_refresh_interval: 1000 });
|
|
36
|
+
const mapOrderDirection = (side) => {
|
|
37
|
+
const normalized = side.toUpperCase();
|
|
38
|
+
if (normalized === 'BID' || normalized === 'BUY') {
|
|
39
|
+
return 'OPEN_LONG';
|
|
40
|
+
}
|
|
41
|
+
if (normalized === 'ASK' || normalized === 'SELL') {
|
|
42
|
+
return 'OPEN_SHORT';
|
|
43
|
+
}
|
|
44
|
+
return 'OPEN_LONG';
|
|
45
|
+
};
|
|
46
|
+
providePendingOrdersService(terminal, defaultPerpAccountId, async () => {
|
|
47
|
+
const orders = await getUserOpenOrders({ user: credential.address });
|
|
48
|
+
return orders.map((order) => {
|
|
49
|
+
var _a, _b;
|
|
50
|
+
return ({
|
|
51
|
+
order_id: `${order.oid}`,
|
|
52
|
+
account_id: defaultPerpAccountId,
|
|
53
|
+
product_id: encodePath('PERPETUAL', `${(_a = order.coin) === null || _a === void 0 ? void 0 : _a.trim()}-USD`),
|
|
54
|
+
order_type: 'LIMIT',
|
|
55
|
+
order_direction: mapOrderDirection(order.side),
|
|
56
|
+
volume: Number(order.sz) || 0,
|
|
57
|
+
price: Number(order.limitPx) || undefined,
|
|
58
|
+
submit_at: Number((_b = order.timestamp) !== null && _b !== void 0 ? _b : Date.now()),
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}, { auto_refresh_interval: 2000 });
|
|
62
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../src/account.ts"],"names":[],"mappings":"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","sourcesContent":["import { addAccountMarket, IPosition, provideAccountInfoService } from '@yuants/data-account';\nimport { IOrder, providePendingOrdersService } from '@yuants/data-order';\nimport { Terminal } from '@yuants/protocol';\nimport { encodePath } from '@yuants/utils';\nimport { getUserOpenOrders, getUserPerpetualsAccountSummary } from './api/public-api';\nimport { getDefaultCredential } from './api/types';\n\nconst terminal = Terminal.fromNodeEnv();\nconst credential = getDefaultCredential();\nconst walletAddress = credential.address.toLowerCase();\nexport const defaultPerpAccountId = `hyperliquid/${walletAddress}/perp/USDC`;\n\naddAccountMarket(terminal, { account_id: defaultPerpAccountId, market_id: 'HYPERLIQUID/PERP' });\n\nconst mapPosition = (position: any): IPosition => ({\n position_id: `${position.position.coin}-USD`,\n datasource_id: 'HYPERLIQUID',\n product_id: encodePath('PERPETUAL', `${position.position.coin}-USD`),\n direction: +position.position.szi > 0 ? 'LONG' : 'SHORT',\n volume: Math.abs(+position.position.szi),\n free_volume: Math.abs(+position.position.szi),\n position_price: +position.position.entryPx,\n closable_price: Math.abs(+position.position.positionValue / +position.position.szi || 0),\n floating_profit: +position.position.unrealizedPnl,\n valuation: +position.position.positionValue,\n margin: +position.position.marginUsed,\n});\n\nprovideAccountInfoService(\n terminal,\n defaultPerpAccountId,\n async () => {\n const summary = await getUserPerpetualsAccountSummary({ user: credential.address });\n return {\n money: {\n currency: 'USDC',\n equity: +summary.crossMarginSummary.accountValue,\n free: +summary.withdrawable,\n },\n positions: summary.assetPositions.map(mapPosition),\n };\n },\n { auto_refresh_interval: 1000 },\n);\n\nconst mapOrderDirection = (side: string): IOrder['order_direction'] => {\n const normalized = side.toUpperCase();\n if (normalized === 'BID' || normalized === 'BUY') {\n return 'OPEN_LONG';\n }\n if (normalized === 'ASK' || normalized === 'SELL') {\n return 'OPEN_SHORT';\n }\n return 'OPEN_LONG';\n};\n\nprovidePendingOrdersService(\n terminal,\n defaultPerpAccountId,\n async () => {\n const orders = await getUserOpenOrders({ user: credential.address });\n return orders.map(\n (order): IOrder => ({\n order_id: `${order.oid}`,\n account_id: defaultPerpAccountId,\n product_id: encodePath('PERPETUAL', `${order.coin?.trim()}-USD`),\n order_type: 'LIMIT',\n order_direction: mapOrderDirection(order.side),\n volume: Number(order.sz) || 0,\n price: Number(order.limitPx) || undefined,\n submit_at: Number(order.timestamp ?? Date.now()),\n }),\n );\n },\n { auto_refresh_interval: 2000 },\n);\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { UUID, formatTime } from '@yuants/utils';
|
|
2
|
+
import { Subject, filter, firstValueFrom, mergeMap, of, shareReplay, throwError, timeout, timer } from 'rxjs';
|
|
3
|
+
const BASE_URL = 'https://api.hyperliquid.xyz';
|
|
4
|
+
const buildUrl = (path, method, params) => {
|
|
5
|
+
const url = new URL(BASE_URL);
|
|
6
|
+
url.pathname = path;
|
|
7
|
+
if (method === 'GET' && params) {
|
|
8
|
+
const entries = Object.entries(params).sort(([a], [b]) => a.localeCompare(b));
|
|
9
|
+
for (const [key, value] of entries) {
|
|
10
|
+
url.searchParams.set(key, '' + value);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return url;
|
|
14
|
+
};
|
|
15
|
+
const callApi = async (method, path, params) => {
|
|
16
|
+
const url = buildUrl(path, method, params);
|
|
17
|
+
const body = method === 'GET' ? '' : JSON.stringify(params !== null && params !== void 0 ? params : {});
|
|
18
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
19
|
+
console.info(formatTime(Date.now()), method, url.href, body);
|
|
20
|
+
const res = await fetch(url.href, {
|
|
21
|
+
method,
|
|
22
|
+
headers,
|
|
23
|
+
body: method === 'GET' ? undefined : body || undefined,
|
|
24
|
+
});
|
|
25
|
+
const retStr = await res.text();
|
|
26
|
+
try {
|
|
27
|
+
if (process.env.LOG_LEVEL === 'DEBUG') {
|
|
28
|
+
console.debug(formatTime(Date.now()), 'HyperliquidResponse', path, JSON.stringify(params), retStr);
|
|
29
|
+
}
|
|
30
|
+
return JSON.parse(retStr);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.error(formatTime(Date.now()), 'HyperliquidRequestFailed', path, JSON.stringify(params), retStr);
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const controllers = new Map();
|
|
38
|
+
const ensureController = (path, period, limit) => {
|
|
39
|
+
if (controllers.has(path)) {
|
|
40
|
+
return controllers.get(path);
|
|
41
|
+
}
|
|
42
|
+
const controller = {
|
|
43
|
+
requestQueue: [],
|
|
44
|
+
responseChannel: new Subject(),
|
|
45
|
+
};
|
|
46
|
+
timer(0, period)
|
|
47
|
+
.pipe(filter(() => controller.requestQueue.length > 0), mergeMap(() => controller.requestQueue.splice(0, limit)), mergeMap(async (request) => {
|
|
48
|
+
try {
|
|
49
|
+
const response = await callApi(request.method, request.path, request.params);
|
|
50
|
+
return { trace_id: request.trace_id, response };
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return { trace_id: request.trace_id, error: error };
|
|
54
|
+
}
|
|
55
|
+
}))
|
|
56
|
+
.subscribe(controller.responseChannel);
|
|
57
|
+
controllers.set(path, controller);
|
|
58
|
+
return controller;
|
|
59
|
+
};
|
|
60
|
+
export const request = (method, path, params) => callApi(method, path, params);
|
|
61
|
+
export const requestWithFlowControl = async (method, path, flowControl, params) => {
|
|
62
|
+
var _a;
|
|
63
|
+
const controller = ensureController(path, flowControl.period, flowControl.limit);
|
|
64
|
+
const trace_id = UUID();
|
|
65
|
+
const res$ = controller.responseChannel.pipe(filter((resp) => resp.trace_id === trace_id), mergeMap((resp) => (resp.error ? throwError(() => resp.error) : of(resp))), timeout(30000), shareReplay(1));
|
|
66
|
+
controller.requestQueue.push({ trace_id, method, path, params });
|
|
67
|
+
return ((_a = (await firstValueFrom(res$)).response) !== null && _a !== void 0 ? _a : null);
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { UUID, formatTime } from '@yuants/utils';\nimport { Subject, filter, firstValueFrom, mergeMap, of, shareReplay, throwError, timeout, timer } from 'rxjs';\n\ntype HttpMethod = 'GET' | 'POST';\n\nconst BASE_URL = 'https://api.hyperliquid.xyz';\n\nconst buildUrl = (path: string, method: HttpMethod, params?: any) => {\n const url = new URL(BASE_URL);\n url.pathname = path;\n if (method === 'GET' && params) {\n const entries = Object.entries(params).sort(([a], [b]) => a.localeCompare(b));\n for (const [key, value] of entries) {\n url.searchParams.set(key, '' + value);\n }\n }\n return url;\n};\n\nconst callApi = async (method: HttpMethod, path: string, params?: any) => {\n const url = buildUrl(path, method, params);\n const body = method === 'GET' ? '' : JSON.stringify(params ?? {});\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n console.info(formatTime(Date.now()), method, url.href, body);\n const res = await fetch(url.href, {\n method,\n headers,\n body: method === 'GET' ? undefined : body || undefined,\n });\n const retStr = await res.text();\n try {\n if (process.env.LOG_LEVEL === 'DEBUG') {\n console.debug(formatTime(Date.now()), 'HyperliquidResponse', path, JSON.stringify(params), retStr);\n }\n return JSON.parse(retStr);\n } catch (err) {\n console.error(formatTime(Date.now()), 'HyperliquidRequestFailed', path, JSON.stringify(params), retStr);\n throw err;\n }\n};\n\ntype FlowController = {\n requestQueue: Array<{ trace_id: string; method: HttpMethod; path: string; params?: any }>;\n responseChannel: Subject<{ trace_id: string; response?: any; error?: Error }>;\n};\n\nconst controllers = new Map<string, FlowController>();\n\nconst ensureController = (path: string, period: number, limit: number) => {\n if (controllers.has(path)) {\n return controllers.get(path)!;\n }\n const controller: FlowController = {\n requestQueue: [],\n responseChannel: new Subject(),\n };\n timer(0, period)\n .pipe(\n filter(() => controller.requestQueue.length > 0),\n mergeMap(() => controller.requestQueue.splice(0, limit)),\n mergeMap(async (request) => {\n try {\n const response = await callApi(request.method, request.path, request.params);\n return { trace_id: request.trace_id, response };\n } catch (error) {\n return { trace_id: request.trace_id, error: error as Error };\n }\n }),\n )\n .subscribe(controller.responseChannel);\n controllers.set(path, controller);\n return controller;\n};\n\nexport const request = <T = any>(method: HttpMethod, path: string, params?: any) =>\n callApi(method, path, params) as Promise<T>;\n\nexport const requestWithFlowControl = async <T = any>(\n method: HttpMethod,\n path: string,\n flowControl: { period: number; limit: number },\n params?: any,\n) => {\n const controller = ensureController(path, flowControl.period, flowControl.limit);\n const trace_id = UUID();\n const res$ = controller.responseChannel.pipe(\n filter((resp) => resp.trace_id === trace_id),\n mergeMap((resp) => (resp.error ? throwError(() => resp.error) : of(resp))),\n timeout(30_000),\n shareReplay(1),\n );\n controller.requestQueue.push({ trace_id, method, path, params });\n return ((await firstValueFrom(res$)).response ?? null) as T;\n};\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Wallet } from 'ethers';
|
|
2
|
+
import { signL1Action } from '../sign';
|
|
3
|
+
import { request } from './client';
|
|
4
|
+
const walletCache = new Map();
|
|
5
|
+
const getWallet = (credential) => {
|
|
6
|
+
if (!walletCache.has(credential.private_key)) {
|
|
7
|
+
walletCache.set(credential.private_key, new Wallet(credential.private_key));
|
|
8
|
+
}
|
|
9
|
+
return walletCache.get(credential.private_key);
|
|
10
|
+
};
|
|
11
|
+
export const placeOrder = async (credential, params) => {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const action = {
|
|
14
|
+
type: 'order',
|
|
15
|
+
orders: params.orders,
|
|
16
|
+
grouping: 'na',
|
|
17
|
+
};
|
|
18
|
+
if (params.builder) {
|
|
19
|
+
action['builder'] = params.builder;
|
|
20
|
+
}
|
|
21
|
+
const nonce = Date.now();
|
|
22
|
+
const signature = await signL1Action(getWallet(credential), action, (_a = params.vaultAddress) !== null && _a !== void 0 ? _a : null, nonce, (_b = params.expiresAfter) !== null && _b !== void 0 ? _b : null, true);
|
|
23
|
+
return request('POST', 'exchange', { action, nonce, signature });
|
|
24
|
+
};
|
|
25
|
+
export const cancelOrder = async (credential, params) => {
|
|
26
|
+
var _a, _b;
|
|
27
|
+
const action = {
|
|
28
|
+
type: 'cancel',
|
|
29
|
+
cancels: params.cancels,
|
|
30
|
+
};
|
|
31
|
+
const nonce = Date.now();
|
|
32
|
+
const signature = await signL1Action(getWallet(credential), action, (_a = params.vaultAddress) !== null && _a !== void 0 ? _a : null, nonce, (_b = params.expiresAfter) !== null && _b !== void 0 ? _b : null, true);
|
|
33
|
+
return request('POST', 'exchange', { action, nonce, signature });
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=private-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"private-api.js","sourceRoot":"","sources":["../../src/api/private-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAyBnC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE9C,MAAM,SAAS,GAAG,CAAC,UAAuB,EAAE,EAAE;IAC5C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE;QAC5C,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;KAC7E;IACD,OAAO,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAE,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAC7B,UAAuB,EACvB,MAKC,EACD,EAAE;;IACF,MAAM,MAAM,GAAwB;QAClC,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,IAAI;KACf,CAAC;IACF,IAAI,MAAM,CAAC,OAAO,EAAE;QAClB,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC;KACpC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,MAAM,YAAY,CAClC,SAAS,CAAC,UAAU,CAAC,EACrB,MAAM,EACN,MAAA,MAAM,CAAC,YAAY,mCAAI,IAAI,EAC3B,KAAK,EACL,MAAA,MAAM,CAAC,YAAY,mCAAI,IAAI,EAC3B,IAAI,CACL,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AACnE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,UAAuB,EACvB,MAAkF,EAClF,EAAE;;IACF,MAAM,MAAM,GAAwB;QAClC,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,SAAS,GAAG,MAAM,YAAY,CAClC,SAAS,CAAC,UAAU,CAAC,EACrB,MAAM,EACN,MAAA,MAAM,CAAC,YAAY,mCAAI,IAAI,EAC3B,KAAK,EACL,MAAA,MAAM,CAAC,YAAY,mCAAI,IAAI,EAC3B,IAAI,CACL,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AACnE,CAAC,CAAC","sourcesContent":["import { Wallet } from 'ethers';\nimport { signL1Action } from '../sign';\nimport { request } from './client';\nimport { ICredential } from './types';\n\ntype OrderPayload = {\n a: number;\n b: boolean;\n p: string;\n s: string;\n r: boolean;\n t: {\n limit?: { tif: string };\n trigger?: {\n isMarket: boolean;\n triggerPx: string;\n tpsl: string;\n };\n };\n c?: number;\n};\n\ntype CancelPayload = {\n a: number;\n o: number;\n};\n\nconst walletCache = new Map<string, Wallet>();\n\nconst getWallet = (credential: ICredential) => {\n if (!walletCache.has(credential.private_key)) {\n walletCache.set(credential.private_key, new Wallet(credential.private_key));\n }\n return walletCache.get(credential.private_key)!;\n};\n\nexport const placeOrder = async (\n credential: ICredential,\n params: {\n orders: OrderPayload[];\n builder?: { b: string; f: number };\n vaultAddress?: string;\n expiresAfter?: number;\n },\n) => {\n const action: Record<string, any> = {\n type: 'order',\n orders: params.orders,\n grouping: 'na',\n };\n if (params.builder) {\n action['builder'] = params.builder;\n }\n const nonce = Date.now();\n const signature = await signL1Action(\n getWallet(credential),\n action,\n params.vaultAddress ?? null,\n nonce,\n params.expiresAfter ?? null,\n true,\n );\n return request('POST', 'exchange', { action, nonce, signature });\n};\n\nexport const cancelOrder = async (\n credential: ICredential,\n params: { cancels: CancelPayload[]; vaultAddress?: string; expiresAfter?: number },\n) => {\n const action: Record<string, any> = {\n type: 'cancel',\n cancels: params.cancels,\n };\n const nonce = Date.now();\n const signature = await signL1Action(\n getWallet(credential),\n action,\n params.vaultAddress ?? null,\n nonce,\n params.expiresAfter ?? null,\n true,\n );\n return request('POST', 'exchange', { action, nonce, signature });\n};\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { request } from './client';
|
|
2
|
+
export const getUserPerpetualsAccountSummary = (params) => request('POST', 'info', Object.assign(Object.assign({}, params), { type: 'clearinghouseState' }));
|
|
3
|
+
export const getPerpetualsMetaData = (params) => request('POST', 'info', Object.assign(Object.assign({}, (params !== null && params !== void 0 ? params : {})), { type: 'meta' }));
|
|
4
|
+
export const getSpotMetaData = () => request('POST', 'info', { type: 'spotMeta' });
|
|
5
|
+
export const getUserFundingHistory = (params) => request('POST', 'info', Object.assign(Object.assign({}, params), { type: 'fundingHistory' }));
|
|
6
|
+
export const getUserTokenBalances = (params) => request('POST', 'info', Object.assign(Object.assign({}, params), { type: 'tokenBalances' }));
|
|
7
|
+
export const getUserOpenOrders = (params) => request('POST', 'info', Object.assign(Object.assign({}, params), { type: 'openOrders' }));
|
|
8
|
+
export const getHistoricalFundingRates = (params) => request('POST', 'info', Object.assign(Object.assign({}, params), { type: 'fundingHistory' }));
|
|
9
|
+
export const getAllMids = () => request('POST', 'info', { type: 'allMids' });
|
|
10
|
+
export const getMetaAndAssetCtxs = () => request('POST', 'info', { type: 'metaAndAssetCtxs' });
|
|
11
|
+
export const getCandleSnapshot = (params) => request('POST', 'info', Object.assign({ type: 'candleSnapshot' }, params));
|
|
12
|
+
//# sourceMappingURL=public-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../src/api/public-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,MAAwB,EAAE,EAAE,CAC1E,OAAO,CAoCJ,MAAM,EAAE,MAAM,kCAAO,MAAM,KAAE,IAAI,EAAE,oBAAoB,IAAG,CAAC;AAEhE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAAyB,EAAE,EAAE,CACjE,OAAO,CAkBJ,MAAM,EAAE,MAAM,kCAAO,CAAC,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,EAAE,CAAC,KAAE,IAAI,EAAE,MAAM,IAAG,CAAC;AAE1D,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE,CAClC,OAAO,CAiBJ,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA8D,EAAE,EAAE,CACtG,OAAO,CAML,MAAM,EAAE,MAAM,kCAAO,MAAM,KAAE,IAAI,EAAE,gBAAgB,IAAG,CAAC;AAE3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAwB,EAAE,EAAE,CAC/D,OAAO,CACL,MAAM,EACN,MAAM,kCAED,MAAM,KACT,IAAI,EAAE,eAAe,IAExB,CAAC;AAEJ,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAwB,EAAE,EAAE,CAC5D,OAAO,CACL,MAAM,EACN,MAAM,kCAED,MAAM,KACT,IAAI,EAAE,YAAY,IAErB,CAAC;AAEJ,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAA6D,EAAE,EAAE,CACzG,OAAO,CAAyE,MAAM,EAAE,MAAM,kCACzF,MAAM,KACT,IAAI,EAAE,gBAAgB,IACtB,CAAC;AAEL,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,CAAyB,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AAErG,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,EAAE,CACtC,OAAO,CAuBL,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;AAElD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAEjC,EAAE,EAAE,CACH,OAAO,CAaL,MAAM,EAAE,MAAM,kBAAI,IAAI,EAAE,gBAAgB,IAAK,MAAM,EAAG,CAAC","sourcesContent":["import { request } from './client';\n\nexport const getUserPerpetualsAccountSummary = (params: { user: string }) =>\n request<{\n marginSummary: {\n accountValue: string;\n totalNtlPos: string;\n totalRawUsd: string;\n totalMarginUsed: string;\n };\n crossMarginSummary: {\n accountValue: string;\n totalNtlPos: string;\n totalRawUsd: string;\n totalMarginUsed: string;\n };\n crossMaintenanceMarginUsed: string;\n withdrawable: string;\n assetPositions: {\n type: string;\n position: {\n coin: string;\n szi: string;\n leverage: { type: string; value: number };\n entryPx: string;\n positionValue: string;\n unrealizedPnl: string;\n returnOnEquity: string;\n liquidationPx: string;\n marginUsed: string;\n maxLeverage: number;\n cumFunding: {\n allTime: string;\n sinceOpen: string;\n sinceChange: string;\n };\n };\n }[];\n time: number;\n }>('POST', 'info', { ...params, type: 'clearinghouseState' });\n\nexport const getPerpetualsMetaData = (params?: { dex?: string }) =>\n request<{\n universe: {\n name: string;\n szDecimals: number;\n maxLeverage: number;\n onlyIsolated?: boolean;\n isDelisted?: boolean;\n }[];\n marginTables: [\n number,\n {\n description: string;\n marginTiers: {\n lowerBound: string;\n maxLeverage: number;\n }[];\n },\n ][];\n }>('POST', 'info', { ...(params ?? {}), type: 'meta' });\n\nexport const getSpotMetaData = () =>\n request<{\n tokens: {\n name: string;\n szDecimals: number;\n weiDecimals: number;\n index: number;\n tokenId: string;\n isCanonical: boolean;\n evmContract: null;\n fullName: null;\n }[];\n universe: {\n name: string;\n tokens: number[];\n index: number;\n isCanonical: boolean;\n }[];\n }>('POST', 'info', { type: 'spotMeta' });\n\nexport const getUserFundingHistory = (params: { user: string; startTime?: number; endTime?: number }) =>\n request<\n {\n time: number;\n hash: string;\n delta: { type: string; coin: string; usdc: string; szi: string; fundingRate: string };\n }[]\n >('POST', 'info', { ...params, type: 'fundingHistory' });\n\nexport const getUserTokenBalances = (params: { user: string }) =>\n request<{ balances: { coin: string; token: number; hold: string; total: string; entryNtl: string }[] }>(\n 'POST',\n 'info',\n {\n ...params,\n type: 'tokenBalances',\n },\n );\n\nexport const getUserOpenOrders = (params: { user: string }) =>\n request<{ coin: string; limitPx: string; oid: number; side: string; sz: string; timestamp: number }[]>(\n 'POST',\n 'info',\n {\n ...params,\n type: 'openOrders',\n },\n );\n\nexport const getHistoricalFundingRates = (params: { coin: string; startTime: number; endTime?: number }) =>\n request<{ coin: string; fundingRate: string; premium: string; time: number }[]>('POST', 'info', {\n ...params,\n type: 'fundingHistory',\n });\n\nexport const getAllMids = () => request<Record<string, string>>('POST', 'info', { type: 'allMids' });\n\nexport const getMetaAndAssetCtxs = () =>\n request<\n [\n {\n universe: {\n name: string;\n szDecimals: number;\n maxLeverage: number;\n onlyIsolated?: boolean;\n isDelisted?: boolean;\n }[];\n },\n {\n dayNtlVlm: string;\n funding: string;\n impactPxs: [string, string];\n markPx: string;\n midPx: string;\n openInterest: string;\n oraclePx: string;\n premium: string;\n prevDayPx: string;\n }[],\n ]\n >('POST', 'info', { type: 'metaAndAssetCtxs' });\n\nexport const getCandleSnapshot = (params: {\n req: { coin: string; interval: string; startTime: number; endTime: number };\n}) =>\n request<\n {\n T: number;\n c: string;\n h: string;\n i: string;\n l: string;\n o: string;\n n: number;\n s: string;\n t: number;\n v: string;\n }[]\n >('POST', 'info', { type: 'candleSnapshot', ...params });\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Wallet } from 'ethers';
|
|
2
|
+
export const createCredential = (private_key) => {
|
|
3
|
+
const wallet = new Wallet(private_key);
|
|
4
|
+
return { private_key, address: wallet.address };
|
|
5
|
+
};
|
|
6
|
+
export const getDefaultCredential = () => {
|
|
7
|
+
const private_key = process.env.PRIVATE_KEY;
|
|
8
|
+
if (!private_key) {
|
|
9
|
+
throw new Error('Missing Hyperliquid credential: PRIVATE_KEY must be set');
|
|
10
|
+
}
|
|
11
|
+
return createCredential(private_key);
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAOhC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAmB,EAAe,EAAE;IACnE,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC;IACvC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAgB,EAAE;IACpD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAC5C,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;KAC5E;IACD,OAAO,gBAAgB,CAAC,WAAW,CAAC,CAAC;AACvC,CAAC,CAAC","sourcesContent":["import { Wallet } from 'ethers';\n\nexport interface ICredential {\n private_key: string;\n address: string;\n}\n\nexport const createCredential = (private_key: string): ICredential => {\n const wallet = new Wallet(private_key);\n return { private_key, address: wallet.address };\n};\n\nexport const getDefaultCredential = (): ICredential => {\n const private_key = process.env.PRIVATE_KEY;\n if (!private_key) {\n throw new Error('Missing Hyperliquid credential: PRIVATE_KEY must be set');\n }\n return createCredential(private_key);\n};\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,48 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import './interest_rate';
|
|
6
|
-
import './order';
|
|
7
|
-
import './product';
|
|
8
|
-
import './pending-orders';
|
|
9
|
-
import './quote';
|
|
10
|
-
const terminal = Terminal.fromNodeEnv();
|
|
11
|
-
(async () => {
|
|
12
|
-
// swap account info
|
|
13
|
-
{
|
|
14
|
-
const account_id = `Hyperliquid/${client.public_key}`;
|
|
15
|
-
provideAccountInfoService(terminal, account_id, async () => {
|
|
16
|
-
const accountRes = await client.getUserPerpetualsAccountSummary({
|
|
17
|
-
user: client.public_key,
|
|
18
|
-
});
|
|
19
|
-
const equity = +accountRes.crossMarginSummary.accountValue;
|
|
20
|
-
const free = +accountRes.withdrawable;
|
|
21
|
-
return {
|
|
22
|
-
money: {
|
|
23
|
-
currency: 'USDC',
|
|
24
|
-
equity,
|
|
25
|
-
free,
|
|
26
|
-
},
|
|
27
|
-
positions: accountRes.assetPositions.map((position) => ({
|
|
28
|
-
position_id: `${position.position.coin}-USD`,
|
|
29
|
-
datasource_id: 'HYPERLIQUID',
|
|
30
|
-
product_id: encodePath('PERPETUAL', `${position.position.coin}-USD`),
|
|
31
|
-
direction: +position.position.szi > 0 ? 'LONG' : 'SHORT',
|
|
32
|
-
volume: Math.abs(+position.position.szi),
|
|
33
|
-
free_volume: Math.abs(+position.position.szi),
|
|
34
|
-
position_price: +position.position.entryPx,
|
|
35
|
-
closable_price: Math.abs(+position.position.positionValue / +position.position.szi),
|
|
36
|
-
floating_profit: +position.position.unrealizedPnl,
|
|
37
|
-
valuation: +position.position.positionValue,
|
|
38
|
-
margin: +position.position.marginUsed,
|
|
39
|
-
})),
|
|
40
|
-
};
|
|
41
|
-
}, { auto_refresh_interval: 1000 });
|
|
42
|
-
addAccountMarket(terminal, { account_id: `Hyperliquid/${client.public_key}`, market_id: 'Hyperliquid' });
|
|
43
|
-
}
|
|
44
|
-
// TODO: spot account info
|
|
45
|
-
// TODO: funding rate
|
|
46
|
-
// TODO: transfer
|
|
47
|
-
})();
|
|
1
|
+
import './account';
|
|
2
|
+
import './order-actions';
|
|
3
|
+
import './order-actions-with-credential';
|
|
4
|
+
import './public-data';
|
|
48
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAC;AACnB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iCAAiC,CAAC;AACzC,OAAO,eAAe,CAAC","sourcesContent":["import './account';\nimport './order-actions';\nimport './order-actions-with-credential';\nimport './public-data';\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { resolveAssetInfo } from '../order-utils';
|
|
2
|
+
import { cancelOrder } from '../api/private-api';
|
|
3
|
+
export const cancelOrderAction = async (credential, order) => {
|
|
4
|
+
var _a, _b, _c;
|
|
5
|
+
const orderId = Number(order.order_id);
|
|
6
|
+
if (!Number.isFinite(orderId)) {
|
|
7
|
+
throw new Error(`Invalid order_id: ${order.order_id}`);
|
|
8
|
+
}
|
|
9
|
+
const assetId = (() => {
|
|
10
|
+
if (order.comment) {
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(order.comment);
|
|
13
|
+
if (typeof (parsed === null || parsed === void 0 ? void 0 : parsed.asset_id) === 'number') {
|
|
14
|
+
return parsed.asset_id;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch (_a) {
|
|
18
|
+
// ignore
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
})();
|
|
23
|
+
const resolvedAsset = assetId !== null && assetId !== void 0 ? assetId : (await resolveAssetInfo(order.product_id)).assetId;
|
|
24
|
+
const res = await cancelOrder(credential, { cancels: [{ a: resolvedAsset, o: orderId }] });
|
|
25
|
+
const status = (_b = (_a = res === null || res === void 0 ? void 0 : res.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.statuses;
|
|
26
|
+
const error = (res === null || res === void 0 ? void 0 : res.status) !== 'ok'
|
|
27
|
+
? 'API ERROR'
|
|
28
|
+
: Array.isArray(status) && typeof status[0] !== 'string'
|
|
29
|
+
? (_c = status[0]) === null || _c === void 0 ? void 0 : _c.error
|
|
30
|
+
: undefined;
|
|
31
|
+
if (error)
|
|
32
|
+
throw new Error(error);
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=cancelOrder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancelOrder.js","sourceRoot":"","sources":["../../src/order-actions/cancelOrder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAuB,EAAE,KAAa,EAAE,EAAE;;IAChF,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QAC7B,MAAM,IAAI,KAAK,CAAC,qBAAqB,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;KACxD;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE;QACpB,IAAI,KAAK,CAAC,OAAO,EAAE;YACjB,IAAI;gBACF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzC,IAAI,OAAO,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,CAAA,KAAK,QAAQ,EAAE;oBACxC,OAAO,MAAM,CAAC,QAAQ,CAAC;iBACxB;aACF;YAAC,WAAM;gBACN,SAAS;aACV;SACF;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,EAAE,CAAC;IACL,MAAM,aAAa,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,CAAC,MAAM,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;IACpF,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3F,MAAM,MAAM,GAAG,MAAA,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,QAAQ,0CAAE,IAAI,0CAAE,QAAQ,CAAC;IAC7C,MAAM,KAAK,GACT,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,MAAM,MAAK,IAAI;QAClB,CAAC,CAAC,WAAW;QACb,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ;YACxD,CAAC,CAAC,MAAA,MAAM,CAAC,CAAC,CAAC,0CAAE,KAAK;YAClB,CAAC,CAAC,SAAS,CAAC;IAEhB,IAAI,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC,CAAC","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { ICredential } from '../api/types';\nimport { resolveAssetInfo } from '../order-utils';\nimport { cancelOrder } from '../api/private-api';\n\nexport const cancelOrderAction = async (credential: ICredential, order: IOrder) => {\n const orderId = Number(order.order_id);\n if (!Number.isFinite(orderId)) {\n throw new Error(`Invalid order_id: ${order.order_id}`);\n }\n const assetId = (() => {\n if (order.comment) {\n try {\n const parsed = JSON.parse(order.comment);\n if (typeof parsed?.asset_id === 'number') {\n return parsed.asset_id;\n }\n } catch {\n // ignore\n }\n }\n return undefined;\n })();\n const resolvedAsset = assetId ?? (await resolveAssetInfo(order.product_id)).assetId;\n const res = await cancelOrder(credential, { cancels: [{ a: resolvedAsset, o: orderId }] });\n const status = res?.response?.data?.statuses;\n const error =\n res?.status !== 'ok'\n ? 'API ERROR'\n : Array.isArray(status) && typeof status[0] !== 'string'\n ? status[0]?.error\n : undefined;\n\n if (error) throw new Error(error);\n};\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { placeOrder } from '../api/private-api';
|
|
2
|
+
import { buildOrderPayload } from '../order-utils';
|
|
3
|
+
export const submitOrder = async (credential, order) => {
|
|
4
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
5
|
+
const { orderParams } = await buildOrderPayload(order);
|
|
6
|
+
const res = await placeOrder(credential, { orders: [orderParams] });
|
|
7
|
+
const status = (_c = (_b = (_a = res === null || res === void 0 ? void 0 : res.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.statuses) === null || _c === void 0 ? void 0 : _c[0];
|
|
8
|
+
const orderId = (_h = (_g = (_e = (_d = status === null || status === void 0 ? void 0 : status.resting) === null || _d === void 0 ? void 0 : _d.oid) !== null && _e !== void 0 ? _e : (_f = status === null || status === void 0 ? void 0 : status.filled) === null || _f === void 0 ? void 0 : _f.oid) !== null && _g !== void 0 ? _g : status === null || status === void 0 ? void 0 : status.oid) !== null && _h !== void 0 ? _h : status === null || status === void 0 ? void 0 : status.orderId;
|
|
9
|
+
const error = (res === null || res === void 0 ? void 0 : res.status) !== 'ok' ? 'API ERROR' : (status === null || status === void 0 ? void 0 : status.error) ? status.error : undefined;
|
|
10
|
+
if (error)
|
|
11
|
+
throw new Error(error);
|
|
12
|
+
if (orderId === undefined)
|
|
13
|
+
throw new Error('No order ID returned from API');
|
|
14
|
+
return { order_id: `${orderId}` };
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=submitOrder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submitOrder.js","sourceRoot":"","sources":["../../src/order-actions/submitOrder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,UAAuB,EAAE,KAAa,EAAiC,EAAE;;IACzG,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,MAAA,MAAA,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,QAAQ,0CAAE,IAAI,0CAAE,QAAQ,0CAAG,CAAC,CAAC,CAAC;IAClD,MAAM,OAAO,GACX,MAAA,MAAA,MAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,OAAO,0CAAE,GAAG,mCAAI,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,0CAAE,GAAG,mCAAK,MAAc,aAAd,MAAM,uBAAN,MAAM,CAAU,GAAG,mCAAK,MAAc,aAAd,MAAM,uBAAN,MAAM,CAAU,OAAO,CAAC;IAClG,MAAM,KAAK,GAAG,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,MAAM,MAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,EAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5F,IAAI,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC5E,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,CAAC;AACpC,CAAC,CAAC","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { placeOrder } from '../api/private-api';\nimport { ICredential } from '../api/types';\nimport { buildOrderPayload } from '../order-utils';\n\nexport const submitOrder = async (credential: ICredential, order: IOrder): Promise<{ order_id: string }> => {\n const { orderParams } = await buildOrderPayload(order);\n const res = await placeOrder(credential, { orders: [orderParams] });\n const status = res?.response?.data?.statuses?.[0];\n const orderId =\n status?.resting?.oid ?? status?.filled?.oid ?? (status as any)?.oid ?? (status as any)?.orderId;\n const error = res?.status !== 'ok' ? 'API ERROR' : status?.error ? status.error : undefined;\n if (error) throw new Error(error);\n if (orderId === undefined) throw new Error('No order ID returned from API');\n return { order_id: `${orderId}` };\n};\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { provideOrderActionsWithCredential } from '@yuants/data-order';
|
|
2
|
+
import { Terminal } from '@yuants/protocol';
|
|
3
|
+
import { cancelOrderAction } from './order-actions/cancelOrder';
|
|
4
|
+
import { submitOrder } from './order-actions/submitOrder';
|
|
5
|
+
const terminal = Terminal.fromNodeEnv();
|
|
6
|
+
provideOrderActionsWithCredential(terminal, 'HYPERLIQUID', {
|
|
7
|
+
type: 'object',
|
|
8
|
+
required: ['private_key', 'address'],
|
|
9
|
+
properties: {
|
|
10
|
+
private_key: { type: 'string' },
|
|
11
|
+
address: { type: 'string' },
|
|
12
|
+
},
|
|
13
|
+
}, {
|
|
14
|
+
submitOrder: submitOrder,
|
|
15
|
+
cancelOrder: cancelOrderAction,
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=order-actions-with-credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order-actions-with-credential.js","sourceRoot":"","sources":["../src/order-actions-with-credential.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAExC,iCAAiC,CAC/B,QAAQ,EACR,aAAa,EACb;IACE,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC;IACpC,UAAU,EAAE;QACV,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC/B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAC5B;CACF,EACD;IACE,WAAW,EAAE,WAAW;IACxB,WAAW,EAAE,iBAAiB;CAC/B,CACF,CAAC","sourcesContent":["import { provideOrderActionsWithCredential } from '@yuants/data-order';\nimport { Terminal } from '@yuants/protocol';\nimport { ICredential } from './api/types';\nimport { cancelOrderAction } from './order-actions/cancelOrder';\nimport { submitOrder } from './order-actions/submitOrder';\n\nconst terminal = Terminal.fromNodeEnv();\n\nprovideOrderActionsWithCredential<ICredential>(\n terminal,\n 'HYPERLIQUID',\n {\n type: 'object',\n required: ['private_key', 'address'],\n properties: {\n private_key: { type: 'string' },\n address: { type: 'string' },\n },\n },\n {\n submitOrder: submitOrder,\n cancelOrder: cancelOrderAction,\n },\n);\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Terminal } from '@yuants/protocol';
|
|
2
|
+
import { defaultPerpAccountId } from './account';
|
|
3
|
+
import { getDefaultCredential } from './api/types';
|
|
4
|
+
import { cancelOrderAction } from './order-actions/cancelOrder';
|
|
5
|
+
import { submitOrder } from './order-actions/submitOrder';
|
|
6
|
+
const terminal = Terminal.fromNodeEnv();
|
|
7
|
+
const credential = getDefaultCredential();
|
|
8
|
+
terminal.server.provideService('SubmitOrder', {
|
|
9
|
+
required: ['account_id', 'product_id', 'order_type', 'order_direction', 'volume'],
|
|
10
|
+
properties: {
|
|
11
|
+
account_id: { const: defaultPerpAccountId },
|
|
12
|
+
},
|
|
13
|
+
}, async (msg) => {
|
|
14
|
+
return {
|
|
15
|
+
res: {
|
|
16
|
+
code: 0,
|
|
17
|
+
message: 'OK',
|
|
18
|
+
data: await submitOrder(credential, msg.req),
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
terminal.server.provideService('CancelOrder', {
|
|
23
|
+
required: ['account_id', 'order_id', 'product_id'],
|
|
24
|
+
properties: {
|
|
25
|
+
account_id: { const: defaultPerpAccountId },
|
|
26
|
+
},
|
|
27
|
+
}, async (msg) => {
|
|
28
|
+
await cancelOrderAction(credential, msg.req);
|
|
29
|
+
return {
|
|
30
|
+
res: {
|
|
31
|
+
code: 0,
|
|
32
|
+
message: 'OK',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=order-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order-actions.js","sourceRoot":"","sources":["../src/order-actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AACxC,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAC;AAE1C,QAAQ,CAAC,MAAM,CAAC,cAAc,CAC5B,aAAa,EACb;IACE,QAAQ,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,QAAQ,CAAC;IACjF,UAAU,EAAE;QACV,UAAU,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE;KAC5C;CACF,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;IACZ,OAAO;QACL,GAAG,EAAE;YACH,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC;SAC7C;KACF,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,QAAQ,CAAC,MAAM,CAAC,cAAc,CAC5B,aAAa,EACb;IACE,QAAQ,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC;IAClD,UAAU,EAAE;QACV,UAAU,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE;KAC5C;CACF,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;IACZ,MAAM,iBAAiB,CAAC,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO;QACL,GAAG,EAAE;YACH,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,IAAI;SACd;KACF,CAAC;AACJ,CAAC,CACF,CAAC","sourcesContent":["import { IOrder } from '@yuants/data-order';\nimport { Terminal } from '@yuants/protocol';\nimport { defaultPerpAccountId } from './account';\nimport { getDefaultCredential } from './api/types';\nimport { cancelOrderAction } from './order-actions/cancelOrder';\nimport { submitOrder } from './order-actions/submitOrder';\n\nconst terminal = Terminal.fromNodeEnv();\nconst credential = getDefaultCredential();\n\nterminal.server.provideService<IOrder, { order_id?: string }>(\n 'SubmitOrder',\n {\n required: ['account_id', 'product_id', 'order_type', 'order_direction', 'volume'],\n properties: {\n account_id: { const: defaultPerpAccountId },\n },\n },\n async (msg) => {\n return {\n res: {\n code: 0,\n message: 'OK',\n data: await submitOrder(credential, msg.req),\n },\n };\n },\n);\n\nterminal.server.provideService<IOrder>(\n 'CancelOrder',\n {\n required: ['account_id', 'order_id', 'product_id'],\n properties: {\n account_id: { const: defaultPerpAccountId },\n },\n },\n async (msg) => {\n await cancelOrderAction(credential, msg.req);\n return {\n res: {\n code: 0,\n message: 'OK',\n },\n };\n },\n);\n"]}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { decodePath } from '@yuants/utils';
|
|
2
|
+
import { getAllMids, getPerpetualsMetaData, getSpotMetaData } from './api/public-api';
|
|
3
|
+
let perpMetaCache;
|
|
4
|
+
let spotMetaCache;
|
|
5
|
+
let midPriceCache;
|
|
6
|
+
const CACHE_TTL = 60000;
|
|
7
|
+
const MID_TTL = 5000;
|
|
8
|
+
const ensurePerpMeta = async () => {
|
|
9
|
+
if (!perpMetaCache || perpMetaCache.expires_at < Date.now()) {
|
|
10
|
+
const meta = await getPerpetualsMetaData();
|
|
11
|
+
const map = new Map();
|
|
12
|
+
meta.universe.forEach((token, index) => map.set(token.name, { assetId: index, szDecimals: token.szDecimals }));
|
|
13
|
+
perpMetaCache = { map, expires_at: Date.now() + CACHE_TTL };
|
|
14
|
+
}
|
|
15
|
+
return perpMetaCache.map;
|
|
16
|
+
};
|
|
17
|
+
const ensureSpotMeta = async () => {
|
|
18
|
+
if (!spotMetaCache || spotMetaCache.expires_at < Date.now()) {
|
|
19
|
+
const meta = await getSpotMetaData();
|
|
20
|
+
const map = new Map();
|
|
21
|
+
meta.tokens.forEach((token) => map.set(token.name, { assetId: token.index, szDecimals: token.szDecimals }));
|
|
22
|
+
spotMetaCache = { map, expires_at: Date.now() + CACHE_TTL };
|
|
23
|
+
}
|
|
24
|
+
return spotMetaCache.map;
|
|
25
|
+
};
|
|
26
|
+
const ensureMidPrices = async () => {
|
|
27
|
+
if (!midPriceCache || midPriceCache.expires_at < Date.now()) {
|
|
28
|
+
const mids = await getAllMids();
|
|
29
|
+
const map = new Map();
|
|
30
|
+
for (const [coin, price] of Object.entries(mids !== null && mids !== void 0 ? mids : {})) {
|
|
31
|
+
const value = Number(price);
|
|
32
|
+
if (Number.isFinite(value)) {
|
|
33
|
+
map.set(coin, value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
midPriceCache = { map, expires_at: Date.now() + MID_TTL };
|
|
37
|
+
}
|
|
38
|
+
return midPriceCache.map;
|
|
39
|
+
};
|
|
40
|
+
export const resolveAssetInfo = async (product_id) => {
|
|
41
|
+
const [instType, symbol] = decodePath(product_id);
|
|
42
|
+
if (!instType || !symbol) {
|
|
43
|
+
throw new Error(`Invalid product_id: ${product_id}`);
|
|
44
|
+
}
|
|
45
|
+
const baseCurrency = symbol.split('-')[0];
|
|
46
|
+
if (instType === "PERPETUAL" /* InstrumentType.PERPETUAL */) {
|
|
47
|
+
const map = await ensurePerpMeta();
|
|
48
|
+
const info = map.get(baseCurrency);
|
|
49
|
+
if (!info) {
|
|
50
|
+
throw new Error(`Unable to resolve Hyperliquid asset id for ${baseCurrency}`);
|
|
51
|
+
}
|
|
52
|
+
return Object.assign(Object.assign({}, info), { instType: "PERPETUAL" /* InstrumentType.PERPETUAL */, baseCurrency });
|
|
53
|
+
}
|
|
54
|
+
if (instType === "SPOT" /* InstrumentType.SPOT */) {
|
|
55
|
+
const map = await ensureSpotMeta();
|
|
56
|
+
const info = map.get(baseCurrency);
|
|
57
|
+
if (!info) {
|
|
58
|
+
throw new Error(`Unable to resolve Hyperliquid spot asset id for ${baseCurrency}`);
|
|
59
|
+
}
|
|
60
|
+
return Object.assign(Object.assign({}, info), { instType: "SPOT" /* InstrumentType.SPOT */, baseCurrency });
|
|
61
|
+
}
|
|
62
|
+
throw new Error(`Unsupported instrument type: ${instType}`);
|
|
63
|
+
};
|
|
64
|
+
export const roundPrice = (price, instType, szDecimals) => {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
const MAX_DECIMALS = instType === 'PERPETUAL' ? 6 : 8;
|
|
67
|
+
const maxDecimalPlaces = Math.max(0, MAX_DECIMALS - szDecimals);
|
|
68
|
+
if (!Number.isFinite(price)) {
|
|
69
|
+
throw new Error(`Invalid price: ${price}`);
|
|
70
|
+
}
|
|
71
|
+
if (Number.isInteger(price)) {
|
|
72
|
+
return price.toString();
|
|
73
|
+
}
|
|
74
|
+
const priceStr = price.toString();
|
|
75
|
+
const significantFigures = priceStr.replace(/^0+\.?0*/, '').replace(/\./g, '').length;
|
|
76
|
+
let roundedPrice = price;
|
|
77
|
+
if (significantFigures > 5) {
|
|
78
|
+
const decimalIndex = priceStr.indexOf('.');
|
|
79
|
+
if (decimalIndex === -1) {
|
|
80
|
+
const magnitude = Math.floor(Math.log10(Math.abs(price)));
|
|
81
|
+
const factor = Math.pow(10, magnitude - 4);
|
|
82
|
+
roundedPrice = Math.round(price / factor) * factor;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const beforeDecimal = priceStr.substring(0, decimalIndex);
|
|
86
|
+
const afterDecimal = priceStr.substring(decimalIndex + 1);
|
|
87
|
+
if (beforeDecimal !== '0') {
|
|
88
|
+
const integerDigits = beforeDecimal.replace('-', '').length;
|
|
89
|
+
const neededDecimalDigits = Math.max(0, 5 - integerDigits);
|
|
90
|
+
roundedPrice = parseFloat(price.toFixed(neededDecimalDigits));
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const leadingZeros = (_b = (_a = afterDecimal.match(/^0*/)) === null || _a === void 0 ? void 0 : _a[0].length) !== null && _b !== void 0 ? _b : 0;
|
|
94
|
+
const precision = leadingZeros + 5;
|
|
95
|
+
roundedPrice = parseFloat(price.toFixed(precision));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const finalPrice = parseFloat(roundedPrice.toFixed(maxDecimalPlaces));
|
|
100
|
+
return finalPrice.toString();
|
|
101
|
+
};
|
|
102
|
+
const resolvePrice = async (order, instType, szDecimals, baseCurrency) => {
|
|
103
|
+
if (order.order_type === 'MARKET') {
|
|
104
|
+
const mid = await getMidPriceWithSlippage(baseCurrency, order.order_direction === 'OPEN_LONG' || order.order_direction === 'CLOSE_SHORT');
|
|
105
|
+
return roundPrice(mid, instType, szDecimals);
|
|
106
|
+
}
|
|
107
|
+
if (!order.price) {
|
|
108
|
+
throw new Error('price is required for non-market orders');
|
|
109
|
+
}
|
|
110
|
+
return roundPrice(+order.price, instType, szDecimals);
|
|
111
|
+
};
|
|
112
|
+
export const buildOrderPayload = async (order) => {
|
|
113
|
+
const assetInfo = await resolveAssetInfo(order.product_id);
|
|
114
|
+
const isBuy = order.order_direction === 'OPEN_LONG' || order.order_direction === 'CLOSE_SHORT';
|
|
115
|
+
const reduceOnly = order.order_direction === 'CLOSE_LONG' || order.order_direction === 'CLOSE_SHORT';
|
|
116
|
+
const price = await resolvePrice(order, assetInfo.instType, assetInfo.szDecimals, assetInfo.baseCurrency);
|
|
117
|
+
const tif = order.order_type === 'MARKET' ? 'Ioc' : order.order_type === 'MAKER' ? 'Alo' : 'Gtc';
|
|
118
|
+
return {
|
|
119
|
+
assetInfo,
|
|
120
|
+
orderParams: {
|
|
121
|
+
a: assetInfo.assetId,
|
|
122
|
+
b: isBuy,
|
|
123
|
+
p: `${price}`,
|
|
124
|
+
s: `${order.volume}`,
|
|
125
|
+
r: reduceOnly,
|
|
126
|
+
t: { limit: { tif } },
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
export const getMidPriceWithSlippage = async (coin, isBuy) => {
|
|
131
|
+
const mids = await ensureMidPrices();
|
|
132
|
+
const mid = mids.get(coin);
|
|
133
|
+
if (!mid) {
|
|
134
|
+
throw new Error(`Unable to resolve Hyperliquid mid price for ${coin}`);
|
|
135
|
+
}
|
|
136
|
+
const slippage = isBuy ? 1.05 : 0.95;
|
|
137
|
+
return mid * slippage;
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=order-utils.js.map
|