@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.
- package/README.md +18 -1
- package/build/api/balances.d.ts +23 -0
- package/build/api/balances.js +1 -0
- package/build/api/candles.d.ts +22 -0
- package/build/api/candles.js +1 -0
- package/build/api/perps.d.ts +155 -0
- package/build/api/perps.js +1 -0
- package/build/bin/quiet-localstorage.js +8 -0
- package/build/bin/walt.d.ts +1 -0
- package/build/bin/walt.js +152 -0
- package/build/cli/run.d.ts +22 -0
- package/build/cli/run.js +510 -0
- package/build/client.d.ts +38 -0
- package/build/client.js +55 -0
- package/build/core.d.ts +13 -0
- package/build/core.js +5 -0
- package/build/index.d.ts +6 -2
- package/build/index.js +4 -3
- package/build/refresh.d.ts +60 -0
- package/build/refresh.js +130 -0
- package/build/telegram/auth.d.ts +6 -35
- package/build/telegram/auth.js +18 -118
- package/build/telegram/file-storage.d.ts +1 -1
- package/build/transport.js +10 -5
- package/package.json +16 -10
- package/build/bin/login.js +0 -30
- /package/build/bin/{login.d.ts → quiet-localstorage.d.ts} +0 -0
package/build/cli/run.js
ADDED
|
@@ -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
|
}
|
package/build/core.d.ts
ADDED
|
@@ -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 {
|
|
11
|
+
import { RefreshTokenSource, RefreshTokenSourceOptions, TokenState, TokenStorage } from "./refresh.js";
|
|
9
12
|
import { WaltAuthError, WaltRequestError } from "./transport.js";
|
|
10
|
-
|
|
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 };
|