@strkfarm/sdk 2.0.0-dev.35 → 2.0.0-dev.36
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/cli.js +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/index.browser.global.js +19244 -28574
- package/dist/index.browser.mjs +8439 -17951
- package/dist/index.d.ts +578 -2746
- package/dist/index.js +8528 -18078
- package/dist/index.mjs +8456 -17968
- package/package.json +3 -3
- package/src/data/universal-vault.abi.json +8 -7
- package/src/dataTypes/bignumber.browser.ts +5 -1
- package/src/dataTypes/bignumber.node.ts +5 -0
- package/src/global.ts +21 -1
- package/src/interfaces/common.tsx +39 -4
- package/src/modules/avnu.ts +19 -10
- package/src/modules/index.ts +1 -1
- package/src/strategies/base-strategy.ts +92 -8
- package/src/strategies/constants.ts +8 -3
- package/src/strategies/ekubo-cl-vault.tsx +150 -16
- package/src/strategies/factory.ts +21 -1
- package/src/strategies/index.ts +2 -7
- package/src/strategies/registry.ts +28 -5
- package/src/strategies/sensei.ts +29 -13
- package/src/strategies/svk-strategy.ts +26 -2
- package/src/strategies/token-boosted-xstrk-carry-strategy.tsx +1057 -0
- package/src/strategies/universal-adapters/avnu-adapter.ts +16 -8
- package/src/strategies/universal-adapters/index.ts +1 -2
- package/src/strategies/universal-adapters/svk-troves-adapter.ts +19 -6
- package/src/strategies/universal-adapters/vesu-modify-position-adapter.ts +22 -3
- package/src/strategies/universal-adapters/vesu-multiply-adapter.ts +75 -52
- package/src/strategies/universal-adapters/vesu-position-common.ts +38 -31
- package/src/strategies/universal-lst-muliplier-strategy.tsx +222 -269
- package/src/strategies/universal-strategy.tsx +166 -105
- package/src/strategies/vesu-rebalance.tsx +3 -6
- package/src/strategies/yoloVault.ts +1084 -0
- package/src/utils/health-factor-math.ts +29 -0
- package/src/modules/ExtendedWrapperSDk/index.ts +0 -62
- package/src/modules/ExtendedWrapperSDk/types.ts +0 -334
- package/src/modules/ExtendedWrapperSDk/wrapper.ts +0 -611
- package/src/strategies/universal-adapters/extended-adapter.ts +0 -860
- package/src/strategies/universal-adapters/usdc<>usdce-adapter.ts +0 -200
- package/src/strategies/usdc-boosted-strategy.tsx +0 -693
- package/src/strategies/vesu-extended-strategy/services/executionService.ts +0 -2234
- package/src/strategies/vesu-extended-strategy/services/extended-vesu-state-manager.ts +0 -4254
- package/src/strategies/vesu-extended-strategy/services/ltv-imbalance-rebalance-math.ts +0 -783
- package/src/strategies/vesu-extended-strategy/services/operationService.ts +0 -56
- package/src/strategies/vesu-extended-strategy/types/transaction-metadata.ts +0 -88
- package/src/strategies/vesu-extended-strategy/utils/config.runtime.ts +0 -78
- package/src/strategies/vesu-extended-strategy/utils/constants.ts +0 -48
- package/src/strategies/vesu-extended-strategy/utils/helper.ts +0 -528
- package/src/strategies/vesu-extended-strategy/vesu-extended-strategy.tsx +0 -1014
|
@@ -1,611 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ExtendedWrapper - TypeScript wrapper for Extended Exchange API
|
|
3
|
-
* Provides a clean interface to interact with the Extended Exchange trading API
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import BigNumber from "bignumber.js";
|
|
7
|
-
import {
|
|
8
|
-
CreateOrderRequest,
|
|
9
|
-
WithdrawRequest,
|
|
10
|
-
SignedWithdrawRequest,
|
|
11
|
-
CancelOrderRequest,
|
|
12
|
-
PlacedOrder,
|
|
13
|
-
OpenOrder,
|
|
14
|
-
Position,
|
|
15
|
-
Balance,
|
|
16
|
-
Market,
|
|
17
|
-
MarketStats,
|
|
18
|
-
AssetOperation,
|
|
19
|
-
ExtendedApiResponse,
|
|
20
|
-
ExtendedWrapperConfig,
|
|
21
|
-
OrderSide,
|
|
22
|
-
TimeInForce,
|
|
23
|
-
AssetOperationType,
|
|
24
|
-
AssetOperationStatus,
|
|
25
|
-
FundingRate,
|
|
26
|
-
FundingPayment,
|
|
27
|
-
UpdateLeverageRequest,
|
|
28
|
-
} from "./types";
|
|
29
|
-
|
|
30
|
-
type ExtendedTradingRules = {
|
|
31
|
-
minOrderSize: BigNumber;
|
|
32
|
-
qtyStep: BigNumber;
|
|
33
|
-
priceStep: BigNumber;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
function asRecord(v: unknown): Record<string, unknown> | null {
|
|
37
|
-
return v !== null && typeof v === "object" && !Array.isArray(v)
|
|
38
|
-
? (v as Record<string, unknown>)
|
|
39
|
-
: null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function pickTradingConfig(row: Record<string, unknown>): Record<string, unknown> | null {
|
|
43
|
-
const tc = row.trading_config ?? row.tradingConfig;
|
|
44
|
-
return asRecord(tc);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function readTcString(
|
|
48
|
-
tc: Record<string, unknown>,
|
|
49
|
-
snake: string,
|
|
50
|
-
camel: string,
|
|
51
|
-
): string | undefined {
|
|
52
|
-
const v = tc[snake] ?? tc[camel];
|
|
53
|
-
if (v === undefined || v === null) return undefined;
|
|
54
|
-
return String(v).trim();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function tradingRulesFromMarketRow(
|
|
58
|
-
marketName: string,
|
|
59
|
-
row: unknown,
|
|
60
|
-
): ExtendedTradingRules {
|
|
61
|
-
const r = asRecord(row);
|
|
62
|
-
if (!r) {
|
|
63
|
-
throw new Error(`ExtendedWrapper: invalid market payload for ${marketName}`);
|
|
64
|
-
}
|
|
65
|
-
const tc = pickTradingConfig(r);
|
|
66
|
-
if (!tc) {
|
|
67
|
-
throw new Error(`ExtendedWrapper: missing tradingConfig for market ${marketName}`);
|
|
68
|
-
}
|
|
69
|
-
const minS = readTcString(tc, "min_order_size", "minOrderSize");
|
|
70
|
-
const qtyStep = readTcString(tc, "min_order_size_change", "minOrderSizeChange");
|
|
71
|
-
const pxStep = readTcString(tc, "min_price_change", "minPriceChange");
|
|
72
|
-
if (!minS || !qtyStep || !pxStep) {
|
|
73
|
-
throw new Error(`ExtendedWrapper: incomplete tradingConfig for market ${marketName}`);
|
|
74
|
-
}
|
|
75
|
-
const minOrderSize = new BigNumber(minS);
|
|
76
|
-
const qty = new BigNumber(qtyStep);
|
|
77
|
-
const px = new BigNumber(pxStep);
|
|
78
|
-
if (!minOrderSize.isFinite() || minOrderSize.lte(0)) {
|
|
79
|
-
throw new Error(`ExtendedWrapper: invalid minOrderSize for ${marketName}`);
|
|
80
|
-
}
|
|
81
|
-
if (!qty.isFinite() || qty.lte(0)) {
|
|
82
|
-
throw new Error(`ExtendedWrapper: invalid minOrderSizeChange for ${marketName}`);
|
|
83
|
-
}
|
|
84
|
-
if (!px.isFinite() || px.lte(0)) {
|
|
85
|
-
throw new Error(`ExtendedWrapper: invalid minPriceChange for ${marketName}`);
|
|
86
|
-
}
|
|
87
|
-
return { minOrderSize, qtyStep: qty, priceStep: px };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function roundToStepBn(value: BigNumber, step: BigNumber): BigNumber {
|
|
91
|
-
if (step.lte(0)) return value;
|
|
92
|
-
return value.div(step).round(0, BigNumber.ROUND_HALF_UP).times(step);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function formatBnForApi(bn: BigNumber, step: BigNumber): string {
|
|
96
|
-
const dp = Math.max(step.decimalPlaces() ?? 0, bn.decimalPlaces() ?? 0, 0);
|
|
97
|
-
return Number(bn.toFixed(Math.min(80, dp))).toString();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export class ExtendedWrapper {
|
|
101
|
-
private readUrl: string;
|
|
102
|
-
private writeUrl: string;
|
|
103
|
-
private apiKey?: string;
|
|
104
|
-
private timeout: number;
|
|
105
|
-
private retries: number;
|
|
106
|
-
/** Per-market rules from GET /markets (tradingConfig); retained for process lifetime (no TTL). */
|
|
107
|
-
private marketTradingRulesCache = new Map<string, ExtendedTradingRules>();
|
|
108
|
-
private marketTradingRulesInflight = new Map<
|
|
109
|
-
string,
|
|
110
|
-
Promise<ExtendedTradingRules>
|
|
111
|
-
>();
|
|
112
|
-
|
|
113
|
-
constructor(config: ExtendedWrapperConfig) {
|
|
114
|
-
this.apiKey = config.apiKey;
|
|
115
|
-
this.timeout = config.timeout || 30000; // 30 seconds default
|
|
116
|
-
this.retries = config.retries || 3;
|
|
117
|
-
this.readUrl = config.readUrl.replace(/\/$/, "");
|
|
118
|
-
this.writeUrl = config.writeUrl.replace(/\/$/, "");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Make HTTP request with retry logic and error handling
|
|
123
|
-
*/
|
|
124
|
-
private async makeRequest<T>(
|
|
125
|
-
endpoint: string,
|
|
126
|
-
isRead: boolean,
|
|
127
|
-
options: RequestInit = {},
|
|
128
|
-
): Promise<ExtendedApiResponse<T>> {
|
|
129
|
-
const url = `${isRead ? this.readUrl : this.writeUrl}${endpoint}`;
|
|
130
|
-
const headers: Record<string, any> = {
|
|
131
|
-
"Content-Type": "application/json",
|
|
132
|
-
...options.headers,
|
|
133
|
-
};
|
|
134
|
-
if (this.apiKey) {
|
|
135
|
-
headers["X-API-Key"] = this.apiKey;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const requestOptions: RequestInit = {
|
|
139
|
-
...options,
|
|
140
|
-
headers,
|
|
141
|
-
signal: AbortSignal.timeout(this.timeout),
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
let lastError: Error | null = null;
|
|
145
|
-
|
|
146
|
-
for (let attempt = 1; attempt <= this.retries; attempt++) {
|
|
147
|
-
try {
|
|
148
|
-
const response = await fetch(url, requestOptions);
|
|
149
|
-
|
|
150
|
-
if (!response.ok) {
|
|
151
|
-
const errorData = await response.json().catch(() => ({}));
|
|
152
|
-
throw new Error(
|
|
153
|
-
`HTTP ${response.status}: ${
|
|
154
|
-
errorData.detail || response.statusText
|
|
155
|
-
}`,
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const text = await response.text();
|
|
160
|
-
|
|
161
|
-
// Replace large integers (greater than MAX_SAFE_INTEGER) with quoted strings
|
|
162
|
-
// This regex finds numbers that are likely to be large integers in the "data" field
|
|
163
|
-
const MAX_SAFE_INTEGER_STR = "9007199254740991";
|
|
164
|
-
const largeIntegerRegex = /"data"\s*:\s*(\d{16,})/g;
|
|
165
|
-
|
|
166
|
-
const modifiedText = text.replace(
|
|
167
|
-
largeIntegerRegex,
|
|
168
|
-
(match, largeInt) => {
|
|
169
|
-
// Compare as strings to avoid precision loss
|
|
170
|
-
if (
|
|
171
|
-
largeInt.length > MAX_SAFE_INTEGER_STR.length ||
|
|
172
|
-
(largeInt.length === MAX_SAFE_INTEGER_STR.length &&
|
|
173
|
-
largeInt > MAX_SAFE_INTEGER_STR)
|
|
174
|
-
) {
|
|
175
|
-
// Replace the number with a quoted string to preserve precision
|
|
176
|
-
return `"data":"${largeInt}"`;
|
|
177
|
-
}
|
|
178
|
-
return match; // Keep original if it's a safe integer
|
|
179
|
-
},
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
const data = JSON.parse(modifiedText);
|
|
183
|
-
|
|
184
|
-
if (data && typeof data.data === "string" && /^\d+$/.test(data.data)) {
|
|
185
|
-
const numValue = Number(data.data);
|
|
186
|
-
if (Number.isSafeInteger(numValue)) {
|
|
187
|
-
data.data = numValue;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return data;
|
|
192
|
-
} catch (error) {
|
|
193
|
-
lastError = error as Error;
|
|
194
|
-
|
|
195
|
-
if (attempt < this.retries) {
|
|
196
|
-
// Exponential backoff
|
|
197
|
-
const delay = Math.pow(2, attempt) * 1000;
|
|
198
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
throw lastError || new Error("Request failed after all retries");
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
private async resolveTradingRules(
|
|
207
|
-
marketName: string,
|
|
208
|
-
): Promise<ExtendedTradingRules> {
|
|
209
|
-
const cached = this.marketTradingRulesCache.get(marketName);
|
|
210
|
-
if (cached) return cached;
|
|
211
|
-
const existing = this.marketTradingRulesInflight.get(marketName);
|
|
212
|
-
if (existing) return existing;
|
|
213
|
-
const inflight = (async () => {
|
|
214
|
-
const res = await this.getMarkets(marketName);
|
|
215
|
-
if (res.status !== "OK") {
|
|
216
|
-
throw new Error(
|
|
217
|
-
`ExtendedWrapper: getMarkets failed for ${marketName}: ${res.message}`,
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
const rows = res.data;
|
|
221
|
-
if (!Array.isArray(rows) || rows.length === 0) {
|
|
222
|
-
throw new Error(
|
|
223
|
-
`ExtendedWrapper: empty markets response for ${marketName}`,
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
const row = rows.find((m) => asRecord(m)?.name === marketName);
|
|
227
|
-
if (!row) {
|
|
228
|
-
throw new Error(
|
|
229
|
-
`ExtendedWrapper: market ${marketName} not found in markets list`,
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
const rules = tradingRulesFromMarketRow(marketName, row);
|
|
233
|
-
this.marketTradingRulesCache.set(marketName, rules);
|
|
234
|
-
return rules;
|
|
235
|
-
})();
|
|
236
|
-
this.marketTradingRulesInflight.set(marketName, inflight);
|
|
237
|
-
void inflight.finally(() => {
|
|
238
|
-
if (this.marketTradingRulesInflight.get(marketName) === inflight) {
|
|
239
|
-
this.marketTradingRulesInflight.delete(marketName);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
return inflight;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Create a new order on Extended Exchange
|
|
247
|
-
*/
|
|
248
|
-
async createOrder(
|
|
249
|
-
request: CreateOrderRequest,
|
|
250
|
-
): Promise<ExtendedApiResponse<PlacedOrder>> {
|
|
251
|
-
const rules = await this.resolveTradingRules(request.market_name);
|
|
252
|
-
const amountBn = new BigNumber(String(request.amount).trim());
|
|
253
|
-
const priceBn = new BigNumber(String(request.price).trim());
|
|
254
|
-
if (!amountBn.isFinite() || amountBn.lte(0)) {
|
|
255
|
-
throw new Error(`ExtendedWrapper: invalid order amount=${request.amount}`);
|
|
256
|
-
}
|
|
257
|
-
if (!priceBn.isFinite() || priceBn.lte(0)) {
|
|
258
|
-
throw new Error(`ExtendedWrapper: invalid order price=${request.price}`);
|
|
259
|
-
}
|
|
260
|
-
if (amountBn.lt(rules.minOrderSize)) {
|
|
261
|
-
throw new Error(
|
|
262
|
-
`ExtendedWrapper: order amount ${request.amount} is below minOrderSize ${rules.minOrderSize.toFixed()} for ${request.market_name}`,
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
const adjAmount = roundToStepBn(amountBn, rules.qtyStep);
|
|
266
|
-
const adjPrice = roundToStepBn(priceBn, rules.priceStep);
|
|
267
|
-
if (adjAmount.lt(rules.minOrderSize)) {
|
|
268
|
-
throw new Error(
|
|
269
|
-
`ExtendedWrapper: amount after tick rounding ${formatBnForApi(adjAmount, rules.qtyStep)} is below minOrderSize ${rules.minOrderSize.toFixed()} (${request.market_name})`,
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
const payload: CreateOrderRequest = {
|
|
273
|
-
...request,
|
|
274
|
-
amount: formatBnForApi(adjAmount, rules.qtyStep),
|
|
275
|
-
price: formatBnForApi(adjPrice, rules.priceStep),
|
|
276
|
-
};
|
|
277
|
-
return this.makeRequest<PlacedOrder>("/api/v1/orders", false, {
|
|
278
|
-
method: "POST",
|
|
279
|
-
body: JSON.stringify(payload),
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Get all markets
|
|
285
|
-
*/
|
|
286
|
-
async getMarkets(
|
|
287
|
-
marketNames?: string,
|
|
288
|
-
): Promise<ExtendedApiResponse<Market[]>> {
|
|
289
|
-
const params = marketNames
|
|
290
|
-
? `?market_names=${encodeURIComponent(marketNames)}`
|
|
291
|
-
: "";
|
|
292
|
-
return this.makeRequest<Market[]>(`/api/v1/markets${params}`, false);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
*
|
|
297
|
-
* @param orderId - The ID of the order to get
|
|
298
|
-
* @returns The order
|
|
299
|
-
*/
|
|
300
|
-
async getOrderByOrderId(
|
|
301
|
-
orderId: string,
|
|
302
|
-
): Promise<ExtendedApiResponse<OpenOrder>> {
|
|
303
|
-
const orderIdInt = parseInt(orderId);
|
|
304
|
-
return this.makeRequest<OpenOrder>(`/api/v1/orderId/${orderIdInt}`, false);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Get market statistics for a specific market
|
|
309
|
-
*/
|
|
310
|
-
async getMarketStatistics(
|
|
311
|
-
marketName: string,
|
|
312
|
-
): Promise<ExtendedApiResponse<MarketStats>> {
|
|
313
|
-
return this.makeRequest<MarketStats>(
|
|
314
|
-
`/api/v1/markets/statistics?market_name=${encodeURIComponent(marketName)}`,
|
|
315
|
-
false,
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Get current trading positions
|
|
321
|
-
*/
|
|
322
|
-
async getPositions(
|
|
323
|
-
marketNames?: string,
|
|
324
|
-
): Promise<ExtendedApiResponse<Position[]>> {
|
|
325
|
-
const params = marketNames
|
|
326
|
-
? `?market_names=${encodeURIComponent(marketNames)}`
|
|
327
|
-
: "";
|
|
328
|
-
const response = await this.makeRequest<Position[]>(`/api/v1/positions${params}`, true);
|
|
329
|
-
return response;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* Get account balance and holdings
|
|
334
|
-
*/
|
|
335
|
-
async getHoldings(): Promise<ExtendedApiResponse<Balance>> {
|
|
336
|
-
return this.makeRequest<Balance>("/api/v1/holdings", true);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Initiate a withdrawal from Extended Exchange
|
|
341
|
-
* Returns data as number | string to preserve precision for large integers
|
|
342
|
-
*/
|
|
343
|
-
async withdraw(
|
|
344
|
-
request: WithdrawRequest,
|
|
345
|
-
): Promise<ExtendedApiResponse<number | string>> {
|
|
346
|
-
return this.makeRequest<number | string>("/api/v1/withdraw", false, {
|
|
347
|
-
method: "POST",
|
|
348
|
-
body: JSON.stringify(request),
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Create and sign a withdrawal request hash
|
|
354
|
-
*/
|
|
355
|
-
async signWithdrawalRequest(request: SignedWithdrawRequest): Promise<
|
|
356
|
-
ExtendedApiResponse<{
|
|
357
|
-
withdraw_request_hash: string;
|
|
358
|
-
signature: {
|
|
359
|
-
r: string;
|
|
360
|
-
s: string;
|
|
361
|
-
};
|
|
362
|
-
}>
|
|
363
|
-
> {
|
|
364
|
-
return this.makeRequest("/api/v1/withdraw/sign", false, {
|
|
365
|
-
method: "POST",
|
|
366
|
-
body: JSON.stringify(request),
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Cancel an existing order
|
|
372
|
-
*/
|
|
373
|
-
async cancelOrder(
|
|
374
|
-
request: CancelOrderRequest,
|
|
375
|
-
): Promise<ExtendedApiResponse<{}>> {
|
|
376
|
-
return this.makeRequest<{}>("/api/v1/orders/cancel", false, {
|
|
377
|
-
method: "POST",
|
|
378
|
-
body: JSON.stringify(request),
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Get all open orders
|
|
384
|
-
*/
|
|
385
|
-
async getOpenOrders(
|
|
386
|
-
marketName?: string,
|
|
387
|
-
): Promise<ExtendedApiResponse<OpenOrder[]>> {
|
|
388
|
-
const endpoint = marketName
|
|
389
|
-
? `/api/v1/marketOrders/${marketName}`
|
|
390
|
-
: "/api/v1/marketOrders";
|
|
391
|
-
return this.makeRequest<OpenOrder[]>(endpoint, false, {
|
|
392
|
-
method: "GET",
|
|
393
|
-
headers: {
|
|
394
|
-
"Content-Type": "application/json",
|
|
395
|
-
},
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Update leverage on the market
|
|
401
|
-
* @param request
|
|
402
|
-
* @returns
|
|
403
|
-
*/
|
|
404
|
-
async updateLeverage(
|
|
405
|
-
request: UpdateLeverageRequest,
|
|
406
|
-
): Promise<ExtendedApiResponse<{}>> {
|
|
407
|
-
return this.makeRequest<{}>("/api/v1/leverage", false, {
|
|
408
|
-
method: "POST",
|
|
409
|
-
body: JSON.stringify(request),
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Get asset operations with optional filtering
|
|
415
|
-
*/
|
|
416
|
-
async getAssetOperations(
|
|
417
|
-
options: {
|
|
418
|
-
id?: number;
|
|
419
|
-
operationsType?: AssetOperationType[];
|
|
420
|
-
operationsStatus?: AssetOperationStatus[];
|
|
421
|
-
startTime?: number;
|
|
422
|
-
endTime?: number;
|
|
423
|
-
cursor?: number;
|
|
424
|
-
limit?: number;
|
|
425
|
-
} = {},
|
|
426
|
-
): Promise<ExtendedApiResponse<AssetOperation[]>> {
|
|
427
|
-
const params = new URLSearchParams();
|
|
428
|
-
|
|
429
|
-
if (options.id !== undefined) params.append("id", options.id.toString());
|
|
430
|
-
if (options.operationsType) {
|
|
431
|
-
params.append("operations_type", options.operationsType.join(","));
|
|
432
|
-
}
|
|
433
|
-
if (options.operationsStatus) {
|
|
434
|
-
params.append("operations_status", options.operationsStatus.join(","));
|
|
435
|
-
}
|
|
436
|
-
if (options.startTime !== undefined)
|
|
437
|
-
params.append("start_time", options.startTime.toString());
|
|
438
|
-
if (options.endTime !== undefined)
|
|
439
|
-
params.append("end_time", options.endTime.toString());
|
|
440
|
-
if (options.cursor !== undefined)
|
|
441
|
-
params.append("cursor", options.cursor.toString());
|
|
442
|
-
if (options.limit !== undefined)
|
|
443
|
-
params.append("limit", options.limit.toString());
|
|
444
|
-
|
|
445
|
-
const queryString = params.toString();
|
|
446
|
-
const endpoint = `/api/v1/asset-operations${
|
|
447
|
-
queryString ? `?${queryString}` : ""
|
|
448
|
-
}`;
|
|
449
|
-
|
|
450
|
-
return this.makeRequest<AssetOperation[]>(endpoint, false);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Health check endpoint
|
|
455
|
-
*/
|
|
456
|
-
async healthCheck(): Promise<ExtendedApiResponse<MarketStats>> {
|
|
457
|
-
return this.makeRequest<MarketStats>("/api/v1/health", false);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Convenience method to create a buy order
|
|
462
|
-
*/
|
|
463
|
-
async createBuyOrder(
|
|
464
|
-
marketName: string,
|
|
465
|
-
amount: string,
|
|
466
|
-
price: string,
|
|
467
|
-
options: {
|
|
468
|
-
post_only?: boolean;
|
|
469
|
-
reduce_only?: boolean;
|
|
470
|
-
previous_order_id?: number;
|
|
471
|
-
external_id?: string;
|
|
472
|
-
time_in_force?: TimeInForce;
|
|
473
|
-
} = {},
|
|
474
|
-
): Promise<ExtendedApiResponse<PlacedOrder>> {
|
|
475
|
-
return this.createOrder({
|
|
476
|
-
market_name: marketName,
|
|
477
|
-
amount,
|
|
478
|
-
price,
|
|
479
|
-
side: OrderSide.BUY,
|
|
480
|
-
...options,
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* Get order by ID
|
|
486
|
-
* @param orderId - The ID of the order to get
|
|
487
|
-
* @returns The order
|
|
488
|
-
*/
|
|
489
|
-
async getOrderById(orderId: number): Promise<ExtendedApiResponse<OpenOrder>> {
|
|
490
|
-
return this.makeRequest<OpenOrder>(`/api/v1/orderId/${orderId}`, false);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
/**
|
|
494
|
-
* Convenience method to create a sell order
|
|
495
|
-
*/
|
|
496
|
-
async createSellOrder(
|
|
497
|
-
marketName: string,
|
|
498
|
-
amount: string,
|
|
499
|
-
price: string,
|
|
500
|
-
options: {
|
|
501
|
-
post_only?: boolean;
|
|
502
|
-
reduce_only?: boolean;
|
|
503
|
-
previous_order_id?: number;
|
|
504
|
-
external_id?: string;
|
|
505
|
-
time_in_force?: TimeInForce;
|
|
506
|
-
} = {},
|
|
507
|
-
): Promise<ExtendedApiResponse<PlacedOrder>> {
|
|
508
|
-
return this.createOrder({
|
|
509
|
-
market_name: marketName,
|
|
510
|
-
amount,
|
|
511
|
-
price,
|
|
512
|
-
side: OrderSide.SELL,
|
|
513
|
-
...options,
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Get positions for a specific market
|
|
519
|
-
*/
|
|
520
|
-
async getPositionsForMarket(
|
|
521
|
-
marketName: string,
|
|
522
|
-
): Promise<ExtendedApiResponse<Position[]>> {
|
|
523
|
-
return this.getPositions(marketName);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/**
|
|
527
|
-
* Get open orders for a specific market
|
|
528
|
-
*/
|
|
529
|
-
async getOpenOrdersForMarket(
|
|
530
|
-
marketName: string,
|
|
531
|
-
): Promise<ExtendedApiResponse<OpenOrder[]>> {
|
|
532
|
-
return this.getOpenOrders(marketName);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Cancel order by ID (convenience method)
|
|
537
|
-
*/
|
|
538
|
-
async cancelOrderById(orderId: number): Promise<ExtendedApiResponse<{}>> {
|
|
539
|
-
return this.cancelOrder({ order_id: orderId });
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* Get order history for a specific market
|
|
544
|
-
* @param marketName - The name of the market to get order history for
|
|
545
|
-
* @returns The order history for the specified market
|
|
546
|
-
*/
|
|
547
|
-
async getOrderHistory(
|
|
548
|
-
marketName: string,
|
|
549
|
-
): Promise<ExtendedApiResponse<OpenOrder[]>> {
|
|
550
|
-
return this.makeRequest<OpenOrder[]>(`/api/v1/marketOrders/${marketName}`, false);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Withdraw USDC (convenience method)
|
|
555
|
-
* Returns data as number | string to preserve precision for large integers
|
|
556
|
-
*/
|
|
557
|
-
async withdrawUSDC(
|
|
558
|
-
amount: string,
|
|
559
|
-
): Promise<ExtendedApiResponse<number | string>> {
|
|
560
|
-
return this.withdraw({ amount, asset: "USDC" });
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
/**
|
|
564
|
-
* Get funding rates for a specific market
|
|
565
|
-
* @param marketName - The name of the market to get funding rates for
|
|
566
|
-
* @returns The funding rates for the specified market
|
|
567
|
-
*/
|
|
568
|
-
async getFundingRates(
|
|
569
|
-
marketName: string,
|
|
570
|
-
side: string,
|
|
571
|
-
startTime?: number,
|
|
572
|
-
endTime?: number,
|
|
573
|
-
// in epoch milliseconds
|
|
574
|
-
): Promise<ExtendedApiResponse<FundingRate[]>> {
|
|
575
|
-
const endTimeParam = endTime !== undefined ? `&end_time=${endTime}` : "";
|
|
576
|
-
const startTimeParam =
|
|
577
|
-
startTime !== undefined ? `&start_time=${startTime}` : "";
|
|
578
|
-
const response = await this.makeRequest<FundingRate[]>(
|
|
579
|
-
`/api/v1/markets/funding-rates?market_name=${encodeURIComponent(
|
|
580
|
-
marketName,
|
|
581
|
-
)}&side=${encodeURIComponent(side)}${startTimeParam}${endTimeParam}`,
|
|
582
|
-
true
|
|
583
|
-
);
|
|
584
|
-
return response;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
/**
|
|
588
|
-
* Get funding payments for a specific market.
|
|
589
|
-
*/
|
|
590
|
-
async getUserFundingPayments(
|
|
591
|
-
marketName: string,
|
|
592
|
-
side: string,
|
|
593
|
-
startTime: number,
|
|
594
|
-
limit?: number,
|
|
595
|
-
cursor?: number,
|
|
596
|
-
): Promise<ExtendedApiResponse<FundingPayment[]>> {
|
|
597
|
-
const params = new URLSearchParams();
|
|
598
|
-
params.append("start_time", String(startTime));
|
|
599
|
-
params.append("market_names", marketName);
|
|
600
|
-
params.append("side", side);
|
|
601
|
-
if (limit !== undefined) params.append("limit", String(limit));
|
|
602
|
-
if (cursor !== undefined) params.append("cursor", String(cursor));
|
|
603
|
-
|
|
604
|
-
return this.makeRequest<FundingPayment[]>(
|
|
605
|
-
`/api/v1/account/funding-payments?${params.toString()}`,
|
|
606
|
-
true,
|
|
607
|
-
);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
export default ExtendedWrapper;
|