@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/README.md
CHANGED
|
@@ -21,6 +21,9 @@ npm install @2bad/walt
|
|
|
21
21
|
|
|
22
22
|
ESM only. Requires Node.js 26 or later.
|
|
23
23
|
|
|
24
|
+
`@2bad/walt/client` exports everything except `TelegramTokenSource`.
|
|
25
|
+
It imports no Node.js API and no Telegram library, for runtimes such as Cloudflare Workers.
|
|
26
|
+
|
|
24
27
|
## Quick start
|
|
25
28
|
|
|
26
29
|
```ts
|
|
@@ -36,12 +39,13 @@ await source.disconnect()
|
|
|
36
39
|
|
|
37
40
|
## Examples
|
|
38
41
|
|
|
39
|
-
- [Connecting](examples/connecting.md): Telegram credentials, token storage, retries and pacing
|
|
42
|
+
- [Connecting](examples/connecting.md): Telegram credentials, token storage, refreshing without Telegram, retries and pacing
|
|
40
43
|
- [Balances](examples/balances.md): accounts, portfolio, profit and loss, staked funds
|
|
41
44
|
- [Prices](examples/prices.md): coin rates, charts and past prices
|
|
42
45
|
- [Exchange](examples/exchange.md): available pairs, quotes, exchanges and limit orders
|
|
43
46
|
- [Transactions](examples/transactions.md): history, details and reading a transaction
|
|
44
47
|
- [Errors](examples/errors.md): `WaltRequestError`, `WaltAuthError` and what is retried
|
|
48
|
+
- [Command line](examples/cli.md): the read-only `walt` command for balances, history, prices and orders
|
|
45
49
|
|
|
46
50
|
A runnable script is in [examples/portfolio.ts](examples/portfolio.ts).
|
|
47
51
|
|
|
@@ -55,11 +59,18 @@ type TelegramTokenSource = {
|
|
|
55
59
|
disconnect(): Promise<void>
|
|
56
60
|
}
|
|
57
61
|
|
|
62
|
+
new RefreshTokenSource(options: RefreshTokenSourceOptions)
|
|
63
|
+
|
|
64
|
+
type RefreshTokenSource = {
|
|
65
|
+
token(rejected?: string): Promise<string>
|
|
66
|
+
}
|
|
67
|
+
|
|
58
68
|
new WaltClient(options: WaltClientOptions)
|
|
59
69
|
|
|
60
70
|
type WaltClient = {
|
|
61
71
|
accounts(): Promise<AccountsResponse>
|
|
62
72
|
portfolio(): Promise<Portfolio>
|
|
73
|
+
balances(fiatCurrency: FiatCurrency): Promise<Balances>
|
|
63
74
|
pnl(): Promise<PnlResponse>
|
|
64
75
|
portfolioHistory(dateFrom: Date | string, resolution: '1d' | '1m'): Promise<PortfolioHistory>
|
|
65
76
|
frozenBalances<T = unknown>(): Promise<T[]>
|
|
@@ -74,6 +85,7 @@ type WaltClient = {
|
|
|
74
85
|
charts(currency: string, fiatCurrency: FiatCurrency): Promise<Charts>
|
|
75
86
|
priceForFiatAtTime(crypto: string, fiat: FiatCurrency, amount: number | string, time: Date | string | number): Promise<PriceAtTime>
|
|
76
87
|
localCurrency(): Promise<FiatCurrency>
|
|
88
|
+
candles(requests: CandleRequest[]): Promise<CandleSeries[]>
|
|
77
89
|
|
|
78
90
|
availableExchanges(): Promise<AvailableExchanges>
|
|
79
91
|
quote(fromCurrency: string, toCurrency: string, fromAmount: number): Promise<ExchangeQuote>
|
|
@@ -85,6 +97,11 @@ type WaltClient = {
|
|
|
85
97
|
limitOrderBounds(baseCurrency: string): Promise<LimitOrderBounds>
|
|
86
98
|
limitOrderTokens(): Promise<LimitOrderToken[]>
|
|
87
99
|
|
|
100
|
+
perpContracts(contractId?: number): Promise<PerpContract[]>
|
|
101
|
+
perpSystemStatus(): Promise<PerpSystemStatus>
|
|
102
|
+
perpPositions(options?: { statuses?: PerpPositionStatus[]; contractId?: number }): Promise<PerpPosition[]>
|
|
103
|
+
perpOrders(options?: { contractId?: number; statuses?: PerpOrderStatus[]; limit?: number }): Promise<PerpOrdersPage>
|
|
104
|
+
|
|
88
105
|
transactions(limit?: number, cursor?: string): Promise<TransactionsPage>
|
|
89
106
|
accountTransactions(currency: string, limit?: number, cursor?: string): Promise<TransactionsPage>
|
|
90
107
|
allTransactions(limit?: number): AsyncGenerator<Transaction>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type Balance = {
|
|
2
|
+
/** `REGULAR` for spot, `HOLD_LIMIT` for USDT reserved by open limit orders, `EARN_V2` for staked funds. */
|
|
3
|
+
account_type: string;
|
|
4
|
+
currency: string;
|
|
5
|
+
asset_currency: string;
|
|
6
|
+
total_balance: string;
|
|
7
|
+
available_balance: string;
|
|
8
|
+
balance_hold: string;
|
|
9
|
+
is_always_on_main: boolean;
|
|
10
|
+
category: string;
|
|
11
|
+
rate_to_fiat: string;
|
|
12
|
+
rate_to_usd: string;
|
|
13
|
+
available_balance_fiat_amount: string;
|
|
14
|
+
available_balance_usd_amount: string;
|
|
15
|
+
};
|
|
16
|
+
export type Balances = {
|
|
17
|
+
accounts: Balance[];
|
|
18
|
+
fiat_currency: string;
|
|
19
|
+
/** Spot, staked and limit order holds together. */
|
|
20
|
+
overall_available_balance_fiat_amount: string;
|
|
21
|
+
/** Also `true` when the perps account has no open position. */
|
|
22
|
+
has_open_perp_position: boolean;
|
|
23
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type CandleRequest = {
|
|
2
|
+
/** `<currency>/USD/SPOT`, or `<base>/USD/PERP_TRADE` for a perps contract. */
|
|
3
|
+
ticker: string;
|
|
4
|
+
/** Accepted: `1m`, `5m`, `15m`, `1h`, `4h`, `1d`, `1w`, `1mo`. */
|
|
5
|
+
resolution: string;
|
|
6
|
+
/** At least 1. The whole batch may ask for 3000 candles at most. */
|
|
7
|
+
limit: number;
|
|
8
|
+
};
|
|
9
|
+
export type Candle = {
|
|
10
|
+
o: string;
|
|
11
|
+
h: string;
|
|
12
|
+
l: string;
|
|
13
|
+
c: string;
|
|
14
|
+
v: string;
|
|
15
|
+
};
|
|
16
|
+
export type CandleSeries = {
|
|
17
|
+
ticker: string;
|
|
18
|
+
resolution: string;
|
|
19
|
+
/** Opening time of the first candle, in ms. */
|
|
20
|
+
start_ts: number;
|
|
21
|
+
candles: Candle[];
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
export type PerpContract = {
|
|
2
|
+
contract_id: number;
|
|
3
|
+
contract_name: string;
|
|
4
|
+
base_asset: string;
|
|
5
|
+
quote_asset: string;
|
|
6
|
+
venue_status: string;
|
|
7
|
+
is_active: boolean;
|
|
8
|
+
price_decimals: number;
|
|
9
|
+
size_decimals: number;
|
|
10
|
+
tick_size: string;
|
|
11
|
+
step_size: string;
|
|
12
|
+
min_size_base: string;
|
|
13
|
+
max_size_base: string;
|
|
14
|
+
max_size_quote: string;
|
|
15
|
+
min_size_quote: string;
|
|
16
|
+
max_leverage: number;
|
|
17
|
+
maker_fee_pct: string;
|
|
18
|
+
taker_fee_pct: string;
|
|
19
|
+
base_taker_fee_pct: string;
|
|
20
|
+
taker_fee_subscription_id: number;
|
|
21
|
+
price_slippage: string;
|
|
22
|
+
tpsl_buffer_pct: string;
|
|
23
|
+
funding_rate_hourly: string;
|
|
24
|
+
next_funding_at: string;
|
|
25
|
+
open_interest_usd: string;
|
|
26
|
+
volume_24h_usd: string;
|
|
27
|
+
trading_hours_state: unknown;
|
|
28
|
+
market_data: {
|
|
29
|
+
server_time: string;
|
|
30
|
+
/** `fresh`, or `stale` with both prices `null`. */
|
|
31
|
+
status: string;
|
|
32
|
+
mark_price: string | null;
|
|
33
|
+
index_price: string | null;
|
|
34
|
+
source_timestamp: string;
|
|
35
|
+
expires_at: string;
|
|
36
|
+
};
|
|
37
|
+
/** Fractions in basis points: `1000` is 10%, so 10x leverage. */
|
|
38
|
+
margin: {
|
|
39
|
+
default_initial_margin_fraction: number;
|
|
40
|
+
min_initial_margin_fraction: number;
|
|
41
|
+
maintenance_margin_fraction: number;
|
|
42
|
+
closeout_margin_fraction: number;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export type PerpSystemStatus = {
|
|
46
|
+
actions: {
|
|
47
|
+
open_enabled: boolean;
|
|
48
|
+
cancel_enabled: boolean;
|
|
49
|
+
close_enabled: boolean;
|
|
50
|
+
add_margin_enabled: boolean;
|
|
51
|
+
remove_margin_enabled: boolean;
|
|
52
|
+
auto_close_enabled: boolean;
|
|
53
|
+
};
|
|
54
|
+
exchange_status: {
|
|
55
|
+
exchange_partner_tech_name: string;
|
|
56
|
+
operational_state: string;
|
|
57
|
+
is_trading_halted: boolean;
|
|
58
|
+
message: unknown;
|
|
59
|
+
current_status: unknown;
|
|
60
|
+
upcoming_maintenance: unknown;
|
|
61
|
+
last_changed_at: string;
|
|
62
|
+
last_checked_at: string;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export type PerpOrdersPage = {
|
|
66
|
+
orders: PerpOrder[];
|
|
67
|
+
next_cursor: unknown;
|
|
68
|
+
/** `sort_ts` of the last order on the page, `null` on an empty page. */
|
|
69
|
+
last_sort_ts: string | null;
|
|
70
|
+
};
|
|
71
|
+
export type PerpPositionStatus = 'open' | 'closed';
|
|
72
|
+
export type PerpOrderStatus = 'pending' | 'processing' | 'processed' | 'filled' | 'partially_filled' | 'failed' | 'canceled';
|
|
73
|
+
type PerpPositionCore = {
|
|
74
|
+
contract_id: number;
|
|
75
|
+
contract_name: string;
|
|
76
|
+
contract_base_asset: string;
|
|
77
|
+
contract_quote_asset: string;
|
|
78
|
+
/** Seen: `long`, `short`. */
|
|
79
|
+
side: string;
|
|
80
|
+
/** Seen: `closed`. */
|
|
81
|
+
status: string;
|
|
82
|
+
leverage: number;
|
|
83
|
+
/** Seen: `isolated`. */
|
|
84
|
+
margin_type: string;
|
|
85
|
+
value_base: string;
|
|
86
|
+
margin_quote: string;
|
|
87
|
+
avg_entry_price: string;
|
|
88
|
+
liquidation_price: string;
|
|
89
|
+
funding_paid_quote: string;
|
|
90
|
+
created_at: string;
|
|
91
|
+
updated_at: string;
|
|
92
|
+
synced_at: string;
|
|
93
|
+
};
|
|
94
|
+
export type PerpPosition = PerpPositionCore & {
|
|
95
|
+
trading_agent_code: string;
|
|
96
|
+
/** Priced at the current mark, closed positions included, so it is not the P/L a closed position realised. */
|
|
97
|
+
valuation: {
|
|
98
|
+
server_time: string;
|
|
99
|
+
status: string;
|
|
100
|
+
mark_price: string;
|
|
101
|
+
index_price: string;
|
|
102
|
+
source_timestamp: string;
|
|
103
|
+
expires_at: string;
|
|
104
|
+
unrealized_pnl_quote: string;
|
|
105
|
+
equity_quote: string;
|
|
106
|
+
};
|
|
107
|
+
auto_close: unknown;
|
|
108
|
+
};
|
|
109
|
+
export type PerpOrder = {
|
|
110
|
+
order_id: string;
|
|
111
|
+
contract_id: number;
|
|
112
|
+
contract_name: string;
|
|
113
|
+
contract_base_asset: string;
|
|
114
|
+
contract_quote_asset: string;
|
|
115
|
+
side: string;
|
|
116
|
+
/** Seen: `market`. */
|
|
117
|
+
type: string;
|
|
118
|
+
/** Seen: `open`, `close`, `stop_loss`, `take_profit`. */
|
|
119
|
+
category: string;
|
|
120
|
+
status: string;
|
|
121
|
+
error_code: unknown;
|
|
122
|
+
leverage: number;
|
|
123
|
+
base_size: string;
|
|
124
|
+
base_price: string;
|
|
125
|
+
accounting_base_amount: string;
|
|
126
|
+
accounting_quote_amount: string;
|
|
127
|
+
filled_price: string | null;
|
|
128
|
+
filled_base_amount: string | null;
|
|
129
|
+
filled_quote_amount: string | null;
|
|
130
|
+
pnl_quote: string | null;
|
|
131
|
+
pnl_quote_charged: unknown;
|
|
132
|
+
roi: string | null;
|
|
133
|
+
trigger_price_quote: string | null;
|
|
134
|
+
limit_price_quote: string | null;
|
|
135
|
+
/** Unix seconds. */
|
|
136
|
+
valid_to: number | null;
|
|
137
|
+
liquidation_fee: unknown;
|
|
138
|
+
liquidation_fee_charged: unknown;
|
|
139
|
+
integrator_fee: string | null;
|
|
140
|
+
integrator_fee_charged: string | null;
|
|
141
|
+
venue_fee: string | null;
|
|
142
|
+
total_fee: string | null;
|
|
143
|
+
total_fee_charged: string | null;
|
|
144
|
+
margin_returned_amount: string | null;
|
|
145
|
+
created_at: string;
|
|
146
|
+
updated_at: string;
|
|
147
|
+
filled_at: string | null;
|
|
148
|
+
canceled_at: unknown;
|
|
149
|
+
sort_ts: string;
|
|
150
|
+
position: PerpPositionCore & {
|
|
151
|
+
fee_quote: unknown;
|
|
152
|
+
close_price: string;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// source/bin/quiet-localstorage.ts
|
|
2
|
+
const nodeOptions = (process.env["NODE_OPTIONS"] ?? "").split(/\s+/);
|
|
3
|
+
if (![...process.execArgv, ...nodeOptions].some((arg) => arg.startsWith("--localstorage-file"))) Object.defineProperty(globalThis, "localStorage", {
|
|
4
|
+
value: void 0,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true
|
|
7
|
+
});
|
|
8
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./quiet-localstorage.js";
|
|
3
|
+
import { COMMANDS, UsageError, run } from "../cli/run.js";
|
|
4
|
+
import { WaltClient } from "../client.js";
|
|
5
|
+
import { TelegramTokenSource } from "../telegram/auth.js";
|
|
6
|
+
import { WaltAuthError, WaltRequestError } from "../transport.js";
|
|
7
|
+
import { TelegramClient } from "teleproto";
|
|
8
|
+
import { StringSession } from "teleproto/sessions/index.js";
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { stdin, stdout } from "node:process";
|
|
11
|
+
import { createInterface } from "node:readline/promises";
|
|
12
|
+
import { parseArgs } from "node:util";
|
|
13
|
+
// source/bin/walt.ts
|
|
14
|
+
/**
|
|
15
|
+
* Signs in to Telegram interactively and prints the session string to save as `TG_SESSION`.
|
|
16
|
+
*
|
|
17
|
+
* @returns The process exit code.
|
|
18
|
+
*/
|
|
19
|
+
const login = async () => {
|
|
20
|
+
const rl = createInterface({
|
|
21
|
+
input: stdin,
|
|
22
|
+
output: stdout
|
|
23
|
+
});
|
|
24
|
+
const ask = (question) => rl.question(question);
|
|
25
|
+
const apiId = Number(process.env["TG_API_ID"] || await ask("API id (from https://my.telegram.org): "));
|
|
26
|
+
if (!Number.isSafeInteger(apiId) || apiId <= 0) {
|
|
27
|
+
rl.close();
|
|
28
|
+
console.error("The API id must be the number shown at https://my.telegram.org");
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
const apiHash = process.env["TG_API_HASH"] || await ask("API hash: ");
|
|
32
|
+
const client = new TelegramClient(new StringSession(""), apiId, apiHash, { connectionRetries: 3 });
|
|
33
|
+
await client.start({
|
|
34
|
+
phoneNumber: () => ask("Phone (+country...): "),
|
|
35
|
+
phoneCode: () => ask("Code you received: "),
|
|
36
|
+
password: () => ask("2FA password (blank if none): "),
|
|
37
|
+
onError: (error) => console.error(error)
|
|
38
|
+
});
|
|
39
|
+
rl.close();
|
|
40
|
+
console.log("\nLogged in. Save this as TG_SESSION (keep it secret):\n");
|
|
41
|
+
console.log(client.session.save());
|
|
42
|
+
await client.disconnect();
|
|
43
|
+
return 0;
|
|
44
|
+
};
|
|
45
|
+
const USAGE = `Usage: walt <command> [options]
|
|
46
|
+
|
|
47
|
+
${COMMANDS}
|
|
48
|
+
login sign in to Telegram and print TG_SESSION
|
|
49
|
+
token sign in as a new device and print its token state as JSON
|
|
50
|
+
|
|
51
|
+
Options:
|
|
52
|
+
--json print JSON instead of a table
|
|
53
|
+
--fiat CODE currency for values (default USD)
|
|
54
|
+
--env-file PATH read TG_API_ID, TG_API_HASH and TG_SESSION from a file
|
|
55
|
+
-h, --help show this help
|
|
56
|
+
-v, --version show the version
|
|
57
|
+
|
|
58
|
+
Needs TG_API_ID and TG_API_HASH from https://my.telegram.org and TG_SESSION from \`walt login\`.
|
|
59
|
+
Every command is read-only.`;
|
|
60
|
+
const fail = (message, code) => {
|
|
61
|
+
console.error(`walt: ${message}`);
|
|
62
|
+
process.exit(code);
|
|
63
|
+
};
|
|
64
|
+
const parse = () => {
|
|
65
|
+
try {
|
|
66
|
+
return parseArgs({
|
|
67
|
+
allowPositionals: true,
|
|
68
|
+
options: {
|
|
69
|
+
json: { type: "boolean" },
|
|
70
|
+
fiat: { type: "string" },
|
|
71
|
+
"env-file": { type: "string" },
|
|
72
|
+
asset: { type: "string" },
|
|
73
|
+
limit: { type: "string" },
|
|
74
|
+
from: { type: "string" },
|
|
75
|
+
monthly: { type: "boolean" },
|
|
76
|
+
all: { type: "boolean" },
|
|
77
|
+
closed: { type: "boolean" },
|
|
78
|
+
help: {
|
|
79
|
+
type: "boolean",
|
|
80
|
+
short: "h"
|
|
81
|
+
},
|
|
82
|
+
version: {
|
|
83
|
+
type: "boolean",
|
|
84
|
+
short: "v"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return fail(`${error.message}\nRun \`walt --help\` for usage.`, 2);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const { values, positionals } = parse();
|
|
93
|
+
const [command, ...args] = positionals;
|
|
94
|
+
if (values.version) {
|
|
95
|
+
const manifest = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8"));
|
|
96
|
+
console.log(manifest.version);
|
|
97
|
+
process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
if (values.help || command === void 0) {
|
|
100
|
+
console.log(USAGE);
|
|
101
|
+
process.exit(command === void 0 && !values.help ? 2 : 0);
|
|
102
|
+
}
|
|
103
|
+
if (values["env-file"] !== void 0) try {
|
|
104
|
+
process.loadEnvFile(values["env-file"]);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
fail(`cannot read ${values["env-file"]}: ${error.message}`, 2);
|
|
107
|
+
}
|
|
108
|
+
if (command === "login") process.exit(await login());
|
|
109
|
+
const session = process.env["TG_SESSION"];
|
|
110
|
+
const apiId = Number(process.env["TG_API_ID"]);
|
|
111
|
+
const apiHash = process.env["TG_API_HASH"];
|
|
112
|
+
if (!session || !apiId || !apiHash) fail("set TG_API_ID, TG_API_HASH and TG_SESSION first (run `walt login` for the session)", 2);
|
|
113
|
+
if (command === "token") console.log = console.error;
|
|
114
|
+
let issued = null;
|
|
115
|
+
const source = new TelegramTokenSource({
|
|
116
|
+
session: session ?? "",
|
|
117
|
+
apiId,
|
|
118
|
+
apiHash: apiHash ?? "",
|
|
119
|
+
...command === "token" && { storage: {
|
|
120
|
+
load: async () => null,
|
|
121
|
+
save: async (state) => {
|
|
122
|
+
issued = state;
|
|
123
|
+
}
|
|
124
|
+
} }
|
|
125
|
+
});
|
|
126
|
+
const client = new WaltClient({ tokenProvider: (rejected) => source.token(rejected) });
|
|
127
|
+
let exitCode = 0;
|
|
128
|
+
try {
|
|
129
|
+
if (command === "token") {
|
|
130
|
+
await source.token();
|
|
131
|
+
stdout.write(`${JSON.stringify(issued)}\n`);
|
|
132
|
+
} else console.log(await run(client, command, args, values));
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error instanceof UsageError) {
|
|
135
|
+
console.error(`walt: ${error.message}\nRun \`walt --help\` for usage.`);
|
|
136
|
+
exitCode = 2;
|
|
137
|
+
} else if (error instanceof WaltRequestError) {
|
|
138
|
+
const code = error.body?.code;
|
|
139
|
+
console.error(`walt: ${error.message}${typeof code === "string" ? ` (${code})` : ""}`);
|
|
140
|
+
exitCode = 1;
|
|
141
|
+
} else if (error instanceof WaltAuthError) {
|
|
142
|
+
console.error(`walt: sign-in failed: ${error.message}`);
|
|
143
|
+
exitCode = 1;
|
|
144
|
+
} else {
|
|
145
|
+
console.error(`walt: ${error instanceof Error ? error.message : String(error)}`);
|
|
146
|
+
exitCode = 1;
|
|
147
|
+
}
|
|
148
|
+
} finally {
|
|
149
|
+
await source.disconnect();
|
|
150
|
+
}
|
|
151
|
+
process.exit(exitCode);
|
|
152
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { WaltClient } from "../client.js";
|
|
2
|
+
export type CliOptions = {
|
|
3
|
+
json?: boolean;
|
|
4
|
+
fiat?: string;
|
|
5
|
+
asset?: string;
|
|
6
|
+
limit?: string;
|
|
7
|
+
from?: string;
|
|
8
|
+
monthly?: boolean;
|
|
9
|
+
all?: boolean;
|
|
10
|
+
closed?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare class UsageError extends Error {}
|
|
13
|
+
export declare const COMMANDS = "Commands:\n balances [--all] every asset: spot, staked and held by limit orders,\n and with --all the ones worth less than 0.01\n history [--monthly] balance, deposits, withdrawals and P/L per day or month\n [--from DATE] start date, YYYY-MM-DD (default: 30 days or 12 months back)\n transactions latest transactions\n [--asset SYM] only this asset\n [--limit N] how many (default 20)\n price SYM... current price and change over 24h, 7d and 30d\n quote FROM TO AMOUNT what an exchange would give right now, without making it\n orders [--all] open limit orders, or every order with --all\n perps [--closed] open perpetual positions, or closed ones\n earn [--all] your earn stakes, or every active campaign with --all";
|
|
14
|
+
/**
|
|
15
|
+
* Runs one read-only command and returns what to print.
|
|
16
|
+
*
|
|
17
|
+
* @param client - A signed-in client.
|
|
18
|
+
* @param command - The command name, such as `balances`.
|
|
19
|
+
* @param args - Positional arguments after the command.
|
|
20
|
+
* @param options - Parsed flags.
|
|
21
|
+
*/
|
|
22
|
+
export declare const run: (client: WaltClient, command: string, args: string[], options?: CliOptions) => Promise<string>;
|