@2bad/walt 1.0.1 → 2.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.
@@ -0,0 +1,510 @@
1
+ import { WaltRequestError } from "../transport.js";
2
+ // source/cli/run.ts
3
+ var UsageError = class extends Error {};
4
+ const COMMANDS = `Commands:
5
+ balances [--all] every asset: spot, staked and held by limit orders,
6
+ and with --all the ones worth less than 0.01
7
+ history [--monthly] balance, deposits, withdrawals and P/L per day or month
8
+ [--from DATE] start date, YYYY-MM-DD (default: 30 days or 12 months back)
9
+ transactions latest transactions
10
+ [--asset SYM] only this asset
11
+ [--limit N] how many (default 20)
12
+ price SYM... current price and change over 24h, 7d and 30d
13
+ quote FROM TO AMOUNT what an exchange would give right now, without making it
14
+ orders [--all] open limit orders, or every order with --all
15
+ perps [--closed] open perpetual positions, or closed ones
16
+ earn [--all] your earn stakes, or every active campaign with --all`;
17
+ const fixed = (value, digits = 2) => {
18
+ const parsed = Number(value);
19
+ return value === null || value === void 0 || value === "" || !Number.isFinite(parsed) ? "-" : parsed.toFixed(digits);
20
+ };
21
+ const trimmed = (value) => {
22
+ const parsed = Number(value);
23
+ if (value === null || value === void 0 || value === "" || !Number.isFinite(parsed)) return "-";
24
+ return String(Number(parsed.toFixed(8)));
25
+ };
26
+ const significant = (value) => Number.isFinite(value) ? String(Number(value.toPrecision(8))) : "-";
27
+ const percent = (value) => Number.isFinite(value) ? `${value >= 0 ? "+" : ""}${(value * 100).toFixed(2)}%` : "-";
28
+ const change = (now, then) => then === void 0 || then === 0 ? "-" : percent(now / then - 1);
29
+ const minute = (timestamp) => timestamp.slice(0, 16).replace("T", " ");
30
+ const isoDate = (date) => date.toISOString().slice(0, 10);
31
+ const ACCOUNT_KINDS = {
32
+ REGULAR: "spot",
33
+ EARN_V2: "earn",
34
+ HOLD_LIMIT: "orders"
35
+ };
36
+ const positiveInteger = (value, fallback) => {
37
+ if (value === void 0) return fallback;
38
+ const parsed = Number(value);
39
+ if (!Number.isSafeInteger(parsed) || parsed < 1) throw new UsageError(`--limit must be a whole number, got ${value}`);
40
+ return parsed;
41
+ };
42
+ const balances = async (client, fiat, options) => {
43
+ const data = await client.balances(fiat);
44
+ const total = Number(data.overall_available_balance_fiat_amount);
45
+ const held = data.accounts.filter((account) => Number(account.total_balance) > 0).map((account) => ({
46
+ account,
47
+ value: Number(account.available_balance_fiat_amount)
48
+ }));
49
+ const shown = options.all ? held : held.filter(({ value }) => !(value < .005));
50
+ const rows = shown.sort((a, b) => b.value - a.value).map(({ account, value }) => ({
51
+ asset: account.currency,
52
+ kind: ACCOUNT_KINDS[account.account_type] ?? account.account_type.toLowerCase(),
53
+ amount: trimmed(account.total_balance),
54
+ value: value.toFixed(2),
55
+ share: total > 0 ? `${(value / total * 100).toFixed(1)}%` : "-"
56
+ }));
57
+ return {
58
+ columns: [
59
+ {
60
+ key: "asset",
61
+ title: "ASSET"
62
+ },
63
+ {
64
+ key: "kind",
65
+ title: "KIND"
66
+ },
67
+ {
68
+ key: "amount",
69
+ title: "AMOUNT",
70
+ numeric: true
71
+ },
72
+ {
73
+ key: "value",
74
+ title: `VALUE ${data.fiat_currency}`,
75
+ numeric: true
76
+ },
77
+ {
78
+ key: "share",
79
+ title: "SHARE",
80
+ numeric: true
81
+ }
82
+ ],
83
+ rows,
84
+ footer: [`total ${total.toFixed(2)} ${data.fiat_currency}`, ...shown.length < held.length ? [`${held.length - shown.length} worth less than 0.01 not shown, --all lists them`] : []]
85
+ };
86
+ };
87
+ const history = async (client, options) => {
88
+ const start = /* @__PURE__ */ new Date();
89
+ if (options.monthly) start.setUTCMonth(start.getUTCMonth() - 11, 1);
90
+ else start.setUTCDate(start.getUTCDate() - 29);
91
+ const from = options.from ?? isoDate(start);
92
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(from)) throw new UsageError(`--from must be YYYY-MM-DD, got ${from}`);
93
+ const data = await client.portfolioHistory(from, options.monthly ? "1m" : "1d");
94
+ const period = (dateFrom) => options.monthly ? dateFrom.slice(0, 7) : dateFrom.slice(0, 10);
95
+ const rows = data.chart.data_points.map((point) => ({
96
+ period: period(point.date_from),
97
+ balance: fixed(point.close_amount_fiat),
98
+ deposits: fixed(point.deposits_details.total),
99
+ withdrawals: fixed(point.withdrawals_details.total),
100
+ pnl: fixed(point.total_pnl),
101
+ pnlPercent: point.total_pnl_percent === null ? "-" : `${fixed(point.total_pnl_percent)}%`
102
+ }));
103
+ const total = data.total_period_details;
104
+ return {
105
+ columns: [
106
+ {
107
+ key: "period",
108
+ title: options.monthly ? "MONTH" : "DAY"
109
+ },
110
+ {
111
+ key: "balance",
112
+ title: `BALANCE ${data.fiat_currency}`,
113
+ numeric: true
114
+ },
115
+ {
116
+ key: "deposits",
117
+ title: "DEPOSITS",
118
+ numeric: true
119
+ },
120
+ {
121
+ key: "withdrawals",
122
+ title: "WITHDRAWALS",
123
+ numeric: true
124
+ },
125
+ {
126
+ key: "pnl",
127
+ title: "P/L",
128
+ numeric: true
129
+ },
130
+ {
131
+ key: "pnlPercent",
132
+ title: "P/L %",
133
+ numeric: true
134
+ }
135
+ ],
136
+ rows,
137
+ footer: [`since ${from}: P/L ${fixed(total.total_pnl)} ${data.fiat_currency}` + (total.total_pnl_percent === null ? "" : ` (${fixed(total.total_pnl_percent)}%)`) + `, deposits ${fixed(total.deposits_details.total)}, withdrawals ${fixed(total.withdrawals_details.total)}`, "as reported by Walt"]
138
+ };
139
+ };
140
+ const transactions = async (client, options) => {
141
+ const limit = positiveInteger(options.limit, 20);
142
+ return {
143
+ columns: [
144
+ {
145
+ key: "time",
146
+ title: "TIME (UTC)"
147
+ },
148
+ {
149
+ key: "type",
150
+ title: "TYPE"
151
+ },
152
+ {
153
+ key: "gateway",
154
+ title: "VIA"
155
+ },
156
+ {
157
+ key: "amount",
158
+ title: "AMOUNT",
159
+ numeric: true
160
+ },
161
+ {
162
+ key: "asset",
163
+ title: "ASSET"
164
+ },
165
+ {
166
+ key: "status",
167
+ title: "STATUS"
168
+ }
169
+ ],
170
+ rows: (options.asset ? await client.accountTransactions(options.asset, limit) : await client.transactions(limit)).transactions.map((row) => ({
171
+ time: minute(row.created_at),
172
+ type: row.type,
173
+ gateway: row.gateway,
174
+ amount: trimmed(row.amount),
175
+ asset: row.currency,
176
+ status: row.status
177
+ }))
178
+ };
179
+ };
180
+ const price = async (client, symbols, fiat) => {
181
+ if (symbols.length === 0) throw new UsageError("price needs at least one symbol, such as `walt price BTC`");
182
+ const rows = await Promise.all(symbols.map(async (symbol) => {
183
+ const charts = await client.charts(symbol, fiat);
184
+ const rates = (points) => points.map((point) => Number(point.rate));
185
+ const day = rates(charts.day);
186
+ const last = day.at(-1) ?? rates(charts.month).at(-1);
187
+ if (last === void 0) return {
188
+ asset: symbol,
189
+ price: "-",
190
+ day: "-",
191
+ week: "-",
192
+ month: "-"
193
+ };
194
+ return {
195
+ asset: symbol,
196
+ price: significant(last),
197
+ day: change(last, day[0]),
198
+ week: change(last, rates(charts.week)[0]),
199
+ month: change(last, rates(charts.month)[0])
200
+ };
201
+ }));
202
+ return {
203
+ columns: [
204
+ {
205
+ key: "asset",
206
+ title: "ASSET"
207
+ },
208
+ {
209
+ key: "price",
210
+ title: `PRICE ${fiat}`,
211
+ numeric: true
212
+ },
213
+ {
214
+ key: "day",
215
+ title: "24H",
216
+ numeric: true
217
+ },
218
+ {
219
+ key: "week",
220
+ title: "7D",
221
+ numeric: true
222
+ },
223
+ {
224
+ key: "month",
225
+ title: "30D",
226
+ numeric: true
227
+ }
228
+ ],
229
+ rows
230
+ };
231
+ };
232
+ const quoteSizes = (amount) => {
233
+ const [whole = "", fraction = ""] = amount.split(".");
234
+ const sizes = [amount, ...[
235
+ 6,
236
+ 4,
237
+ 2,
238
+ 0
239
+ ].filter((places) => places < fraction.length).map((places) => places === 0 ? whole : `${whole}.${fraction.slice(0, places)}`)];
240
+ return [...new Set(sizes)].filter((size) => Number(size) > 0);
241
+ };
242
+ const quote = async (client, args) => {
243
+ const [from, to, amount] = args;
244
+ if (!from || !to || amount === void 0 || !/^\d+(\.\d+)?$/.test(amount) || !(Number(amount) > 0)) throw new UsageError("usage: walt quote FROM TO AMOUNT, such as `walt quote USDT BTC 100`");
245
+ let result;
246
+ let size = amount;
247
+ let rejection;
248
+ for (const candidate of quoteSizes(amount)) try {
249
+ result = await client.quote(from, to, Number(candidate));
250
+ size = candidate;
251
+ break;
252
+ } catch (error) {
253
+ if (!(error instanceof WaltRequestError) || error.body?.code !== "invalid_amount") throw error;
254
+ rejection = error;
255
+ }
256
+ if (result === void 0) throw rejection;
257
+ const sale = result.to_currency === "USDT" && result.from_currency !== "USDT";
258
+ const price = result.from_amount <= 0 || result.to_amount <= 0 ? "-" : sale ? `${significant(result.to_amount / result.from_amount)} USDT/${result.from_currency}` : `${significant(result.from_amount / result.to_amount)} ${result.from_currency}/${result.to_currency}`;
259
+ const footer = [`order size ${result.min_amount} to ${result.max_amount} ${from}`, "fees included, nothing was exchanged"];
260
+ if (size !== amount) footer.unshift(`amount cut to ${size} ${from}, the most decimals it accepts`);
261
+ return {
262
+ columns: [
263
+ {
264
+ key: "pay",
265
+ title: "PAY",
266
+ numeric: true
267
+ },
268
+ {
269
+ key: "receive",
270
+ title: "RECEIVE",
271
+ numeric: true
272
+ },
273
+ {
274
+ key: "price",
275
+ title: "PRICE",
276
+ numeric: true
277
+ }
278
+ ],
279
+ rows: [{
280
+ pay: `${result.from_amount} ${result.from_currency}`,
281
+ receive: `${result.to_amount} ${result.to_currency}`,
282
+ price
283
+ }],
284
+ footer
285
+ };
286
+ };
287
+ const orders = async (client, options) => {
288
+ const list = await client.limitOrders(options.all ? { limit: 100 } : {
289
+ status: ["OPEN", "CANCELLING"],
290
+ limit: 100
291
+ });
292
+ const held = list.filter((order) => order.status === "OPEN").reduce((sum, order) => sum + Number(order.total), 0);
293
+ return {
294
+ columns: [
295
+ {
296
+ key: "created",
297
+ title: "CREATED (UTC)"
298
+ },
299
+ {
300
+ key: "asset",
301
+ title: "ASSET"
302
+ },
303
+ {
304
+ key: "side",
305
+ title: "SIDE"
306
+ },
307
+ {
308
+ key: "limit",
309
+ title: "LIMIT",
310
+ numeric: true
311
+ },
312
+ {
313
+ key: "quantity",
314
+ title: "QUANTITY",
315
+ numeric: true
316
+ },
317
+ {
318
+ key: "total",
319
+ title: "TOTAL",
320
+ numeric: true
321
+ },
322
+ {
323
+ key: "fee",
324
+ title: "FEE",
325
+ numeric: true
326
+ },
327
+ {
328
+ key: "status",
329
+ title: "STATUS"
330
+ }
331
+ ],
332
+ rows: list.map((order) => ({
333
+ created: minute(order.created_at),
334
+ asset: order.base_currency,
335
+ side: order.side,
336
+ limit: order.price_limit,
337
+ quantity: order.quantity,
338
+ total: `${order.total} ${order.fee_currency}`,
339
+ fee: order.fee,
340
+ status: order.status
341
+ })),
342
+ footer: [`${held.toFixed(2)} USDT held by open orders`]
343
+ };
344
+ };
345
+ const perps = async (client, options) => {
346
+ const positions = await client.perpPositions({ statuses: [options.closed ? "closed" : "open"] });
347
+ const columns = [
348
+ {
349
+ key: "contract",
350
+ title: "CONTRACT"
351
+ },
352
+ {
353
+ key: "side",
354
+ title: "SIDE"
355
+ },
356
+ {
357
+ key: "leverage",
358
+ title: "LEV",
359
+ numeric: true
360
+ },
361
+ {
362
+ key: "size",
363
+ title: "SIZE",
364
+ numeric: true
365
+ },
366
+ {
367
+ key: "entry",
368
+ title: "ENTRY",
369
+ numeric: true
370
+ },
371
+ {
372
+ key: "margin",
373
+ title: "MARGIN",
374
+ numeric: true
375
+ }
376
+ ];
377
+ if (options.closed) columns.push({
378
+ key: "opened",
379
+ title: "OPENED (UTC)"
380
+ }, {
381
+ key: "closed",
382
+ title: "CLOSED (UTC)"
383
+ });
384
+ else columns.push({
385
+ key: "mark",
386
+ title: "MARK",
387
+ numeric: true
388
+ }, {
389
+ key: "liquidation",
390
+ title: "LIQUIDATION",
391
+ numeric: true
392
+ }, {
393
+ key: "pnl",
394
+ title: "UNREALISED",
395
+ numeric: true
396
+ });
397
+ return {
398
+ columns,
399
+ rows: positions.map((position) => ({
400
+ contract: position.contract_name,
401
+ side: position.side,
402
+ leverage: `${position.leverage}x`,
403
+ size: trimmed(position.value_base),
404
+ entry: significant(Number(position.avg_entry_price)),
405
+ margin: fixed(position.margin_quote),
406
+ opened: minute(position.created_at),
407
+ closed: minute(position.updated_at),
408
+ mark: significant(Number(position.valuation.mark_price)),
409
+ liquidation: significant(Number(position.liquidation_price)),
410
+ pnl: fixed(position.valuation.unrealized_pnl_quote)
411
+ }))
412
+ };
413
+ };
414
+ const earn = async (client, options) => {
415
+ const { campaigns } = await client.earnCampaigns();
416
+ return {
417
+ columns: [
418
+ {
419
+ key: "campaign",
420
+ title: "CAMPAIGN"
421
+ },
422
+ {
423
+ key: "asset",
424
+ title: "ASSET"
425
+ },
426
+ {
427
+ key: "staked",
428
+ title: "STAKED",
429
+ numeric: true
430
+ },
431
+ {
432
+ key: "paid",
433
+ title: "PAID OUT",
434
+ numeric: true
435
+ },
436
+ {
437
+ key: "apy",
438
+ title: "APY",
439
+ numeric: true
440
+ },
441
+ {
442
+ key: "status",
443
+ title: "STATUS"
444
+ }
445
+ ],
446
+ rows: campaigns.filter((campaign) => options.all ? campaign.status === "active" : campaign.account !== null && Number(campaign.account.balance) > 0).map((campaign) => ({
447
+ campaign: campaign.name,
448
+ asset: campaign.account?.currency ?? campaign.deposit_currency,
449
+ staked: trimmed(campaign.account?.balance),
450
+ paid: trimmed(campaign.account?.paid_out_amount),
451
+ apy: `${fixed(Number(campaign.current_apy) * 100)}%`,
452
+ status: campaign.status
453
+ }))
454
+ };
455
+ };
456
+ const render = (report) => {
457
+ if (report.rows.length === 0) return ["nothing to show", ...report.footer ?? []].join("\n");
458
+ const widths = report.columns.map((column) => Math.max(column.title.length, ...report.rows.map((row) => (row[column.key] ?? "").length)));
459
+ const line = (cells) => cells.map((cell, index) => {
460
+ const width = widths[index] ?? 0;
461
+ return report.columns[index]?.numeric ? cell.padStart(width) : cell.padEnd(width);
462
+ }).join(" ").trimEnd();
463
+ return [
464
+ line(report.columns.map((column) => column.title)),
465
+ ...report.rows.map((row) => line(report.columns.map((column) => row[column.key] ?? ""))),
466
+ ...report.footer ?? []
467
+ ].join("\n");
468
+ };
469
+ /**
470
+ * Runs one read-only command and returns what to print.
471
+ *
472
+ * @param client - A signed-in client.
473
+ * @param command - The command name, such as `balances`.
474
+ * @param args - Positional arguments after the command.
475
+ * @param options - Parsed flags.
476
+ */
477
+ const run = async (client, command, args, options = {}) => {
478
+ const fiat = (options.fiat ?? "USD").toUpperCase();
479
+ let report;
480
+ switch (command) {
481
+ case "balances":
482
+ report = await balances(client, fiat, options);
483
+ break;
484
+ case "history":
485
+ report = await history(client, options);
486
+ break;
487
+ case "transactions":
488
+ report = await transactions(client, options);
489
+ break;
490
+ case "price":
491
+ report = await price(client, args, fiat);
492
+ break;
493
+ case "quote":
494
+ report = await quote(client, args);
495
+ break;
496
+ case "orders":
497
+ report = await orders(client, options);
498
+ break;
499
+ case "perps":
500
+ report = await perps(client, options);
501
+ break;
502
+ case "earn":
503
+ report = await earn(client, options);
504
+ break;
505
+ default: throw new UsageError(`unknown command: ${command}`);
506
+ }
507
+ if (!options.json) return render(report);
508
+ return JSON.stringify(report.rows.map((row) => Object.fromEntries(report.columns.map((column) => [column.key, row[column.key] ?? null]))), null, 2);
509
+ };
510
+ export { COMMANDS, UsageError, run };
package/build/client.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import { AccountsResponse, Charts, Coin, CoinDetails, FiatCurrency, PriceAtTime } from "./api/accounts.js";
2
2
  import { PnlResponse, PortfolioHistory } from "./api/analytics.js";
3
+ import { Balances } from "./api/balances.js";
4
+ import { CandleRequest, CandleSeries } from "./api/candles.js";
3
5
  import { EarnCampaignsResponse, EarnRate, EarnTransaction, EarnTransactionsPage } from "./api/earn.js";
4
6
  import { AvailableExchanges, Exchange, ExchangeQuote, ExchangeRequest } from "./api/exchange.js";
5
7
  import { LimitOrder, LimitOrderBounds, LimitOrderQuote, LimitOrderToken } from "./api/limit-orders.js";
8
+ import { PerpContract, PerpOrderStatus, PerpOrdersPage, PerpPosition, PerpPositionStatus, PerpSystemStatus } from "./api/perps.js";
6
9
  import { Transaction, TransactionDetails, TransactionGateway, TransactionsPage } from "./api/transactions.js";
7
10
  export type WaltClientOptions = {
8
11
  /** Called again with the rejected token after a 401, so the provider can renew it before its expiry. */
@@ -36,6 +39,12 @@ export declare class WaltClient {
36
39
  private readonly maxConcurrent;
37
40
  constructor(options: WaltClientOptions);
38
41
  accounts(): Promise<AccountsResponse>;
42
+ /**
43
+ * Every balance with its account type, including USDT held by open limit orders, which `accounts()` omits.
44
+ *
45
+ * @param fiatCurrency - Currency of the fiat amounts and the overall total.
46
+ */
47
+ balances(fiatCurrency: FiatCurrency): Promise<Balances>;
39
48
  coins(fiatCurrency: FiatCurrency): Promise<Coin[]>;
40
49
  localCurrency(): Promise<FiatCurrency>;
41
50
  transactions(limit?: number, cursor?: string): Promise<TransactionsPage>;
@@ -115,6 +124,35 @@ export declare class WaltClient {
115
124
  limitOrderBounds(baseCurrency: string): Promise<LimitOrderBounds>;
116
125
  /** Every currency a limit order can buy. */
117
126
  limitOrderTokens(): Promise<LimitOrderToken[]>;
127
+ /** @param contractId - Only this contract. */
128
+ perpContracts(contractId?: number): Promise<PerpContract[]>;
129
+ perpSystemStatus(): Promise<PerpSystemStatus>;
130
+ /**
131
+ * @param options - Filters, all optional.
132
+ * @param options.statuses - Only positions in these states. Without it, closed positions are included.
133
+ * @param options.contractId - Only this contract.
134
+ */
135
+ perpPositions(options?: {
136
+ statuses?: PerpPositionStatus[];
137
+ contractId?: number;
138
+ }): Promise<PerpPosition[]>;
139
+ /**
140
+ * @param options - Filters, all optional.
141
+ * @param options.contractId - Only this contract.
142
+ * @param options.statuses - Only orders in these states.
143
+ * @param options.limit - Most orders to return.
144
+ */
145
+ perpOrders(options?: {
146
+ contractId?: number;
147
+ statuses?: PerpOrderStatus[];
148
+ limit?: number;
149
+ }): Promise<PerpOrdersPage>;
150
+ /**
151
+ * OHLCV candles for several tickers in one request.
152
+ *
153
+ * @param requests - One per series wanted.
154
+ */
155
+ candles(requests: CandleRequest[]): Promise<CandleSeries[]>;
118
156
  coinDetails(currency: string, fiatCurrency: FiatCurrency): Promise<CoinDetails>;
119
157
  charts(currency: string, fiatCurrency: FiatCurrency): Promise<Charts>;
120
158
  priceForFiatAtTime(cryptoCurrency: string, localCurrency: FiatCurrency, amount: number | string, time: Date | string | number): Promise<PriceAtTime>;
package/build/client.js CHANGED
@@ -32,6 +32,16 @@ var WaltClient = class {
32
32
  accounts() {
33
33
  return this.transport.get("/api/v1/accounts/");
34
34
  }
35
+ /**
36
+ * Every balance with its account type, including USDT held by open limit orders, which `accounts()` omits.
37
+ *
38
+ * @param fiatCurrency - Currency of the fiat amounts and the overall total.
39
+ */
40
+ async balances(fiatCurrency) {
41
+ const query = new URLSearchParams({ fiat_currency: fiatCurrency });
42
+ const { data } = await this.transport.get(`/portmone/public-api/v1/user/accounts?${query.toString()}`);
43
+ return data;
44
+ }
35
45
  async coins(fiatCurrency) {
36
46
  const { coins } = await this.transport.get(`/api/v1/coins/list/${fiatCurrency}/`);
37
47
  return coins;
@@ -222,6 +232,51 @@ var WaltClient = class {
222
232
  const { tokens } = await this.transport.get("/emporos/public-api/orders/limit/tokens");
223
233
  return tokens;
224
234
  }
235
+ /** @param contractId - Only this contract. */
236
+ async perpContracts(contractId) {
237
+ const query = contractId === void 0 ? "" : `?${new URLSearchParams({ contract_id: String(contractId) }).toString()}`;
238
+ const { contracts } = await this.transport.get(`/perps/public-api/v1/contracts/${query}`);
239
+ return contracts;
240
+ }
241
+ perpSystemStatus() {
242
+ return this.transport.get("/perps/public-api/v1/system-status/");
243
+ }
244
+ /**
245
+ * @param options - Filters, all optional.
246
+ * @param options.statuses - Only positions in these states. Without it, closed positions are included.
247
+ * @param options.contractId - Only this contract.
248
+ */
249
+ async perpPositions(options = {}) {
250
+ const query = new URLSearchParams();
251
+ if (options.contractId !== void 0) query.set("contract_id", String(options.contractId));
252
+ for (const status of options.statuses ?? []) query.append("statuses", status);
253
+ const search = query.size === 0 ? "" : `?${query.toString()}`;
254
+ const { positions } = await this.transport.get(`/perps/public-api/v1/positions/${search}`);
255
+ return positions;
256
+ }
257
+ /**
258
+ * @param options - Filters, all optional.
259
+ * @param options.contractId - Only this contract.
260
+ * @param options.statuses - Only orders in these states.
261
+ * @param options.limit - Most orders to return.
262
+ */
263
+ perpOrders(options = {}) {
264
+ const query = new URLSearchParams();
265
+ if (options.contractId !== void 0) query.set("contract_id", String(options.contractId));
266
+ if (options.limit !== void 0) query.set("limit", String(options.limit));
267
+ for (const status of options.statuses ?? []) query.append("statuses", status);
268
+ const search = query.size === 0 ? "" : `?${query.toString()}`;
269
+ return this.transport.get(`/perps/public-api/v2/orders/${search}`);
270
+ }
271
+ /**
272
+ * OHLCV candles for several tickers in one request.
273
+ *
274
+ * @param requests - One per series wanted.
275
+ */
276
+ async candles(requests) {
277
+ const { responses } = await this.transport.post("/kandelabr/public-api/v1/candles/batch", { requests });
278
+ return responses;
279
+ }
225
280
  coinDetails(currency, fiatCurrency) {
226
281
  return this.transport.get(`/api/v1/coins/details/${encodeURIComponent(currency)}/${encodeURIComponent(fiatCurrency)}/`);
227
282
  }
@@ -0,0 +1,13 @@
1
+ import { Account, AccountAction, AccountActions, AccountAddress, AccountsResponse, ChartPoint, Charts, Coin, CoinDetails, FiatCurrency, PriceAtTime, TradingHoursPeriod, TradingHoursState } from "./api/accounts.js";
2
+ import { PnlPosition, PnlResponse, PnlTotals, PortfolioFlows, PortfolioHistory, PortfolioPeriod } from "./api/analytics.js";
3
+ import { Balance, Balances } from "./api/balances.js";
4
+ import { Candle, CandleRequest, CandleSeries } from "./api/candles.js";
5
+ import { EarnAccessPolicy, EarnAccount, EarnAmount, EarnBonus, EarnCampaign, EarnCampaignsResponse, EarnDepegInfo, EarnInterestRate, EarnPayoutPool, EarnRate, EarnTransaction, EarnTransactionsPage } from "./api/earn.js";
6
+ import { AvailableExchanges, Exchange, ExchangeQuote, ExchangeRequest } from "./api/exchange.js";
7
+ import { LimitOrder, LimitOrderBounds, LimitOrderQuote, LimitOrderToken } from "./api/limit-orders.js";
8
+ import { PerpContract, PerpOrder, PerpOrderStatus, PerpOrdersPage, PerpPosition, PerpPositionStatus, PerpSystemStatus } from "./api/perps.js";
9
+ import { NormalizedTransaction, Transaction, TransactionDetails, TransactionGateway, TransactionLeg, TransactionsPage, normalizeTransaction } from "./api/transactions.js";
10
+ import { Portfolio, PortfolioEntry, WaltClient, WaltClientOptions } from "./client.js";
11
+ import { RefreshTokenSource, RefreshTokenSourceOptions, TokenState, TokenStorage } from "./refresh.js";
12
+ import { WaltAuthError, WaltRequestError } from "./transport.js";
13
+ export { type Account, type AccountAction, type AccountActions, type AccountAddress, type AccountsResponse, type AvailableExchanges, type Balance, type Balances, type Candle, type CandleRequest, type CandleSeries, type ChartPoint, type Charts, type Coin, type CoinDetails, type EarnAccessPolicy, type EarnAccount, type EarnAmount, type EarnBonus, type EarnCampaign, type EarnCampaignsResponse, type EarnDepegInfo, type EarnInterestRate, type EarnPayoutPool, type EarnRate, type EarnTransaction, type EarnTransactionsPage, type Exchange, type ExchangeQuote, type ExchangeRequest, type FiatCurrency, type LimitOrder, type LimitOrderBounds, type LimitOrderQuote, type LimitOrderToken, type NormalizedTransaction, type PerpContract, type PerpOrder, type PerpOrderStatus, type PerpOrdersPage, type PerpPosition, type PerpPositionStatus, type PerpSystemStatus, type PnlPosition, type PnlResponse, type PnlTotals, type Portfolio, type PortfolioEntry, type PortfolioFlows, type PortfolioHistory, type PortfolioPeriod, type PriceAtTime, RefreshTokenSource, type RefreshTokenSourceOptions, type TokenState, type TokenStorage, type TradingHoursPeriod, type TradingHoursState, type Transaction, type TransactionDetails, type TransactionGateway, type TransactionLeg, type TransactionsPage, WaltAuthError, WaltClient, type WaltClientOptions, WaltRequestError, normalizeTransaction };
package/build/core.js ADDED
@@ -0,0 +1,5 @@
1
+ import { normalizeTransaction } from "./api/transactions.js";
2
+ import { WaltClient } from "./client.js";
3
+ import { RefreshTokenSource } from "./refresh.js";
4
+ import { WaltAuthError, WaltRequestError } from "./transport.js";
5
+ export { RefreshTokenSource, WaltAuthError, WaltClient, WaltRequestError, normalizeTransaction };
package/build/index.d.ts CHANGED
@@ -1,10 +1,14 @@
1
1
  import { Account, AccountAction, AccountActions, AccountAddress, AccountsResponse, ChartPoint, Charts, Coin, CoinDetails, FiatCurrency, PriceAtTime, TradingHoursPeriod, TradingHoursState } from "./api/accounts.js";
2
2
  import { PnlPosition, PnlResponse, PnlTotals, PortfolioFlows, PortfolioHistory, PortfolioPeriod } from "./api/analytics.js";
3
+ import { Balance, Balances } from "./api/balances.js";
4
+ import { Candle, CandleRequest, CandleSeries } from "./api/candles.js";
3
5
  import { EarnAccessPolicy, EarnAccount, EarnAmount, EarnBonus, EarnCampaign, EarnCampaignsResponse, EarnDepegInfo, EarnInterestRate, EarnPayoutPool, EarnRate, EarnTransaction, EarnTransactionsPage } from "./api/earn.js";
4
6
  import { AvailableExchanges, Exchange, ExchangeQuote, ExchangeRequest } from "./api/exchange.js";
5
7
  import { LimitOrder, LimitOrderBounds, LimitOrderQuote, LimitOrderToken } from "./api/limit-orders.js";
8
+ import { PerpContract, PerpOrder, PerpOrderStatus, PerpOrdersPage, PerpPosition, PerpPositionStatus, PerpSystemStatus } from "./api/perps.js";
6
9
  import { NormalizedTransaction, Transaction, TransactionDetails, TransactionGateway, TransactionLeg, TransactionsPage, normalizeTransaction } from "./api/transactions.js";
7
10
  import { Portfolio, PortfolioEntry, WaltClient, WaltClientOptions } from "./client.js";
8
- import { TelegramTokenSource, TelegramTokenSourceOptions, TokenState, TokenStorage } from "./telegram/auth.js";
11
+ import { RefreshTokenSource, RefreshTokenSourceOptions, TokenState, TokenStorage } from "./refresh.js";
9
12
  import { WaltAuthError, WaltRequestError } from "./transport.js";
10
- export { type Account, type AccountAction, type AccountActions, type AccountAddress, type AccountsResponse, type AvailableExchanges, type ChartPoint, type Charts, type Coin, type CoinDetails, type EarnAccessPolicy, type EarnAccount, type EarnAmount, type EarnBonus, type EarnCampaign, type EarnCampaignsResponse, type EarnDepegInfo, type EarnInterestRate, type EarnPayoutPool, type EarnRate, type EarnTransaction, type EarnTransactionsPage, type Exchange, type ExchangeQuote, type ExchangeRequest, type FiatCurrency, type LimitOrder, type LimitOrderBounds, type LimitOrderQuote, type LimitOrderToken, type NormalizedTransaction, type PnlPosition, type PnlResponse, type PnlTotals, type Portfolio, type PortfolioEntry, type PortfolioFlows, type PortfolioHistory, type PortfolioPeriod, type PriceAtTime, TelegramTokenSource, type TelegramTokenSourceOptions, type TokenState, type TokenStorage, type TradingHoursPeriod, type TradingHoursState, type Transaction, type TransactionDetails, type TransactionGateway, type TransactionLeg, type TransactionsPage, WaltAuthError, WaltClient, type WaltClientOptions, WaltRequestError, normalizeTransaction };
13
+ import { TelegramTokenSource, TelegramTokenSourceOptions } from "./telegram/auth.js";
14
+ export { type Account, type AccountAction, type AccountActions, type AccountAddress, type AccountsResponse, type AvailableExchanges, type Balance, type Balances, type Candle, type CandleRequest, type CandleSeries, type ChartPoint, type Charts, type Coin, type CoinDetails, type EarnAccessPolicy, type EarnAccount, type EarnAmount, type EarnBonus, type EarnCampaign, type EarnCampaignsResponse, type EarnDepegInfo, type EarnInterestRate, type EarnPayoutPool, type EarnRate, type EarnTransaction, type EarnTransactionsPage, type Exchange, type ExchangeQuote, type ExchangeRequest, type FiatCurrency, type LimitOrder, type LimitOrderBounds, type LimitOrderQuote, type LimitOrderToken, type NormalizedTransaction, type PerpContract, type PerpOrder, type PerpOrderStatus, type PerpOrdersPage, type PerpPosition, type PerpPositionStatus, type PerpSystemStatus, type PnlPosition, type PnlResponse, type PnlTotals, type Portfolio, type PortfolioEntry, type PortfolioFlows, type PortfolioHistory, type PortfolioPeriod, type PriceAtTime, RefreshTokenSource, type RefreshTokenSourceOptions, TelegramTokenSource, type TelegramTokenSourceOptions, type TokenState, type TokenStorage, type TradingHoursPeriod, type TradingHoursState, type Transaction, type TransactionDetails, type TransactionGateway, type TransactionLeg, type TransactionsPage, WaltAuthError, WaltClient, type WaltClientOptions, WaltRequestError, normalizeTransaction };