@ostium/builder-sdk 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/README.md +589 -0
- package/dist/cli.js +6835 -0
- package/dist/index.cjs +5013 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1449 -0
- package/dist/index.d.ts +1449 -0
- package/dist/index.js +4988 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1449 @@
|
|
|
1
|
+
import { Hex, Address } from 'viem';
|
|
2
|
+
|
|
3
|
+
declare enum OrderType$1 {
|
|
4
|
+
Market = "market",
|
|
5
|
+
Limit = "limit",
|
|
6
|
+
Stop = "stop"
|
|
7
|
+
}
|
|
8
|
+
declare enum CancelOrderType {
|
|
9
|
+
Limit = "limit",
|
|
10
|
+
PendingOpen = "pendingOpen",
|
|
11
|
+
PendingClose = "pendingClose"
|
|
12
|
+
}
|
|
13
|
+
interface OpenTradeParams {
|
|
14
|
+
/** Trading pair index (e.g. 0 for BTC/USD). */
|
|
15
|
+
pairIndex: number;
|
|
16
|
+
/** true = long, false = short. */
|
|
17
|
+
buy: boolean;
|
|
18
|
+
/** Entry price as a decimal string (e.g. "65000.50"). */
|
|
19
|
+
price: string;
|
|
20
|
+
/** Collateral in USD as a decimal string (e.g. "100.00", minimum $5). */
|
|
21
|
+
collateral: string;
|
|
22
|
+
/** Leverage as a decimal string (e.g. "10" for 10×, max 100×). */
|
|
23
|
+
leverage: string;
|
|
24
|
+
/** Order type. */
|
|
25
|
+
type: OrderType$1;
|
|
26
|
+
/** Take profit price as a decimal string. Optional. */
|
|
27
|
+
takeProfit?: string;
|
|
28
|
+
/** Stop loss price as a decimal string. Optional. */
|
|
29
|
+
stopLoss?: string;
|
|
30
|
+
/** Per-trade slippage override in basis points. Overrides client default. */
|
|
31
|
+
slippage?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Mark the trade as a day trade. Must be `true` when the desired leverage
|
|
34
|
+
* exceeds `pair.overnightMaxLeverage` (and `overnightMaxLeverage > 0`).
|
|
35
|
+
* Day trades are automatically closed before market close if not manually
|
|
36
|
+
* closed beforehand. Defaults to `false`.
|
|
37
|
+
*/
|
|
38
|
+
isDayTrade?: boolean;
|
|
39
|
+
}
|
|
40
|
+
interface CloseTradeParams {
|
|
41
|
+
/**
|
|
42
|
+
* Trading pair id — same value as `Position.pairId` returned by `getOpenPositions`.
|
|
43
|
+
* Accepts both the numeric string (e.g. `"0"`) and a plain `number` for ergonomics.
|
|
44
|
+
*/
|
|
45
|
+
pairId: string | number;
|
|
46
|
+
/**
|
|
47
|
+
* Position index within the pair — same value as `Position.idx` returned by
|
|
48
|
+
* `getOpenPositions`. Identifies which of the trader's open positions to close.
|
|
49
|
+
*/
|
|
50
|
+
idx: number;
|
|
51
|
+
/** Current market price as a decimal string. */
|
|
52
|
+
price: string;
|
|
53
|
+
/** Percentage to close (1–100). */
|
|
54
|
+
closePercent: number;
|
|
55
|
+
/** Per-trade slippage override in basis points. */
|
|
56
|
+
slippage?: number;
|
|
57
|
+
/**
|
|
58
|
+
* When true, verifies USDC allowance covers the oracle fee before submitting.
|
|
59
|
+
* Skip by default if you know allowance is sufficient.
|
|
60
|
+
*/
|
|
61
|
+
checkAllowance?: boolean;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Cancel a pending limit order.
|
|
65
|
+
*/
|
|
66
|
+
interface CancelLimitOrderParams {
|
|
67
|
+
type: CancelOrderType.Limit;
|
|
68
|
+
/**
|
|
69
|
+
* Trading pair id — same value as `OpenOrder.pairId` returned by `getOpenOrders`.
|
|
70
|
+
* Accepts both the numeric string (e.g. `"0"`) and a plain `number`.
|
|
71
|
+
*/
|
|
72
|
+
pairId: string | number;
|
|
73
|
+
/**
|
|
74
|
+
* Limit order index within the pair — same value as `OpenOrder.idx` returned
|
|
75
|
+
* by `getOpenOrders`. Identifies which limit order to cancel.
|
|
76
|
+
*/
|
|
77
|
+
idx: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Cancel a timed-out market open order.
|
|
81
|
+
*/
|
|
82
|
+
interface CancelPendingOpenParams {
|
|
83
|
+
type: CancelOrderType.PendingOpen;
|
|
84
|
+
/** Market order ID from the original openTrade submission. */
|
|
85
|
+
orderId: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Cancel a timed-out market close order.
|
|
89
|
+
*/
|
|
90
|
+
interface CancelPendingCloseParams {
|
|
91
|
+
type: CancelOrderType.PendingClose;
|
|
92
|
+
/** Market order ID from the original closeTrade submission. */
|
|
93
|
+
orderId: number;
|
|
94
|
+
/**
|
|
95
|
+
* If true, re-submits the close order after cancelling the timed-out one.
|
|
96
|
+
* Defaults to false (cancel only, trade remains open).
|
|
97
|
+
*/
|
|
98
|
+
retry?: boolean;
|
|
99
|
+
}
|
|
100
|
+
type CancelOrderParams = CancelLimitOrderParams | CancelPendingOpenParams | CancelPendingCloseParams;
|
|
101
|
+
interface ModifyOrderParams {
|
|
102
|
+
/**
|
|
103
|
+
* Trading pair id.
|
|
104
|
+
* - Updating TP/SL on an open position → use `Position.pairId` from `getOpenPositions`.
|
|
105
|
+
* - Updating a limit order's trigger price → use `OpenOrder.pairId` from `getOpenOrders`.
|
|
106
|
+
* Accepts both the numeric string (e.g. `"0"`) and a plain `number`.
|
|
107
|
+
*/
|
|
108
|
+
pairId: string | number;
|
|
109
|
+
/**
|
|
110
|
+
* Slot index within the pair.
|
|
111
|
+
* - Updating TP/SL on an open position → use `Position.idx`.
|
|
112
|
+
* - Updating a limit order → use `OpenOrder.idx`.
|
|
113
|
+
*/
|
|
114
|
+
idx: number;
|
|
115
|
+
/** New limit-order trigger price. Required when modifying a limit order's price. */
|
|
116
|
+
price?: string;
|
|
117
|
+
/** New take profit price. */
|
|
118
|
+
takeProfit?: string;
|
|
119
|
+
/** New stop loss price. */
|
|
120
|
+
stopLoss?: string;
|
|
121
|
+
}
|
|
122
|
+
interface UpdateCollateralParams {
|
|
123
|
+
/**
|
|
124
|
+
* Trading pair id — same value as `Position.pairId` returned by `getOpenPositions`.
|
|
125
|
+
* Accepts both the numeric string (e.g. `"0"`) and a plain `number`.
|
|
126
|
+
*/
|
|
127
|
+
pairId: string | number;
|
|
128
|
+
/**
|
|
129
|
+
* Position index within the pair — same value as `Position.idx` returned by
|
|
130
|
+
* `getOpenPositions`. Identifies which position to top up or partially withdraw from.
|
|
131
|
+
*/
|
|
132
|
+
idx: number;
|
|
133
|
+
/**
|
|
134
|
+
* Amount in USD as a decimal string.
|
|
135
|
+
* Positive → add collateral (topUpCollateral).
|
|
136
|
+
* Negative → remove collateral (removeCollateral).
|
|
137
|
+
*/
|
|
138
|
+
amount: string;
|
|
139
|
+
}
|
|
140
|
+
interface Balances {
|
|
141
|
+
/** USDC balance as a decimal string (e.g. `"1234.567890"`). */
|
|
142
|
+
usdc: string;
|
|
143
|
+
/** ETH balance as a decimal string (e.g. `"0.001234567890123456789"`). */
|
|
144
|
+
eth: string;
|
|
145
|
+
/** USDC allowance granted to the TradingStorage contract as a decimal string. Max approval is preserved exactly. */
|
|
146
|
+
allowance: string;
|
|
147
|
+
}
|
|
148
|
+
interface AllowanceStatus {
|
|
149
|
+
/** Current USDC allowance (6 decimals, raw bigint). */
|
|
150
|
+
current: bigint;
|
|
151
|
+
/** Required USDC allowance (6 decimals, raw bigint). */
|
|
152
|
+
required: bigint;
|
|
153
|
+
/** true if current >= required. */
|
|
154
|
+
sufficient: boolean;
|
|
155
|
+
}
|
|
156
|
+
interface SubmissionResult {
|
|
157
|
+
txHash: Hex;
|
|
158
|
+
/** Set for gasless submissions — the Safe smart account address that sent the UserOp. */
|
|
159
|
+
smartAccountAddress?: Address;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Shared optional settings available in every mode. */
|
|
163
|
+
interface CommonParams {
|
|
164
|
+
/** Use Arbitrum Sepolia testnet. Defaults to false (mainnet). */
|
|
165
|
+
testnet?: boolean;
|
|
166
|
+
/** Default slippage tolerance in basis points (e.g. 25 = 0.25%). Defaults to 25. */
|
|
167
|
+
slippageBps?: number;
|
|
168
|
+
/**
|
|
169
|
+
* Optional builder fee sharing.
|
|
170
|
+
* `feeBps` is in basis points — max 50 (0.5%).
|
|
171
|
+
*/
|
|
172
|
+
builder?: {
|
|
173
|
+
address: Address;
|
|
174
|
+
feeBps: number;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Override the Ostium subgraph endpoint used by built-in read methods
|
|
178
|
+
* (`getPairs`, `getOpenPositions`, etc.). Defaults to the mainnet or testnet
|
|
179
|
+
* subgraph based on `testnet`.
|
|
180
|
+
*/
|
|
181
|
+
subgraphUrl?: string;
|
|
182
|
+
/**
|
|
183
|
+
* Override the builder API base URL used for live prices, OHLC candles, and
|
|
184
|
+
* the WebSocket stream. Defaults to `https://builder.ostium.io`.
|
|
185
|
+
*/
|
|
186
|
+
builderApiUrl?: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* **Self + Self** — simplest mode.
|
|
190
|
+
*
|
|
191
|
+
* Your EOA is the trader: it holds USDC, owns all positions, and pays gas
|
|
192
|
+
* for every transaction directly.
|
|
193
|
+
*
|
|
194
|
+
* ```ts
|
|
195
|
+
* const client = await OstiumClient.createSelfAndSelf({
|
|
196
|
+
* traderPrivateKey: '0x...',
|
|
197
|
+
* rpcUrl: 'https://arb-mainnet.g.alchemy.com/v2/...',
|
|
198
|
+
* });
|
|
199
|
+
* await client.openTrade({ ... });
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
interface SelfSelfParams extends CommonParams {
|
|
203
|
+
/** Private key of the trader's EOA. This account holds USDC, owns all positions, and pays gas. */
|
|
204
|
+
traderPrivateKey: Hex;
|
|
205
|
+
/** Arbitrum One (or Sepolia) RPC URL. */
|
|
206
|
+
rpcUrl: string;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* **Self + Gasless** — your EOA owns everything; a Safe acts as a transparent gasless relay.
|
|
210
|
+
*
|
|
211
|
+
* Your EOA holds USDC and owns all positions. A Safe smart account is derived
|
|
212
|
+
* deterministically from your private key and registered as your delegate.
|
|
213
|
+
* After a one-time setup (approve USDC + register Safe via `setupGaslessDelegation()`),
|
|
214
|
+
* all subsequent trades are submitted as sponsored UserOperations — no ETH needed.
|
|
215
|
+
*
|
|
216
|
+
* ```ts
|
|
217
|
+
* const client = await OstiumClient.createSelfAndGasless({
|
|
218
|
+
* traderPrivateKey: '0x...',
|
|
219
|
+
* pimlicoUrl: 'https://builder.ostium.io/v1/pimlico/sponsor?chainId=42161',
|
|
220
|
+
* });
|
|
221
|
+
* // One-time setup (EOA pays gas once for each):
|
|
222
|
+
* await client.approveUsdc('max');
|
|
223
|
+
* await client.setupGaslessDelegation();
|
|
224
|
+
* // All subsequent trading is free:
|
|
225
|
+
* await client.openTrade({ ... });
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
interface SelfGaslessParams extends CommonParams {
|
|
229
|
+
/** Private key of the trader's EOA. This account holds USDC and owns all positions. A Safe is derived from this key to relay trades gaslessly. */
|
|
230
|
+
traderPrivateKey: Hex;
|
|
231
|
+
/** Pimlico-compatible bundler/paymaster RPC URL. Defaults to `https://builder.ostium.io/v1/pimlico/sponsor?chainId=42161`. */
|
|
232
|
+
pimlicoUrl?: string;
|
|
233
|
+
/** Arbitrum RPC URL for reads/simulation. Defaults to public Arbitrum RPC when omitted. */
|
|
234
|
+
rpcUrl?: string;
|
|
235
|
+
/** Pimlico sponsorship policy ID. */
|
|
236
|
+
sponsorshipPolicyId?: string;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* **Delegated + Self** — a dedicated delegate EOA signs and pays gas on behalf of a separate trader address.
|
|
240
|
+
*
|
|
241
|
+
* The trader account keeps custody of USDC and positions. The delegate account
|
|
242
|
+
* only needs ETH for gas. The trader must have called `setDelegate(delegateAddress)`
|
|
243
|
+
* on the trading contract before this client can submit trades.
|
|
244
|
+
*
|
|
245
|
+
* ```ts
|
|
246
|
+
* const client = await OstiumClient.createDelegatedAndSelf({
|
|
247
|
+
* delegatePrivateKey: '0xDelegateKey',
|
|
248
|
+
* traderAddress: '0xTraderAddress',
|
|
249
|
+
* rpcUrl: 'https://arb-mainnet.g.alchemy.com/v2/...',
|
|
250
|
+
* });
|
|
251
|
+
* await client.openTrade({ ... }); // submitted as delegatedAction(traderAddress, ...)
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
interface DelegatedSelfParams extends CommonParams {
|
|
255
|
+
/** Private key of the delegate EOA. This account signs and pays gas for all transactions. */
|
|
256
|
+
delegatePrivateKey: Hex;
|
|
257
|
+
/**
|
|
258
|
+
* Address of the trader this delegate acts for.
|
|
259
|
+
* The trader must have called `setDelegate(delegateAddress)` on the trading contract.
|
|
260
|
+
*/
|
|
261
|
+
traderAddress: Address;
|
|
262
|
+
/** Arbitrum One (or Sepolia) RPC URL. */
|
|
263
|
+
rpcUrl: string;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* **Delegated + Gasless** — a Safe derived from the delegate key submits sponsored UserOperations on behalf of the trader.
|
|
267
|
+
*
|
|
268
|
+
* The trader keeps custody of USDC and positions. The delegate's Safe submits
|
|
269
|
+
* trades as UserOperations via Pimlico — no ETH needed after the trader calls
|
|
270
|
+
* `setDelegate(safeAddress)` once.
|
|
271
|
+
*
|
|
272
|
+
* ```ts
|
|
273
|
+
* const client = await OstiumClient.createDelegatedAndGasless({
|
|
274
|
+
* delegatePrivateKey: '0xDelegateKey',
|
|
275
|
+
* traderAddress: '0xTraderAddress',
|
|
276
|
+
* pimlicoUrl: 'https://builder.ostium.io/v1/pimlico/sponsor?chainId=42161',
|
|
277
|
+
* });
|
|
278
|
+
* await client.openTrade({ ... }); // submitted as sponsored delegatedAction UserOp
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
interface DelegatedGaslessParams extends CommonParams {
|
|
282
|
+
/** Private key of the delegate EOA. A Safe smart account is derived from this key and submits UserOperations via Pimlico. */
|
|
283
|
+
delegatePrivateKey: Hex;
|
|
284
|
+
/**
|
|
285
|
+
* Address of the trader this delegate acts for.
|
|
286
|
+
* The trader must have called `setDelegate(safeAddress)` on the trading contract,
|
|
287
|
+
* where `safeAddress` is the Safe derived from `delegatePrivateKey`.
|
|
288
|
+
* Use `client.getSmartAccountAddress()` to retrieve this address.
|
|
289
|
+
*/
|
|
290
|
+
traderAddress: Address;
|
|
291
|
+
/** Pimlico-compatible bundler/paymaster RPC URL. Defaults to `https://builder.ostium.io/v1/pimlico/sponsor?chainId=42161`. */
|
|
292
|
+
pimlicoUrl?: string;
|
|
293
|
+
/** Arbitrum RPC URL for reads/simulation. Defaults to public Arbitrum RPC when omitted. */
|
|
294
|
+
rpcUrl?: string;
|
|
295
|
+
/** Pimlico sponsorship policy ID. */
|
|
296
|
+
sponsorshipPolicyId?: string;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Generic config object used by the legacy `OstiumClient.create()` method.
|
|
300
|
+
* Prefer the named constructors (`createSelfAndSelf`, `createSelfAndGasless`,
|
|
301
|
+
* `createDelegatedAndSelf`, `createDelegatedAndGasless`) for clearer intent.
|
|
302
|
+
*
|
|
303
|
+
* The SDK infers the operational mode from the shape of this object:
|
|
304
|
+
*
|
|
305
|
+
* | `traderAddress` | `pimlicoUrl` | Mode |
|
|
306
|
+
* |:---:|:---:|:---|
|
|
307
|
+
* | ✓ | ✓ | Delegated + Gasless |
|
|
308
|
+
* | ✓ | — | Delegated + Self |
|
|
309
|
+
* | — | ✓ | Self + Gasless |
|
|
310
|
+
* | — | — | Self + Self |
|
|
311
|
+
*/
|
|
312
|
+
interface OstiumClientConfig {
|
|
313
|
+
privateKey: Hex;
|
|
314
|
+
traderAddress?: Address;
|
|
315
|
+
rpcUrl?: string;
|
|
316
|
+
pimlicoUrl?: string;
|
|
317
|
+
sponsorshipPolicyId?: string;
|
|
318
|
+
testnet?: boolean;
|
|
319
|
+
builder?: {
|
|
320
|
+
address: Address;
|
|
321
|
+
feeBps: number;
|
|
322
|
+
};
|
|
323
|
+
slippageBps?: number;
|
|
324
|
+
subgraphUrl?: string;
|
|
325
|
+
builderApiUrl?: string;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/** Mainnet (Arbitrum One) Ostium subgraph endpoint. */
|
|
329
|
+
declare const DEFAULT_SUBGRAPH_ENDPOINT = "https://api.subgraph.ormilabs.com/api/public/67a599d5-c8d2-4cc4-9c4d-2975a97bc5d8/subgraphs/ost-prod/live/gn";
|
|
330
|
+
/** Testnet (Arbitrum Sepolia) Ostium subgraph endpoint. */
|
|
331
|
+
declare const DEFAULT_SUBGRAPH_ENDPOINT_TESTNET = "https://api.subgraph.ormilabs.com/api/public/67a599d5-c8d2-4cc4-9c4d-2975a97bc5d8/subgraphs/ost-sep/live/gn";
|
|
332
|
+
/** Default Ostium builder API base URL (prices, OHLC, WebSocket stream). */
|
|
333
|
+
declare const DEFAULT_BUILDER_API_URL = "https://builder.ostium.io";
|
|
334
|
+
/**
|
|
335
|
+
* Configuration for {@link OstiumSubgraphClient}.
|
|
336
|
+
*
|
|
337
|
+
* All fields are optional — calling `OstiumSubgraphClient.create()` with no
|
|
338
|
+
* arguments connects to the mainnet subgraph.
|
|
339
|
+
*
|
|
340
|
+
* ```ts
|
|
341
|
+
* // Mainnet (default)
|
|
342
|
+
* const client = OstiumSubgraphClient.create();
|
|
343
|
+
*
|
|
344
|
+
* // Testnet (Arbitrum Sepolia)
|
|
345
|
+
* const client = OstiumSubgraphClient.create({ testnet: true });
|
|
346
|
+
*
|
|
347
|
+
* // Custom endpoints
|
|
348
|
+
* const client = OstiumSubgraphClient.create({
|
|
349
|
+
* endpoint: 'https://my-subgraph.example.com/graphql',
|
|
350
|
+
* builderApiUrl: 'https://my-builder-api.example.com',
|
|
351
|
+
* });
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
interface OstiumSubgraphClientConfig {
|
|
355
|
+
/**
|
|
356
|
+
* Subgraph GraphQL endpoint.
|
|
357
|
+
* When omitted, defaults to the mainnet or testnet subgraph based on `testnet`.
|
|
358
|
+
*/
|
|
359
|
+
endpoint?: string;
|
|
360
|
+
/**
|
|
361
|
+
* Use the Arbitrum Sepolia testnet subgraph.
|
|
362
|
+
* Ignored when `endpoint` is set explicitly. Defaults to false (mainnet).
|
|
363
|
+
*/
|
|
364
|
+
testnet?: boolean;
|
|
365
|
+
/**
|
|
366
|
+
* Override the builder API base URL used for live prices, OHLC candles, and the
|
|
367
|
+
* WebSocket stream. Defaults to `https://builder.ostium.io`.
|
|
368
|
+
*/
|
|
369
|
+
builderApiUrl?: string;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
interface Pair {
|
|
373
|
+
/** Numeric string pair identifier (e.g. `"0"` for BTC/USD). Use this as `pairId` everywhere in the SDK. */
|
|
374
|
+
pairId: string;
|
|
375
|
+
/** Normalized quote-asset display name (e.g. `"USD"`). */
|
|
376
|
+
pairTo: string;
|
|
377
|
+
/** Normalized base-asset display name (e.g. `"BTC"`, `"WTI"` for raw `"CL"`). */
|
|
378
|
+
pairFrom: string;
|
|
379
|
+
/** Minimum trade size in base-asset units (`5 / mid`). */
|
|
380
|
+
minSz: string;
|
|
381
|
+
/** Max long size in base-asset units = `(maxOI − buyOI) / mid`. Zero when the long side is at capacity. */
|
|
382
|
+
maxBSz: string;
|
|
383
|
+
/** Max short size in base-asset units = `(maxOI − sellOI) / mid`. Zero when the short side is at capacity. */
|
|
384
|
+
maxSSz: string;
|
|
385
|
+
/** Minimum notional in USD — currently `"5.0"`. */
|
|
386
|
+
minNtl: string;
|
|
387
|
+
/** Maximum leverage for this pair (takes the tighter of pair-level and group-level caps). */
|
|
388
|
+
maxLeverage: number;
|
|
389
|
+
/**
|
|
390
|
+
* Max leverage allowed for overnight positions. `0` means no overnight restriction.
|
|
391
|
+
* When `overnightMaxLeverage > 0` and `trade.leverage > overnightMaxLeverage`,
|
|
392
|
+
* the trade must set `isDayTrade: true` and will be auto-closed before market close.
|
|
393
|
+
*/
|
|
394
|
+
overnightMaxLeverage: number;
|
|
395
|
+
/** Per-block rollover fee for this pair (formatted from `lastRolloverLongPure`). */
|
|
396
|
+
rolloverFeePerBlock: string;
|
|
397
|
+
/** `buyOpenInterest + sellOpenInterest` (USD). */
|
|
398
|
+
openInterest: string;
|
|
399
|
+
/** Current long open interest in USD. */
|
|
400
|
+
buyOpenInterest: string;
|
|
401
|
+
/** Current short open interest in USD. */
|
|
402
|
+
sellOpenInterest: string;
|
|
403
|
+
/** Maximum total open interest allowed for this pair in USD. */
|
|
404
|
+
maxOpenInterest: string;
|
|
405
|
+
/** Group name (e.g. `"crypto"`, `"forex"`). */
|
|
406
|
+
category: string;
|
|
407
|
+
/** 8-hour rollover rate as a percentage, separated by side. Negative = trader earns, positive = trader pays. */
|
|
408
|
+
rolloverRate: {
|
|
409
|
+
long: string;
|
|
410
|
+
short: string;
|
|
411
|
+
};
|
|
412
|
+
/** Current mid price (average of bid and ask). */
|
|
413
|
+
midPx: string;
|
|
414
|
+
/** Current ask price (long entries execute at or above this). */
|
|
415
|
+
askPx: string;
|
|
416
|
+
/** Current bid price (short entries execute at or below this). */
|
|
417
|
+
bidPx: string;
|
|
418
|
+
/** Whether the market is currently open for trading. */
|
|
419
|
+
isMarketOpen: boolean;
|
|
420
|
+
/** Whether intra-day trading is currently closed for this pair. */
|
|
421
|
+
isDayTradingClosed: boolean;
|
|
422
|
+
/** Seconds until `isDayTradingClosed` flips. `-1` when not applicable. */
|
|
423
|
+
secondsToToggleIsDayTradingClosed: number;
|
|
424
|
+
}
|
|
425
|
+
interface PairsResponse {
|
|
426
|
+
pairs: Pair[];
|
|
427
|
+
}
|
|
428
|
+
/** Live price snapshot for a pair (bid/mid/ask as plain numbers). */
|
|
429
|
+
interface PriceData {
|
|
430
|
+
mid: number;
|
|
431
|
+
bid: number;
|
|
432
|
+
ask: number;
|
|
433
|
+
isMarketOpen: boolean;
|
|
434
|
+
isDayTradingClosed: boolean;
|
|
435
|
+
/** Seconds until `isDayTradingClosed` flips. `-1` when not applicable. */
|
|
436
|
+
secondsToToggleIsDayTradingClosed: number;
|
|
437
|
+
}
|
|
438
|
+
interface AllPricesResponse {
|
|
439
|
+
/** Live prices keyed by pair id (string). */
|
|
440
|
+
prices: Record<string, {
|
|
441
|
+
ask: string;
|
|
442
|
+
bid: string;
|
|
443
|
+
mid: string;
|
|
444
|
+
}>;
|
|
445
|
+
}
|
|
446
|
+
interface Position {
|
|
447
|
+
pairTo: string;
|
|
448
|
+
pairFrom: string;
|
|
449
|
+
pairId: string;
|
|
450
|
+
/** Position id from the subgraph (numeric string — same as `Fill.pid`). */
|
|
451
|
+
pid: string;
|
|
452
|
+
/** Position index — the trader's per-pair slot for this position. */
|
|
453
|
+
idx: number;
|
|
454
|
+
/** `"B"` for LONG, `"S"` for SHORT. */
|
|
455
|
+
side: 'B' | 'S';
|
|
456
|
+
/** Position size in base-asset units (use `side` for direction). */
|
|
457
|
+
szi: string;
|
|
458
|
+
/** Price at which the position was opened (USD). */
|
|
459
|
+
entryPx: string;
|
|
460
|
+
/** Current effective leverage as a decimal string (e.g. `"10"`). */
|
|
461
|
+
leverage: string;
|
|
462
|
+
/** Current notional in USD (`size × midPrice`). */
|
|
463
|
+
ntl: string;
|
|
464
|
+
/** Net PnL after rollover, in USD. */
|
|
465
|
+
unrealizedPnl: string;
|
|
466
|
+
/** `unrealizedPnl / collateralUsed`. */
|
|
467
|
+
returnOnEquity: string;
|
|
468
|
+
/** Estimated price at which this position would be liquidated given current rollover. */
|
|
469
|
+
liquidationPx: string;
|
|
470
|
+
/** Collateral locked in this position (USD). */
|
|
471
|
+
collateralUsed: string;
|
|
472
|
+
/** Rollover fee accrued for this trade since it was opened, in USD. */
|
|
473
|
+
cumRollover: string;
|
|
474
|
+
/** Take-profit price, when set on this position. */
|
|
475
|
+
tpPx?: string;
|
|
476
|
+
/** Stop-loss price, when set on this position. */
|
|
477
|
+
slPx?: string;
|
|
478
|
+
/** Open timestamp (Unix milliseconds). */
|
|
479
|
+
openTimestamp: number;
|
|
480
|
+
/** Whether this position was opened as a day trade (auto-closes before market close). */
|
|
481
|
+
isDayTrade: boolean;
|
|
482
|
+
/** Max leverage for the trade/pair/group **/
|
|
483
|
+
maxLeverage: string;
|
|
484
|
+
}
|
|
485
|
+
interface PairPosition {
|
|
486
|
+
position: Position;
|
|
487
|
+
/** Max collateral removable from this position without breaching min leverage, in USD. */
|
|
488
|
+
maxWithdrawable: string;
|
|
489
|
+
}
|
|
490
|
+
interface MarginSummary {
|
|
491
|
+
/** Sum of `(collateral + netPnl)` across all open positions (USD). */
|
|
492
|
+
accountValue: string;
|
|
493
|
+
/** Sum of collateral deposited across all open positions (USD). */
|
|
494
|
+
totalCollateralUsed: string;
|
|
495
|
+
/** Sum of current notional values across all open positions (USD). */
|
|
496
|
+
totalNtlPos: string;
|
|
497
|
+
/** Sum of unrealized PnL (after rollover) across all open positions (USD). */
|
|
498
|
+
totalRawPnlUsd: string;
|
|
499
|
+
}
|
|
500
|
+
interface OpenPositionsResponse {
|
|
501
|
+
/** All open positions for the requested trader, sorted newest first. */
|
|
502
|
+
pairPositions: PairPosition[];
|
|
503
|
+
/** Aggregated margin metrics across all open positions. */
|
|
504
|
+
marginSummary: MarginSummary;
|
|
505
|
+
/**
|
|
506
|
+
* Sum of per-position max-removable collateral, computed from the leverage
|
|
507
|
+
* constraint: `collateral × (1 − currentLeverage / maxLeverage)`.
|
|
508
|
+
*/
|
|
509
|
+
withdrawable: string;
|
|
510
|
+
/** Server time (Unix milliseconds). */
|
|
511
|
+
time: number;
|
|
512
|
+
}
|
|
513
|
+
/** Possible `orderAction` values returned by the subgraph for a fill. */
|
|
514
|
+
type OrderAction = 'Open' | 'Close' | 'Liquidation' | 'StopLoss' | 'TakeProfit' | 'RemoveCollateral' | 'CloseDayTrade';
|
|
515
|
+
/** Possible `orderType` values returned by the subgraph for a fill. */
|
|
516
|
+
type OrderType = 'Market' | 'Limit' | 'REMOVE_COLLATERAL';
|
|
517
|
+
interface FillFees {
|
|
518
|
+
/** Opening fee (devFee + vaultFee) — only on `Open` actions, else `"0"`. */
|
|
519
|
+
opening: string;
|
|
520
|
+
/** Rollover fee — on `Close`, `StopLoss`, `TakeProfit`, and `CloseDayTrade` actions, else `"0"`. */
|
|
521
|
+
rollover: string;
|
|
522
|
+
/** Liquidation fee — only on `Liquidation` actions, else `"0"`. */
|
|
523
|
+
liquidation: string;
|
|
524
|
+
/** Builder fee — when the order was routed via a builder. */
|
|
525
|
+
builder: string;
|
|
526
|
+
/** Estimated price impact cost. */
|
|
527
|
+
priceImpact: string;
|
|
528
|
+
}
|
|
529
|
+
interface Fill {
|
|
530
|
+
/** Normalized quote-asset display name (e.g. `"USD"`). */
|
|
531
|
+
pairTo: string;
|
|
532
|
+
/** Normalized base-asset display name (e.g. `"BTC"`). */
|
|
533
|
+
pairFrom: string;
|
|
534
|
+
/** Numeric string pair identifier — same as `Pair.pairId`. */
|
|
535
|
+
pairId: string;
|
|
536
|
+
/** Order id from the subgraph (composite, hex). */
|
|
537
|
+
oid: string;
|
|
538
|
+
/** Position id from the subgraph (numeric string — same as `Position.pid`). */
|
|
539
|
+
pid: string;
|
|
540
|
+
/** `"B"` for LONG, `"S"` for SHORT. */
|
|
541
|
+
side: 'B' | 'S';
|
|
542
|
+
/**
|
|
543
|
+
* Subgraph `orderAction` — passes through verbatim. Examples: `"Open"`, `"Close"`,
|
|
544
|
+
* `"Liquidation"`, `"StopLoss"`, `"TakeProfit"`, `"RemoveCollateral"`, `"CloseDayTrade"`.
|
|
545
|
+
*/
|
|
546
|
+
action: OrderAction;
|
|
547
|
+
/** Subgraph `orderType` — passes through verbatim. Examples: `"Market"`, `"Limit"`, `"REMOVE_COLLATERAL"`. */
|
|
548
|
+
type: OrderType;
|
|
549
|
+
/** Execution price after dynamic spread impact. */
|
|
550
|
+
px: string;
|
|
551
|
+
/** Trade size in base-asset units at the time of execution. */
|
|
552
|
+
szi: string;
|
|
553
|
+
/** Collateral on the underlying position at the time of the fill (USD). */
|
|
554
|
+
collateralUsed: string;
|
|
555
|
+
fees: FillFees;
|
|
556
|
+
/**
|
|
557
|
+
* Net realized PnL in USD for close actions (`Close`, `StopLoss`, `TakeProfit`,
|
|
558
|
+
* `CloseDayTrade`, `Liquidation`) after subtracting opening fee, oracle fee, and
|
|
559
|
+
* rollover. `"0"` for `Open` and `RemoveCollateral` actions.
|
|
560
|
+
*/
|
|
561
|
+
closedPnl: string;
|
|
562
|
+
/** Execution transaction hash. Empty string for pending orders. */
|
|
563
|
+
hash: string;
|
|
564
|
+
/** Execution time (Unix milliseconds). */
|
|
565
|
+
time: number;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* An order at any stage — pending, executed, or cancelled. Extends `Fill` with
|
|
569
|
+
* initiation metadata and status flags. Poll with `getOrders({ initiatedTxHashes:
|
|
570
|
+
* [txHash] })` using the hash from `SubmissionResult.txHash`, or with `orderIds`.
|
|
571
|
+
*/
|
|
572
|
+
interface Order extends Fill {
|
|
573
|
+
/** Transaction that initiated this order. */
|
|
574
|
+
initiatedTx: string;
|
|
575
|
+
/** Initiation time (Unix milliseconds). */
|
|
576
|
+
initiatedTime: number;
|
|
577
|
+
/** True while the oracle callback has not yet been processed. */
|
|
578
|
+
isPending: boolean;
|
|
579
|
+
/** True when the order was cancelled (timeout, slippage, or manual cancel). */
|
|
580
|
+
isCancelled: boolean;
|
|
581
|
+
/** Reason for cancellation, when `isCancelled` is true. */
|
|
582
|
+
cancelReason?: string;
|
|
583
|
+
}
|
|
584
|
+
interface OpenOrder {
|
|
585
|
+
/** Normalized quote-asset display name (e.g. `"USD"`). */
|
|
586
|
+
pairTo: string;
|
|
587
|
+
/** Normalized base-asset display name (e.g. `"BTC"`). */
|
|
588
|
+
pairFrom: string;
|
|
589
|
+
/** Numeric string pair identifier — same as `Pair.pairId`. */
|
|
590
|
+
pairId: string;
|
|
591
|
+
/**
|
|
592
|
+
* Limit-order slot index within the pair. Pass to `cancelOrder` /
|
|
593
|
+
* `modifyOrder` together with `pairId` to target this limit on-chain.
|
|
594
|
+
*/
|
|
595
|
+
idx: number;
|
|
596
|
+
/** `"B"` for LONG, `"S"` for SHORT. */
|
|
597
|
+
side: 'B' | 'S';
|
|
598
|
+
/** Trigger price — the order executes when the market reaches this level. */
|
|
599
|
+
limitPx: string;
|
|
600
|
+
/** Order size in base-asset units. */
|
|
601
|
+
szi: string;
|
|
602
|
+
/** Normalized order type: `"Limit"` | `"Stop"`. */
|
|
603
|
+
orderType: string;
|
|
604
|
+
/** Take-profit price, when set on this limit order. */
|
|
605
|
+
tpPx?: string;
|
|
606
|
+
/** Stop-loss price, when set on this limit order. */
|
|
607
|
+
slPx?: string;
|
|
608
|
+
/** Initiation time (Unix milliseconds). */
|
|
609
|
+
timestamp: number;
|
|
610
|
+
}
|
|
611
|
+
interface GetOrdersParams {
|
|
612
|
+
/**
|
|
613
|
+
* On-chain order ids to fetch. When provided, fetches
|
|
614
|
+
* those specific orders regardless of pending/cancelled status.
|
|
615
|
+
* Mutually exclusive with `initiatedTxHashes`.
|
|
616
|
+
*/
|
|
617
|
+
orderIds?: Array<string | number>;
|
|
618
|
+
/**
|
|
619
|
+
* Initiating transaction hashes (`orders.initiatedTx` on the subgraph). Use with
|
|
620
|
+
* `SubmissionResult.txHash` to poll a trade you just submitted. Mutually exclusive
|
|
621
|
+
* with `orderIds`.
|
|
622
|
+
*/
|
|
623
|
+
initiatedTxHashes?: readonly Hex[];
|
|
624
|
+
/** Trader address. On `OstiumClient`, defaults to the connected trader. */
|
|
625
|
+
user?: Address;
|
|
626
|
+
/** Max orders to return. Defaults to `100`. */
|
|
627
|
+
limit?: number;
|
|
628
|
+
}
|
|
629
|
+
interface GetPairsParams {
|
|
630
|
+
/** Optional list of pair ids to return. Accepts numeric strings or numbers. When omitted, all pairs are returned. */
|
|
631
|
+
pairIds?: Array<string | number>;
|
|
632
|
+
}
|
|
633
|
+
interface GetUserParams {
|
|
634
|
+
user: Address;
|
|
635
|
+
}
|
|
636
|
+
interface GetOpenPositionsParams extends GetUserParams {
|
|
637
|
+
/** Current Arbitrum block number — required for live PnL. Auto-fetched on `OstiumClient`. */
|
|
638
|
+
blockNumber?: bigint;
|
|
639
|
+
}
|
|
640
|
+
/** Sentinel value for `getFills` / `getFillsByTime` to fetch every trader's fills. */
|
|
641
|
+
type AllTraders = 'ALL';
|
|
642
|
+
interface GetFillsParams {
|
|
643
|
+
/**
|
|
644
|
+
* Trader address — pass `'ALL'` to fetch fills across every trader (no
|
|
645
|
+
* trader filter).
|
|
646
|
+
*/
|
|
647
|
+
user: Address | AllTraders;
|
|
648
|
+
/**
|
|
649
|
+
* Optional pair filter — if provided, only fills on this pair are returned.
|
|
650
|
+
* Accepts the numeric string (e.g. `"0"`) or a plain `number`.
|
|
651
|
+
*/
|
|
652
|
+
pairId?: string | number;
|
|
653
|
+
/**
|
|
654
|
+
* Maximum number of fills to return. Defaults to `1000`.
|
|
655
|
+
* Pass `Infinity` (or any large number) to fetch every matching fill.
|
|
656
|
+
*/
|
|
657
|
+
limit?: number;
|
|
658
|
+
}
|
|
659
|
+
interface GetFillsByTimeParams extends GetFillsParams {
|
|
660
|
+
/** Inclusive lower bound (Unix milliseconds). */
|
|
661
|
+
startTime: number;
|
|
662
|
+
/** Inclusive upper bound (Unix milliseconds). Defaults to `Date.now()`. */
|
|
663
|
+
endTime?: number;
|
|
664
|
+
}
|
|
665
|
+
/** One simulated slippage row for a (pair, side, notional) tuple. */
|
|
666
|
+
interface SimSlippageRow {
|
|
667
|
+
/** Notional echoed from the input (USD). */
|
|
668
|
+
ntl: string;
|
|
669
|
+
/** Slippage as a percentage (e.g. `"0.5"` = 0.5 %). */
|
|
670
|
+
slippage: string;
|
|
671
|
+
}
|
|
672
|
+
/** Per-side simulated slippage for a single pair. */
|
|
673
|
+
interface SimSlippageForPair {
|
|
674
|
+
/** Slippage for long entries — capped to the long side's remaining OI capacity. */
|
|
675
|
+
long: SimSlippageRow[];
|
|
676
|
+
/** Slippage for short entries — capped to the short side's remaining OI capacity. */
|
|
677
|
+
short: SimSlippageRow[];
|
|
678
|
+
}
|
|
679
|
+
/** Simulated slippage results keyed by `pairId`. */
|
|
680
|
+
type SimSlippageByPairId = Record<string, SimSlippageForPair>;
|
|
681
|
+
interface GetSimSlippageParams {
|
|
682
|
+
/** Pair ids to simulate (e.g. `[0, "1", "10"]`). Strings or numbers — both accepted. */
|
|
683
|
+
pairIds: Array<string | number>;
|
|
684
|
+
/** Notional amounts in USD as strings (e.g. `["1000", "5000"]`). */
|
|
685
|
+
ntls: string[];
|
|
686
|
+
}
|
|
687
|
+
/** One synthetic orderbook level — matches Hyperliquid's L2 book level shape. */
|
|
688
|
+
interface SimOrderbookLevel {
|
|
689
|
+
/** Fill price after dynamic spread impact. */
|
|
690
|
+
px: string;
|
|
691
|
+
/** Size in base-asset units (`notional / px`). */
|
|
692
|
+
sz: string;
|
|
693
|
+
/** Number of orders at this level — always `1` for simulated levels. */
|
|
694
|
+
n: number;
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Synthetic bid/ask orderbook — matches Hyperliquid's `L2Book` response shape.
|
|
698
|
+
*
|
|
699
|
+
* - `levels[0]` — bids (short entries), best bid first (highest px → lowest impact).
|
|
700
|
+
* - `levels[1]` — asks (long entries), best ask first (lowest px → lowest impact).
|
|
701
|
+
*/
|
|
702
|
+
interface SimOrderbookResponse {
|
|
703
|
+
pairId: string;
|
|
704
|
+
pairFrom: string;
|
|
705
|
+
pairTo: string;
|
|
706
|
+
levels: [SimOrderbookLevel[], SimOrderbookLevel[]];
|
|
707
|
+
/** Response timestamp (Unix milliseconds). */
|
|
708
|
+
time: number;
|
|
709
|
+
}
|
|
710
|
+
interface GetSimOrderbookParams {
|
|
711
|
+
/** Pair id to simulate. Accepts the numeric string (e.g. `"0"`) or a plain `number`. */
|
|
712
|
+
pairId: string | number;
|
|
713
|
+
/**
|
|
714
|
+
* Maximum number of levels per side. Capped at 20. Defaults to 20.
|
|
715
|
+
* Notionals follow the `[1, 2, 3, 5] × 10ⁿ` exponential scale, stopping at
|
|
716
|
+
* the side's remaining OI capacity.
|
|
717
|
+
*/
|
|
718
|
+
levels?: number;
|
|
719
|
+
}
|
|
720
|
+
/** Live price tick received from the builder API price stream. */
|
|
721
|
+
interface PriceTick {
|
|
722
|
+
/** Upstream feed identifier. */
|
|
723
|
+
feedId: string;
|
|
724
|
+
/** Pair in `"BASE-QUOTE"` format (e.g. `"BTC-USD"`). */
|
|
725
|
+
pair: string;
|
|
726
|
+
/** Base asset symbol (e.g. `"BTC"`). */
|
|
727
|
+
from: string;
|
|
728
|
+
/** Quote asset symbol (e.g. `"USD"`). */
|
|
729
|
+
to: string;
|
|
730
|
+
/** Best bid price (short entries execute at or below this). */
|
|
731
|
+
bid: number;
|
|
732
|
+
/** Mid price (average of bid and ask). */
|
|
733
|
+
mid: number;
|
|
734
|
+
/** Best ask price (long entries execute at or above this). */
|
|
735
|
+
ask: number;
|
|
736
|
+
/** Whether the market is currently open for trading. */
|
|
737
|
+
isMarketOpen: boolean;
|
|
738
|
+
/** Whether intra-day trading is currently closed for this pair. */
|
|
739
|
+
isDayTradingClosed: boolean;
|
|
740
|
+
/** Seconds until `isDayTradingClosed` flips. `-1` when not applicable. */
|
|
741
|
+
secondsToToggleIsDayTradingClosed: number;
|
|
742
|
+
/** Tick timestamp (Unix seconds). */
|
|
743
|
+
timestampSeconds: number;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Candle resolution for `getCandles`.
|
|
747
|
+
* `"1"` = 1 min, `"5"` = 5 min, `"15"` = 15 min, `"60"` = 1 hr, `"240"` = 4 hr, `"1D"` = daily.
|
|
748
|
+
*/
|
|
749
|
+
type CandleResolution = '1' | '5' | '15' | '60' | '240' | '1D';
|
|
750
|
+
/** One OHLC candle returned by `getCandles`. */
|
|
751
|
+
interface Candle {
|
|
752
|
+
/** Normalized base-asset display name (e.g. `"WTI"` for raw `"CL"`). */
|
|
753
|
+
pairFrom: string;
|
|
754
|
+
/** Normalized quote-asset display name (e.g. `"USD"`). */
|
|
755
|
+
pairTo: string;
|
|
756
|
+
/** Candle open time (Unix milliseconds). */
|
|
757
|
+
time: number;
|
|
758
|
+
/** Opening price for the candle period (USD). */
|
|
759
|
+
open: number;
|
|
760
|
+
/** Highest price reached during the candle period (USD). */
|
|
761
|
+
high: number;
|
|
762
|
+
/** Lowest price reached during the candle period (USD). */
|
|
763
|
+
low: number;
|
|
764
|
+
/** Closing price at the end of the candle period (USD). */
|
|
765
|
+
close: number;
|
|
766
|
+
}
|
|
767
|
+
interface GetCandlesParams {
|
|
768
|
+
/**
|
|
769
|
+
* Pair id — same as `Pair.pairId` from `getPairs()`.
|
|
770
|
+
* Accepts both the numeric string (e.g. `"0"`) and a plain `number`.
|
|
771
|
+
*/
|
|
772
|
+
pairId: string | number;
|
|
773
|
+
/** Start time (Unix milliseconds). */
|
|
774
|
+
from: number;
|
|
775
|
+
/** End time (Unix milliseconds). Defaults to `Date.now()`. */
|
|
776
|
+
to?: number;
|
|
777
|
+
/** Candle width — `"1"` (1 min) through `"1D"` (daily). See {@link CandleResolution}. */
|
|
778
|
+
resolution: CandleResolution;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
type TickHandler = (tick: PriceTick) => void;
|
|
782
|
+
type SnapshotHandler = (ticks: PriceTick[]) => void;
|
|
783
|
+
/**
|
|
784
|
+
* WebSocket client for the Ostium live price stream.
|
|
785
|
+
*
|
|
786
|
+
* ```ts
|
|
787
|
+
* // Via OstiumClient / OstiumSubgraphClient (recommended — pairIds resolved automatically):
|
|
788
|
+
* const stream = client.streamPrices([0, 1]); // BTC and ETH by pairId
|
|
789
|
+
*
|
|
790
|
+
* stream.onSnapshot(ticks => console.log('snapshot:', ticks.length));
|
|
791
|
+
* stream.onTick(tick => console.log(tick.pair, tick.mid));
|
|
792
|
+
*
|
|
793
|
+
* stream.subscribe([2]); // add pair 2
|
|
794
|
+
* stream.unsubscribe([0]); // remove pair 0
|
|
795
|
+
* stream.close();
|
|
796
|
+
* ```
|
|
797
|
+
*
|
|
798
|
+
* The socket connects to `{builderApiUrl}/v1/prices/stream` — `https://` is
|
|
799
|
+
* automatically rewritten to `wss://` (and `http://` to `ws://`). When
|
|
800
|
+
* `streamPrices(pairIds)` is called with ids, the SDK sends
|
|
801
|
+
* `{ type: "subscribe", pairs: ["FROM-TO", ...] }` on `open` (same wire format
|
|
802
|
+
* as {@link OstiumPriceStream.subscribe}).
|
|
803
|
+
*
|
|
804
|
+
* `subscribe` / `unsubscribe` accept the same `pairId` values used everywhere
|
|
805
|
+
* else in the SDK. `PriceTick.pair` / `.from` / `.to` use normalized display
|
|
806
|
+
* names (e.g. `"UK100"` not `"FTSE"`).
|
|
807
|
+
*/
|
|
808
|
+
declare class OstiumPriceStream {
|
|
809
|
+
private readonly ws;
|
|
810
|
+
private readonly tickHandlers;
|
|
811
|
+
private readonly snapshotHandlers;
|
|
812
|
+
/** pairId (string) → raw "FROM-TO" name for the WS API. */
|
|
813
|
+
private readonly pairRawNameCache;
|
|
814
|
+
private constructor();
|
|
815
|
+
/**
|
|
816
|
+
* Open a WebSocket connection to the live price stream.
|
|
817
|
+
*
|
|
818
|
+
* Uses the `ws` package which correctly handles case-insensitive `Connection`
|
|
819
|
+
* header values (required for Cloudflare-proxied endpoints).
|
|
820
|
+
*
|
|
821
|
+
* @param builderApiUrl - Base URL (e.g. `"https://builder.ostium.io"`). The `http`/`https`
|
|
822
|
+
* scheme is automatically converted to `ws`/`wss`.
|
|
823
|
+
* @param rawPairs - Optional raw `"FROM-TO"` names (from
|
|
824
|
+
* `OstiumSubgraphClient.streamPrices` pairIds). Sent as
|
|
825
|
+
* `{ type: "subscribe", pairs }` after the socket opens.
|
|
826
|
+
* @param pairRawNameCache - pairId → raw name map; passed in by the subgraph client so
|
|
827
|
+
* `subscribe` / `unsubscribe` can accept pairIds.
|
|
828
|
+
*/
|
|
829
|
+
static connect(builderApiUrl: string, rawPairs?: string[], pairRawNameCache?: Map<string, string>): OstiumPriceStream;
|
|
830
|
+
/**
|
|
831
|
+
* Register a callback that fires on every incoming price tick.
|
|
832
|
+
* Returns an unsubscribe function.
|
|
833
|
+
*/
|
|
834
|
+
onTick(handler: TickHandler): () => void;
|
|
835
|
+
/**
|
|
836
|
+
* Register a callback that fires once with the full snapshot sent on connect.
|
|
837
|
+
* Returns an unsubscribe function.
|
|
838
|
+
*/
|
|
839
|
+
onSnapshot(handler: SnapshotHandler): () => void;
|
|
840
|
+
/** Register a one-time callback that fires when the connection is established. */
|
|
841
|
+
onOpen(handler: () => void): this;
|
|
842
|
+
/** Register an error callback. */
|
|
843
|
+
onError(handler: (event: Error) => void): this;
|
|
844
|
+
/** Register a callback that fires when the connection closes. */
|
|
845
|
+
onClose(handler: (code: number, reason: string) => void): this;
|
|
846
|
+
/**
|
|
847
|
+
* Add pairs to the active filter. Accepts the same `pairId` values used
|
|
848
|
+
* throughout the SDK (numeric string or number).
|
|
849
|
+
* Sends `{ type: "subscribe", pairs: [...rawNames] }` to the server.
|
|
850
|
+
*/
|
|
851
|
+
subscribe(pairIds: Array<string | number>): this;
|
|
852
|
+
/**
|
|
853
|
+
* Remove pairs from the active filter. Accepts the same `pairId` values used
|
|
854
|
+
* throughout the SDK.
|
|
855
|
+
* Sends `{ type: "unsubscribe", pairs: [...rawNames] }` to the server.
|
|
856
|
+
*/
|
|
857
|
+
unsubscribe(pairIds: Array<string | number>): this;
|
|
858
|
+
/** Close the WebSocket connection. */
|
|
859
|
+
close(): void;
|
|
860
|
+
/** Underlying WebSocket ready state (`0=CONNECTING`, `1=OPEN`, `2=CLOSING`, `3=CLOSED`). */
|
|
861
|
+
get readyState(): number;
|
|
862
|
+
private resolveRawNames;
|
|
863
|
+
private send;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
declare class OstiumSubgraphClient {
|
|
867
|
+
private readonly gql;
|
|
868
|
+
private readonly builderApiUrl;
|
|
869
|
+
/** Cached pair-name (`${from}/${to}`) → `pairId` map. Refreshed lazily. */
|
|
870
|
+
private pairIdCache;
|
|
871
|
+
/** Cached `pairId` → `"FROM-TO"` in raw subgraph dash format (used for OHLC API). */
|
|
872
|
+
private pairRawNameCache;
|
|
873
|
+
private constructor();
|
|
874
|
+
/**
|
|
875
|
+
* Create a client connected to the Ostium subgraph.
|
|
876
|
+
*
|
|
877
|
+
* Fetches the full pair list at startup so that `streamPrices`, `getCandles`,
|
|
878
|
+
* and `getAllPrices` can resolve pair ids to raw names without an extra round-trip.
|
|
879
|
+
*
|
|
880
|
+
* ```ts
|
|
881
|
+
* // Mainnet (default)
|
|
882
|
+
* const client = await OstiumSubgraphClient.create();
|
|
883
|
+
*
|
|
884
|
+
* // Testnet (Arbitrum Sepolia)
|
|
885
|
+
* const client = await OstiumSubgraphClient.create({ testnet: true });
|
|
886
|
+
* ```
|
|
887
|
+
*/
|
|
888
|
+
static create(config?: OstiumSubgraphClientConfig): Promise<OstiumSubgraphClient>;
|
|
889
|
+
private initPairCache;
|
|
890
|
+
/**
|
|
891
|
+
* All trading pairs with computed `minSz`/`maxBSz`/`maxSSz`, live prices, and
|
|
892
|
+
* market-status flags. Pass `pairIds` to restrict to a subset.
|
|
893
|
+
*/
|
|
894
|
+
getPairs(params?: GetPairsParams): Promise<PairsResponse>;
|
|
895
|
+
/** Live mid/bid/ask prices keyed by `pairId`. */
|
|
896
|
+
getAllPrices(): Promise<AllPricesResponse>;
|
|
897
|
+
/**
|
|
898
|
+
* Open positions for a trader, sorted newest first, with margin summary.
|
|
899
|
+
*
|
|
900
|
+
* - Fetches live prices automatically.
|
|
901
|
+
* - `blockNumber` is required for live PnL (rollover projection). When omitted,
|
|
902
|
+
* PnL fields are zeroed.
|
|
903
|
+
*/
|
|
904
|
+
getOpenPositions(params: GetOpenPositionsParams): Promise<OpenPositionsResponse>;
|
|
905
|
+
/**
|
|
906
|
+
* Executed fills, sorted by `executedAt desc`.
|
|
907
|
+
*
|
|
908
|
+
* - `user`: pass an address to scope to a single trader, or `'ALL'` to fetch
|
|
909
|
+
* fills across every trader (no trader filter).
|
|
910
|
+
* - `pairId`: optional pair filter — when set, only fills on this pair are returned.
|
|
911
|
+
*/
|
|
912
|
+
getFills(params: GetFillsParams): Promise<Fill[]>;
|
|
913
|
+
/** Executed fills within an inclusive time range (Unix ms). Same filters as `getFills`. */
|
|
914
|
+
getFillsByTime(params: GetFillsByTimeParams): Promise<Fill[]>;
|
|
915
|
+
private fetchFills;
|
|
916
|
+
/** Active limit orders for a trader, sorted by `updatedAt desc`. */
|
|
917
|
+
getOpenOrders({ user }: GetUserParams): Promise<OpenOrder[]>;
|
|
918
|
+
/**
|
|
919
|
+
* Fetch orders at any status — pending, executed, or cancelled.
|
|
920
|
+
*
|
|
921
|
+
* - Pass `initiatedTxHashes` (e.g. `[result.txHash]` from `openTrade` / `closeTrade`)
|
|
922
|
+
* to poll by the subgraph `initiatedTx` field.
|
|
923
|
+
* - Pass `orderIds` to look up by on-chain order id (mutually exclusive with
|
|
924
|
+
* `initiatedTxHashes`).
|
|
925
|
+
* - Pass only `user` (or omit on `OstiumClient`) to get recent orders for
|
|
926
|
+
* a trader regardless of status.
|
|
927
|
+
*/
|
|
928
|
+
getOrders(params?: GetOrdersParams): Promise<Order[]>;
|
|
929
|
+
/**
|
|
930
|
+
* Simulate the dynamic-spread slippage a long and a short entry of each
|
|
931
|
+
* notional would experience on the given pairs. Notionals exceeding the
|
|
932
|
+
* side's remaining open-interest capacity (`maxOI − sideOI`) are dropped.
|
|
933
|
+
*
|
|
934
|
+
* Computed via `CalculateDynamicPriceImpact` from `@ostium/formulae` using
|
|
935
|
+
* the pair's live OI / decay / threshold params + the current bid/mid/ask
|
|
936
|
+
* from the live-prices feed (collateral = `ntl`, leverage = 1).
|
|
937
|
+
*
|
|
938
|
+
* ```ts
|
|
939
|
+
* const sim = await client.getSimSlippage({
|
|
940
|
+
* pairIds: ['0', '1'],
|
|
941
|
+
* ntls: ['10000', '100000', '1000000'],
|
|
942
|
+
* });
|
|
943
|
+
* // → { '0': { long: [{ ntl, slippage }...], short: [...] }, '1': ... }
|
|
944
|
+
* ```
|
|
945
|
+
*/
|
|
946
|
+
getSimSlippage(params: GetSimSlippageParams): Promise<SimSlippageByPairId>;
|
|
947
|
+
/**
|
|
948
|
+
* Build a synthetic bid/ask orderbook for a single pair using the on-chain
|
|
949
|
+
* dynamic-spread params. Each side gets up to `levels` (capped at 20)
|
|
950
|
+
* exponentially-spaced notional levels (`[1, 2, 3, 5] × 10ⁿ`), stopping at
|
|
951
|
+
* the side's remaining open-interest capacity.
|
|
952
|
+
*
|
|
953
|
+
* ```ts
|
|
954
|
+
* const ob = await client.getSimOrderbook({ pairId: '0', levels: 20 });
|
|
955
|
+
* // ob.asks: long-entry levels (you'd buy at `px`)
|
|
956
|
+
* // ob.bids: short-entry levels (you'd sell at `px`)
|
|
957
|
+
* ```
|
|
958
|
+
*/
|
|
959
|
+
getSimOrderbook(params: GetSimOrderbookParams): Promise<SimOrderbookResponse>;
|
|
960
|
+
/**
|
|
961
|
+
* Fetch OHLC candles for a pair.
|
|
962
|
+
*
|
|
963
|
+
* `pairId` maps to the raw subgraph pair name internally (e.g. pair `0` →
|
|
964
|
+
* `"BTC-USD"`). `from` / `to` are Unix milliseconds; `resolution` is one of
|
|
965
|
+
* `"1"`, `"5"`, `"15"`, `"60"`, `"240"`, `"1D"`.
|
|
966
|
+
*
|
|
967
|
+
* ```ts
|
|
968
|
+
* const candles = await client.getCandles({
|
|
969
|
+
* pairId: 0,
|
|
970
|
+
* from: Date.now() - 7 * 86_400_000,
|
|
971
|
+
* resolution: '1D',
|
|
972
|
+
* });
|
|
973
|
+
* ```
|
|
974
|
+
*/
|
|
975
|
+
getCandles(params: GetCandlesParams): Promise<Candle[]>;
|
|
976
|
+
/**
|
|
977
|
+
* Open a WebSocket connection to the live price stream.
|
|
978
|
+
*
|
|
979
|
+
* Optionally filter to a subset of pairs by `pairId` — same values as returned by
|
|
980
|
+
* `getPairs()`. When provided, the client sends `{ type: "subscribe", pairs }` on
|
|
981
|
+
* `open` (no `?pairs=` query on the URL). Omit `pairIds` to receive the full feed.
|
|
982
|
+
*
|
|
983
|
+
* The returned `OstiumPriceStream` fires an initial `snapshot` event with all
|
|
984
|
+
* cached ticks, then a `tick` event on every update. `PriceTick.from` / `.to`
|
|
985
|
+
* are normalized display names (e.g. `"WTI"` not `"CL"`).
|
|
986
|
+
*
|
|
987
|
+
* ```ts
|
|
988
|
+
* const stream = client.streamPrices([0, 1]); // BTC and ETH by pairId
|
|
989
|
+
*
|
|
990
|
+
* stream.onOpen(() => console.log('connected'));
|
|
991
|
+
* stream.onSnapshot(ticks => console.log('snapshot', ticks.length));
|
|
992
|
+
* stream.onTick(tick => console.log(tick.pair, tick.mid));
|
|
993
|
+
*
|
|
994
|
+
* // Dynamically add / remove by pairId:
|
|
995
|
+
* stream.subscribe([2]);
|
|
996
|
+
* stream.unsubscribe([0]);
|
|
997
|
+
* stream.close();
|
|
998
|
+
* ```
|
|
999
|
+
*
|
|
1000
|
+
* Requires a runtime with native `WebSocket` (Node.js 18+, Bun, browsers). Bun’s
|
|
1001
|
+
* `WebSocket` may fail some `https://` upgrades (e.g. CloudFront); use Node if so.
|
|
1002
|
+
*/
|
|
1003
|
+
streamPrices(pairIds?: Array<string | number>): OstiumPriceStream;
|
|
1004
|
+
private fetchRawPairs;
|
|
1005
|
+
private refreshPairIdCache;
|
|
1006
|
+
private ensurePairIdCache;
|
|
1007
|
+
private ensurePairRawName;
|
|
1008
|
+
/** Wrapped `fetchLivePrices` that swallows network errors and returns `{}`. */
|
|
1009
|
+
private fetchLivePricesSafe;
|
|
1010
|
+
private query;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
declare class OstiumClient {
|
|
1014
|
+
private readonly signer?;
|
|
1015
|
+
private readonly submitter?;
|
|
1016
|
+
private readonly contracts;
|
|
1017
|
+
private readonly publicClient;
|
|
1018
|
+
private readonly defaultSlippageBps;
|
|
1019
|
+
private readonly delegated;
|
|
1020
|
+
private readonly gasless;
|
|
1021
|
+
private readonly selfGasless;
|
|
1022
|
+
private readonly eoaSubmit?;
|
|
1023
|
+
private readonly builderAddress?;
|
|
1024
|
+
private readonly builderFeeBps?;
|
|
1025
|
+
/** Internal subgraph client backing all read methods (`getPairs`, `getOpenPositions`, …). */
|
|
1026
|
+
readonly subgraph: OstiumSubgraphClient;
|
|
1027
|
+
private constructor();
|
|
1028
|
+
/**
|
|
1029
|
+
* **Self + Self** — your EOA signs every transaction and pays gas directly.
|
|
1030
|
+
*
|
|
1031
|
+
* Use this when you want the simplest possible setup: one key, no smart accounts,
|
|
1032
|
+
* no delegation. Your EOA holds USDC and owns all positions.
|
|
1033
|
+
*
|
|
1034
|
+
* ```ts
|
|
1035
|
+
* const client = await OstiumClient.createSelfAndSelf({
|
|
1036
|
+
* traderPrivateKey: '0x...',
|
|
1037
|
+
* rpcUrl: 'https://arb-mainnet.g.alchemy.com/v2/...',
|
|
1038
|
+
* });
|
|
1039
|
+
* await client.openTrade({ ... });
|
|
1040
|
+
* ```
|
|
1041
|
+
*/
|
|
1042
|
+
static createSelfAndSelf(params: SelfSelfParams): Promise<OstiumClient>;
|
|
1043
|
+
/**
|
|
1044
|
+
* **Self + Gasless** — your EOA owns everything; a Safe relays trades for free.
|
|
1045
|
+
*
|
|
1046
|
+
* Your EOA holds USDC and owns all positions. A Safe smart account is derived
|
|
1047
|
+
* deterministically from your private key and registered as your on-chain delegate.
|
|
1048
|
+
* After a one-time setup (approve USDC + `setupGaslessDelegation()`), all trades
|
|
1049
|
+
* are submitted as sponsored UserOperations — no ETH required.
|
|
1050
|
+
*
|
|
1051
|
+
* ```ts
|
|
1052
|
+
* const client = await OstiumClient.createSelfAndGasless({
|
|
1053
|
+
* traderPrivateKey: '0x...',
|
|
1054
|
+
* pimlicoUrl: 'https://builder.ostium.io/v1/pimlico/sponsor?chainId=42161',
|
|
1055
|
+
* });
|
|
1056
|
+
* // One-time setup — EOA pays gas once for each:
|
|
1057
|
+
* await client.approveUsdc('max');
|
|
1058
|
+
* await client.setupGaslessDelegation();
|
|
1059
|
+
* // All subsequent trading is gasless:
|
|
1060
|
+
* await client.openTrade({ ... });
|
|
1061
|
+
* ```
|
|
1062
|
+
*/
|
|
1063
|
+
static createSelfAndGasless(params: SelfGaslessParams): Promise<OstiumClient>;
|
|
1064
|
+
/**
|
|
1065
|
+
* **Delegated + Self** — a delegate EOA signs and pays gas on behalf of a trader address.
|
|
1066
|
+
*
|
|
1067
|
+
* The trader retains custody of USDC and positions. The delegate only needs ETH
|
|
1068
|
+
* for gas. Every trade is wrapped in `delegatedAction(traderAddress, callData)`.
|
|
1069
|
+
* The trader must call `setDelegate(delegateAddress)` once before this client
|
|
1070
|
+
* can submit trades.
|
|
1071
|
+
*
|
|
1072
|
+
* ```ts
|
|
1073
|
+
* const client = await OstiumClient.createDelegatedAndSelf({
|
|
1074
|
+
* delegatePrivateKey: '0xDelegateKey',
|
|
1075
|
+
* traderAddress: '0xTraderAddress',
|
|
1076
|
+
* rpcUrl: 'https://arb-mainnet.g.alchemy.com/v2/...',
|
|
1077
|
+
* });
|
|
1078
|
+
* await client.openTrade({ ... });
|
|
1079
|
+
* ```
|
|
1080
|
+
*/
|
|
1081
|
+
static createDelegatedAndSelf(params: DelegatedSelfParams): Promise<OstiumClient>;
|
|
1082
|
+
/**
|
|
1083
|
+
* **Delegated + Gasless** — a Safe derived from the delegate key submits sponsored
|
|
1084
|
+
* UserOperations on behalf of the trader. No ETH needed after setup.
|
|
1085
|
+
*
|
|
1086
|
+
* The trader retains custody of USDC and positions. The delegate's Safe submits
|
|
1087
|
+
* trades as UserOperations via Pimlico. The trader must call `setDelegate(safeAddress)`
|
|
1088
|
+
* once — use `client.getSmartAccountAddress()` to retrieve the Safe address.
|
|
1089
|
+
*
|
|
1090
|
+
* ```ts
|
|
1091
|
+
* const client = await OstiumClient.createDelegatedAndGasless({
|
|
1092
|
+
* delegatePrivateKey: '0xDelegateKey',
|
|
1093
|
+
* traderAddress: '0xTraderAddress',
|
|
1094
|
+
* pimlicoUrl: 'https://builder.ostium.io/v1/pimlico/sponsor?chainId=42161',
|
|
1095
|
+
* });
|
|
1096
|
+
* await client.openTrade({ ... }); // gasless delegatedAction UserOp
|
|
1097
|
+
* ```
|
|
1098
|
+
*/
|
|
1099
|
+
static createDelegatedAndGasless(params: DelegatedGaslessParams): Promise<OstiumClient>;
|
|
1100
|
+
/**
|
|
1101
|
+
* **Read-only client** — no signer, no submitter, no privateKey required.
|
|
1102
|
+
*
|
|
1103
|
+
* All read methods (`getPairs`, `getOpenPositions`, `getFills`, `getBalances`, …)
|
|
1104
|
+
* are available. Methods that take an optional `user` argument require it to be
|
|
1105
|
+
* passed explicitly. Calling any write method throws `INVALID_CONFIG`.
|
|
1106
|
+
*
|
|
1107
|
+
* ```ts
|
|
1108
|
+
* const reader = await OstiumClient.createReadOnly();
|
|
1109
|
+
* const { pairs } = await reader.getPairs();
|
|
1110
|
+
* const balances = await reader.getBalances('0xTrader...');
|
|
1111
|
+
* const positions = await reader.getOpenPositions({ user: '0xTrader...' });
|
|
1112
|
+
* ```
|
|
1113
|
+
*/
|
|
1114
|
+
static createReadOnly(params?: {
|
|
1115
|
+
/** Arbitrum RPC URL. Defaults to the chain's public RPC. */
|
|
1116
|
+
rpcUrl?: string;
|
|
1117
|
+
/** Use Arbitrum Sepolia testnet. Defaults to false (mainnet). */
|
|
1118
|
+
testnet?: boolean;
|
|
1119
|
+
/** Override the subgraph endpoint. */
|
|
1120
|
+
subgraphUrl?: string;
|
|
1121
|
+
/** Override the builder API base URL (prices, OHLC, WebSocket stream). */
|
|
1122
|
+
builderApiUrl?: string;
|
|
1123
|
+
}): Promise<OstiumClient>;
|
|
1124
|
+
/** Internal factory shared by all public constructors. */
|
|
1125
|
+
private static _fromConfig;
|
|
1126
|
+
/**
|
|
1127
|
+
* The on-chain address that owns trades and USDC allowances.
|
|
1128
|
+
*
|
|
1129
|
+
* - Self + Self / Delegated modes: trader's EOA or configured traderAddress.
|
|
1130
|
+
* - Self + Gasless: EOA derived from privateKey (NOT the Safe — USDC lives here).
|
|
1131
|
+
*/
|
|
1132
|
+
getTraderAddress(): Address;
|
|
1133
|
+
/** True when the client was created via `createReadOnly` and cannot submit transactions. */
|
|
1134
|
+
isReadOnly(): boolean;
|
|
1135
|
+
/**
|
|
1136
|
+
* Returns the Safe smart-account address used for gasless submission.
|
|
1137
|
+
* Returns undefined when not in gasless mode.
|
|
1138
|
+
*
|
|
1139
|
+
* - Self + Gasless: Safe that submits on behalf of the EOA (the delegate).
|
|
1140
|
+
* Pass this address to setupGaslessDelegation().
|
|
1141
|
+
* - Delegated + Gasless: delegate's Safe address.
|
|
1142
|
+
* - Self + Self / Delegated + Self: returns undefined.
|
|
1143
|
+
*/
|
|
1144
|
+
getSmartAccountAddress(): Address | undefined;
|
|
1145
|
+
/**
|
|
1146
|
+
* One-time setup for Self + Gasless mode.
|
|
1147
|
+
*
|
|
1148
|
+
* Registers the Safe smart account as a delegate on the trading contract so
|
|
1149
|
+
* the Safe can submit gasless trades on behalf of your EOA. The EOA pays gas
|
|
1150
|
+
* for this single transaction; all subsequent trading is gasless.
|
|
1151
|
+
*
|
|
1152
|
+
* Only callable in Self + Gasless mode. Throws INVALID_CONFIG otherwise.
|
|
1153
|
+
*
|
|
1154
|
+
* @example
|
|
1155
|
+
* ```ts
|
|
1156
|
+
* const client = await OstiumClient.create({ privateKey: '0x...', pimlicoUrl: 'https://builder.ostium.io/v1/pimlico/sponsor?chainId=42161' });
|
|
1157
|
+
* await client.approveUsdc('max'); // EOA approves USDC (gas, one-time)
|
|
1158
|
+
* await client.setupGaslessDelegation(); // EOA sets Safe as delegate (gas, one-time)
|
|
1159
|
+
* // From here: all trading is gasless
|
|
1160
|
+
* await client.openTrade({ ... });
|
|
1161
|
+
* ```
|
|
1162
|
+
*/
|
|
1163
|
+
setupGaslessDelegation(): Promise<SubmissionResult>;
|
|
1164
|
+
/**
|
|
1165
|
+
* Check whether the trader's USDC allowance covers the required amount.
|
|
1166
|
+
* The allowance is always checked against signer.traderAddress (the EOA in
|
|
1167
|
+
* Self + Gasless mode, the Safe in Delegated + Gasless).
|
|
1168
|
+
*/
|
|
1169
|
+
checkUsdcAllowance(requiredUsd: string): Promise<AllowanceStatus>;
|
|
1170
|
+
/**
|
|
1171
|
+
* USDC and ETH balances plus the USDC allowance to TradingStorage.
|
|
1172
|
+
* All three values are decimal strings so large values (e.g. max USDC approval)
|
|
1173
|
+
* are preserved exactly. Parse with `parseFloat` / `Number` only for display.
|
|
1174
|
+
*
|
|
1175
|
+
* In read-only mode, pass `user` explicitly. With a connected trader, omit it
|
|
1176
|
+
* to read the connected address.
|
|
1177
|
+
*/
|
|
1178
|
+
getBalances(user?: Address): Promise<Balances>;
|
|
1179
|
+
/**
|
|
1180
|
+
* Approve USDC spending by the TradingStorage contract.
|
|
1181
|
+
*
|
|
1182
|
+
* - Self + Self: submitted gaslessly from EOA.
|
|
1183
|
+
* - Self + Gasless: submitted directly from EOA (the delegate cannot approve
|
|
1184
|
+
* on behalf of the trader). The EOA pays gas for this one-time operation.
|
|
1185
|
+
* - Delegated modes: throws — the trader must approve from their own account.
|
|
1186
|
+
*
|
|
1187
|
+
* @param amount USD amount as decimal string (e.g. "1000"), or "max" for MaxUint256.
|
|
1188
|
+
*/
|
|
1189
|
+
approveUsdc(amount: string): Promise<SubmissionResult>;
|
|
1190
|
+
/**
|
|
1191
|
+
* Set a delegate on the trading contract.
|
|
1192
|
+
*
|
|
1193
|
+
* - Self + Self: EOA directly registers a delegate.
|
|
1194
|
+
* - Self + Gasless: NOT recommended — use setupGaslessDelegation() instead.
|
|
1195
|
+
* - Delegated modes: wrapped in delegatedAction so the existing delegate can
|
|
1196
|
+
* update the trader's delegation on their behalf.
|
|
1197
|
+
*/
|
|
1198
|
+
setDelegate(delegateAddress: Address): Promise<SubmissionResult>;
|
|
1199
|
+
/**
|
|
1200
|
+
* Remove the current delegate on the trading contract.
|
|
1201
|
+
* Follows the same delegation-wrapping rules as setDelegate().
|
|
1202
|
+
*/
|
|
1203
|
+
removeDelegate(): Promise<SubmissionResult>;
|
|
1204
|
+
/**
|
|
1205
|
+
* Open a new trade position.
|
|
1206
|
+
*
|
|
1207
|
+
* Call `approveUsdc()` (once) before the first trade — the contract will revert
|
|
1208
|
+
* on-chain if the USDC allowance is insufficient. Use `getBalances()` to check
|
|
1209
|
+
* the current allowance.
|
|
1210
|
+
*/
|
|
1211
|
+
openTrade(params: OpenTradeParams): Promise<SubmissionResult>;
|
|
1212
|
+
/**
|
|
1213
|
+
* Close an open position (full or partial).
|
|
1214
|
+
*
|
|
1215
|
+
* `pairId` and `idx` come straight from a `Position` returned by
|
|
1216
|
+
* `getOpenPositions` — pass them through directly:
|
|
1217
|
+
*
|
|
1218
|
+
* ```ts
|
|
1219
|
+
* const { pairPositions } = await client.getOpenPositions();
|
|
1220
|
+
* const { pairId, idx } = pairPositions[0].position;
|
|
1221
|
+
* await client.closeTrade({ pairId, idx, price: '...', closePercent: 100 });
|
|
1222
|
+
* ```
|
|
1223
|
+
*/
|
|
1224
|
+
closeTrade(params: CloseTradeParams): Promise<SubmissionResult>;
|
|
1225
|
+
/**
|
|
1226
|
+
* Cancel a pending order.
|
|
1227
|
+
*
|
|
1228
|
+
* TypeScript discriminates the params shape by `type` — required fields are
|
|
1229
|
+
* enforced at compile time.
|
|
1230
|
+
*
|
|
1231
|
+
* @example Cancel a pending limit order
|
|
1232
|
+
* ```ts
|
|
1233
|
+
* const [order] = await client.getOpenOrders();
|
|
1234
|
+
* await client.cancelOrder({ type: CancelOrderType.Limit, pairId: order.pairId, idx: order.idx });
|
|
1235
|
+
* ```
|
|
1236
|
+
* @example Cancel a timed-out market open
|
|
1237
|
+
* ```ts
|
|
1238
|
+
* await client.cancelOrder({ type: CancelOrderType.PendingOpen, orderId: 123 });
|
|
1239
|
+
* ```
|
|
1240
|
+
* @example Cancel a timed-out market close (retry: true re-submits the close)
|
|
1241
|
+
* ```ts
|
|
1242
|
+
* await client.cancelOrder({ type: CancelOrderType.PendingClose, orderId: 456, retry: true });
|
|
1243
|
+
* ```
|
|
1244
|
+
*/
|
|
1245
|
+
cancelOrder(params: CancelOrderParams): Promise<SubmissionResult>;
|
|
1246
|
+
/**
|
|
1247
|
+
* Modify an open trade or a pending limit order.
|
|
1248
|
+
*
|
|
1249
|
+
* `pairId` and `idx` come straight from `getOpenPositions` (for TP/SL on open
|
|
1250
|
+
* positions) or `getOpenOrders` (for limit-order edits):
|
|
1251
|
+
*
|
|
1252
|
+
* ```ts
|
|
1253
|
+
* // Update TP/SL on an open position
|
|
1254
|
+
* const { pairPositions } = await client.getOpenPositions();
|
|
1255
|
+
* const { pairId, idx } = pairPositions[0].position;
|
|
1256
|
+
* await client.modifyOrder({ pairId, idx, takeProfit: '...', stopLoss: '...' });
|
|
1257
|
+
*
|
|
1258
|
+
* // Re-price a pending limit order
|
|
1259
|
+
* const [order] = await client.getOpenOrders();
|
|
1260
|
+
* await client.modifyOrder({ pairId: order.pairId, idx: order.idx, price: '...' });
|
|
1261
|
+
* ```
|
|
1262
|
+
*
|
|
1263
|
+
* - `price` provided → updates limit-order trigger price (with optional TP/SL).
|
|
1264
|
+
* - `takeProfit` only → calls updateTp on an open trade.
|
|
1265
|
+
* - `stopLoss` only → calls updateSl on an open trade.
|
|
1266
|
+
* - Both `takeProfit` and `stopLoss` without `price` → throws (send two calls).
|
|
1267
|
+
*/
|
|
1268
|
+
modifyOrder(params: ModifyOrderParams): Promise<SubmissionResult>;
|
|
1269
|
+
/**
|
|
1270
|
+
* Update collateral on an open position (isolated margin).
|
|
1271
|
+
*
|
|
1272
|
+
* `pairId` and `idx` come straight from a `Position` returned by `getOpenPositions`:
|
|
1273
|
+
*
|
|
1274
|
+
* ```ts
|
|
1275
|
+
* const { pairPositions } = await client.getOpenPositions();
|
|
1276
|
+
* const { pairId, idx } = pairPositions[0].position;
|
|
1277
|
+
* await client.updateCollateral({ pairId, idx, amount: '50' }); // top up
|
|
1278
|
+
* await client.updateCollateral({ pairId, idx, amount: '-25' }); // remove
|
|
1279
|
+
* ```
|
|
1280
|
+
*
|
|
1281
|
+
* Positive amount → topUpCollateral (adds margin, reduces effective leverage).
|
|
1282
|
+
* Negative amount → removeCollateral (removes margin, increases effective leverage).
|
|
1283
|
+
*
|
|
1284
|
+
* Checks USDC allowance before top-up operations.
|
|
1285
|
+
*/
|
|
1286
|
+
updateCollateral(params: UpdateCollateralParams): Promise<SubmissionResult>;
|
|
1287
|
+
/**
|
|
1288
|
+
* All trading pairs with computed `minSz`/`maxBSz`/`maxSSz`, live prices, and
|
|
1289
|
+
* market-status flags. Pass `pairIds` to restrict to a subset.
|
|
1290
|
+
*/
|
|
1291
|
+
getPairs(params?: GetPairsParams): Promise<PairsResponse>;
|
|
1292
|
+
/** Live mid/bid/ask prices keyed by `pairId`. */
|
|
1293
|
+
getAllPrices(): Promise<AllPricesResponse>;
|
|
1294
|
+
/**
|
|
1295
|
+
* Open positions + margin summary for a user. Defaults to the connected
|
|
1296
|
+
* trader. Live prices and the current block number are fetched automatically.
|
|
1297
|
+
*/
|
|
1298
|
+
getOpenPositions(params?: Partial<GetOpenPositionsParams>): Promise<OpenPositionsResponse>;
|
|
1299
|
+
/**
|
|
1300
|
+
* Executed fills, newest first.
|
|
1301
|
+
*
|
|
1302
|
+
* - `user` defaults to the connected trader. Pass `'ALL'` to fetch fills
|
|
1303
|
+
* across every trader (no trader filter).
|
|
1304
|
+
* - `pairId` (optional) — restricts to a single pair.
|
|
1305
|
+
* - `limit` (optional, default `1000`) — caps the result. Pass `Infinity` to
|
|
1306
|
+
* fetch every matching fill.
|
|
1307
|
+
*/
|
|
1308
|
+
getFills(params?: Partial<GetFillsParams>): Promise<Fill[]>;
|
|
1309
|
+
/**
|
|
1310
|
+
* Executed fills within a time range (Unix ms). Same filters as `getFills`,
|
|
1311
|
+
* including the default `limit: 1000`.
|
|
1312
|
+
*/
|
|
1313
|
+
getFillsByTime(params: Partial<GetFillsByTimeParams> & {
|
|
1314
|
+
startTime: number;
|
|
1315
|
+
}): Promise<Fill[]>;
|
|
1316
|
+
/** Active limit orders for a user. Defaults to the connected trader. */
|
|
1317
|
+
getOpenOrders(params?: Partial<GetUserParams>): Promise<OpenOrder[]>;
|
|
1318
|
+
/**
|
|
1319
|
+
* Fetch orders at any status — pending, executed, or cancelled.
|
|
1320
|
+
*
|
|
1321
|
+
* Pass `initiatedTxHashes: [result.txHash]` to poll by the submission hash, or
|
|
1322
|
+
* `orderIds` by on-chain id. Without either, returns recent orders for the
|
|
1323
|
+
* connected trader.
|
|
1324
|
+
*/
|
|
1325
|
+
getOrders(params?: Omit<GetOrdersParams, 'user'> & {
|
|
1326
|
+
user?: Address;
|
|
1327
|
+
}): Promise<Order[]>;
|
|
1328
|
+
/**
|
|
1329
|
+
* Simulate per-side slippage for a list of pairs and notionals.
|
|
1330
|
+
* See {@link OstiumSubgraphClient.getSimSlippage} for full semantics.
|
|
1331
|
+
*/
|
|
1332
|
+
getSimSlippage(params: GetSimSlippageParams): Promise<SimSlippageByPairId>;
|
|
1333
|
+
/**
|
|
1334
|
+
* Build a synthetic bid/ask orderbook for one pair using exponentially-spaced
|
|
1335
|
+
* notional levels capped at each side's remaining OI capacity.
|
|
1336
|
+
* See {@link OstiumSubgraphClient.getSimOrderbook} for full semantics.
|
|
1337
|
+
*/
|
|
1338
|
+
getSimOrderbook(params: GetSimOrderbookParams): Promise<SimOrderbookResponse>;
|
|
1339
|
+
/**
|
|
1340
|
+
* Fetch OHLC candles for a pair from the builder API.
|
|
1341
|
+
*
|
|
1342
|
+
* `from` / `to` are Unix milliseconds; `resolution` is one of
|
|
1343
|
+
* `"1"`, `"5"`, `"15"`, `"60"`, `"240"`, `"1D"`.
|
|
1344
|
+
*
|
|
1345
|
+
* ```ts
|
|
1346
|
+
* const candles = await client.getCandles({
|
|
1347
|
+
* pairId: 0,
|
|
1348
|
+
* from: Date.now() - 30 * 86_400_000,
|
|
1349
|
+
* resolution: '1D',
|
|
1350
|
+
* });
|
|
1351
|
+
* ```
|
|
1352
|
+
*/
|
|
1353
|
+
getCandles(params: GetCandlesParams): Promise<Candle[]>;
|
|
1354
|
+
/**
|
|
1355
|
+
* Open a WebSocket connection to the live price stream.
|
|
1356
|
+
*
|
|
1357
|
+
* Optionally filter to a subset of pairs by `pairId` — same values as returned by
|
|
1358
|
+
* `getPairs()`. When provided, the client sends `{ type: "subscribe", pairs }` on
|
|
1359
|
+
* `open` (no `?pairs=` query on the URL). Omit `pairIds` to receive the full feed.
|
|
1360
|
+
*
|
|
1361
|
+
* ```ts
|
|
1362
|
+
* const stream = client.streamPrices([0, 1]); // BTC and ETH by pairId
|
|
1363
|
+
* stream.onSnapshot(ticks => console.log(ticks));
|
|
1364
|
+
* stream.onTick(tick => console.log(tick.pair, tick.mid));
|
|
1365
|
+
* stream.subscribe([2]); // add pair
|
|
1366
|
+
* stream.unsubscribe([0]); // remove pair
|
|
1367
|
+
* stream.close();
|
|
1368
|
+
* ```
|
|
1369
|
+
*
|
|
1370
|
+
* Requires Node.js 18+, Bun, or a browser environment. Bun’s `WebSocket` may fail
|
|
1371
|
+
* some `https://` upgrades; use Node if the connection never reaches `open`.
|
|
1372
|
+
*/
|
|
1373
|
+
streamPrices(pairIds?: Array<string | number>): OstiumPriceStream;
|
|
1374
|
+
/**
|
|
1375
|
+
* Core execution pipeline:
|
|
1376
|
+
* 1. signer.prepare() — optionally wraps in delegatedAction.
|
|
1377
|
+
* 2. submitter.submit() — sends via EOA walletClient or Pimlico UserOp.
|
|
1378
|
+
*/
|
|
1379
|
+
private execute;
|
|
1380
|
+
/** Throws if the client is read-only; otherwise returns the signer + submitter. */
|
|
1381
|
+
private requireWriter;
|
|
1382
|
+
/** Direct EOA submission — used only in Self + Gasless for approveUsdc and setupGaslessDelegation. */
|
|
1383
|
+
private submitDirectFromEoa;
|
|
1384
|
+
private resolveSlippage;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
declare enum OstiumErrorCode {
|
|
1388
|
+
INVALID_CONFIG = "INVALID_CONFIG",
|
|
1389
|
+
VALIDATION_FAILED = "VALIDATION_FAILED",
|
|
1390
|
+
ALLOWANCE_INSUFFICIENT = "ALLOWANCE_INSUFFICIENT",
|
|
1391
|
+
SUBMISSION_FAILED = "SUBMISSION_FAILED",
|
|
1392
|
+
DELEGATION_FAILED = "DELEGATION_FAILED",
|
|
1393
|
+
CONTRACT_ERROR = "CONTRACT_ERROR",
|
|
1394
|
+
NETWORK_ERROR = "NETWORK_ERROR"
|
|
1395
|
+
}
|
|
1396
|
+
declare class OstiumError extends Error {
|
|
1397
|
+
readonly code: OstiumErrorCode;
|
|
1398
|
+
readonly cause?: unknown | undefined;
|
|
1399
|
+
constructor(message: string, code: OstiumErrorCode, cause?: unknown | undefined);
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
/**
|
|
1403
|
+
* Decimal conversion utilities for trading precision
|
|
1404
|
+
* Critical: All values must be scaled correctly for smart contract calls
|
|
1405
|
+
*/
|
|
1406
|
+
/**
|
|
1407
|
+
* Parse a USDC amount string to bigint with 6 decimals
|
|
1408
|
+
* @param amount - Amount in USDC (e.g., "100.50" = 100.50 USDC)
|
|
1409
|
+
* @returns Bigint representation with 6 decimal precision
|
|
1410
|
+
*/
|
|
1411
|
+
declare function parseUsdc(amount: string | number): bigint;
|
|
1412
|
+
/**
|
|
1413
|
+
* Parse a price string to bigint with 18 decimals.
|
|
1414
|
+
* Uses string manipulation to avoid floating-point precision loss.
|
|
1415
|
+
* @param price - Price as string (e.g., "1900.50")
|
|
1416
|
+
* @returns Bigint representation with 18 decimal precision
|
|
1417
|
+
*/
|
|
1418
|
+
declare function parsePrice(price: string | number): bigint;
|
|
1419
|
+
/**
|
|
1420
|
+
* Parse leverage to contract format (leverage × 100).
|
|
1421
|
+
* @param leverage - Leverage as number (e.g., 20 for 20x)
|
|
1422
|
+
* @returns Bigint (e.g., 2000 for 20x)
|
|
1423
|
+
*/
|
|
1424
|
+
declare function parseLeverage(leverage: number): bigint;
|
|
1425
|
+
|
|
1426
|
+
/**
|
|
1427
|
+
* Precision constants for decimal conversions
|
|
1428
|
+
* Critical for trading calculations - all values must be scaled correctly
|
|
1429
|
+
*/
|
|
1430
|
+
declare const PRECISION_6 = 1000000n;
|
|
1431
|
+
declare const PRECISION_18 = 1000000000000000000n;
|
|
1432
|
+
declare const DEFAULT_SLIPPAGE_PERCENTAGE = 0.25;
|
|
1433
|
+
declare const MIN_COLLATERAL_USD = 5;
|
|
1434
|
+
declare const MAX_COLLATERAL_USD = 2000000;
|
|
1435
|
+
|
|
1436
|
+
declare enum OstiumSubgraphErrorCode {
|
|
1437
|
+
INVALID_CONFIG = "INVALID_CONFIG",
|
|
1438
|
+
INVALID_PARAMS = "INVALID_PARAMS",
|
|
1439
|
+
FETCH_FAILED = "FETCH_FAILED",
|
|
1440
|
+
NOT_FOUND = "NOT_FOUND",
|
|
1441
|
+
PARSE_ERROR = "PARSE_ERROR"
|
|
1442
|
+
}
|
|
1443
|
+
declare class OstiumSubgraphError extends Error {
|
|
1444
|
+
readonly code: OstiumSubgraphErrorCode;
|
|
1445
|
+
readonly cause?: unknown | undefined;
|
|
1446
|
+
constructor(message: string, code: OstiumSubgraphErrorCode, cause?: unknown | undefined);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
export { type AllPricesResponse, type AllTraders, type AllowanceStatus, type Balances, type CancelLimitOrderParams, type CancelOrderParams, CancelOrderType, type CancelPendingCloseParams, type CancelPendingOpenParams, type Candle, type CandleResolution, type CloseTradeParams, DEFAULT_BUILDER_API_URL, DEFAULT_SLIPPAGE_PERCENTAGE, DEFAULT_SUBGRAPH_ENDPOINT, DEFAULT_SUBGRAPH_ENDPOINT_TESTNET, type DelegatedGaslessParams, type DelegatedSelfParams, type Fill, type FillFees, type OrderType as FillOrderType, type GetCandlesParams, type GetFillsByTimeParams, type GetFillsParams, type GetOpenPositionsParams, type GetOrdersParams, type GetPairsParams, type GetSimOrderbookParams, type GetSimSlippageParams, type GetUserParams, MAX_COLLATERAL_USD, MIN_COLLATERAL_USD, type MarginSummary, type ModifyOrderParams, type OpenOrder, type OpenPositionsResponse, type OpenTradeParams, type Order, type OrderAction, OrderType$1 as OrderType, OstiumClient, type OstiumClientConfig, OstiumError, OstiumErrorCode, OstiumPriceStream, OstiumSubgraphClient, type OstiumSubgraphClientConfig, OstiumSubgraphError, OstiumSubgraphErrorCode, PRECISION_18, PRECISION_6, type Pair, type PairPosition, type PairsResponse, type Position, type PriceData, type PriceTick, type SelfGaslessParams, type SelfSelfParams, type SimOrderbookLevel, type SimOrderbookResponse, type SimSlippageByPairId, type SimSlippageForPair, type SimSlippageRow, type SubmissionResult, type UpdateCollateralParams, parseLeverage, parsePrice, parseUsdc };
|