perp-cli 0.7.1 → 0.7.2
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/bot/config.d.ts +1 -0
- package/dist/bot/config.js +1 -1
- package/dist/bot/engine.js +41 -6
- package/dist/bot/index.d.ts +1 -1
- package/dist/bot/index.js +1 -1
- package/dist/bot/tui/BotDashboard.d.ts +7 -0
- package/dist/bot/tui/BotDashboard.js +3 -2
- package/dist/bot/tui/index.d.ts +1 -1
- package/dist/commands/arb-auto.js +4 -2
- package/dist/commands/arb.d.ts +1 -0
- package/dist/commands/arb.js +2 -0
- package/dist/commands/bot.js +44 -7
- package/dist/commands/bridge.js +1 -1
- package/dist/commands/funds.js +1 -1
- package/dist/commands/history.js +5 -1
- package/dist/commands/market.js +19 -10
- package/dist/commands/trade.js +3 -3
- package/dist/exchanges/aster.d.ts +4 -0
- package/dist/exchanges/aster.js +39 -28
- package/dist/exchanges/edgex.d.ts +62 -0
- package/dist/exchanges/edgex.js +552 -0
- package/package.json +1 -1
package/dist/exchanges/aster.js
CHANGED
|
@@ -23,6 +23,17 @@ export class AsterAdapter {
|
|
|
23
23
|
get isReadOnly() {
|
|
24
24
|
return !this._apiKey || !this._apiSecret;
|
|
25
25
|
}
|
|
26
|
+
/** CLI symbol → Aster API symbol (ETH → ETHUSDT) */
|
|
27
|
+
_toApi(symbol) {
|
|
28
|
+
const s = symbol.toUpperCase().replace(/-PERP$/, "");
|
|
29
|
+
if (s.endsWith("USDT") || s.endsWith("BUSD"))
|
|
30
|
+
return s;
|
|
31
|
+
return `${s}USDT`;
|
|
32
|
+
}
|
|
33
|
+
/** Aster API symbol → CLI symbol (ETHUSDT → ETH) */
|
|
34
|
+
_fromApi(symbol) {
|
|
35
|
+
return symbol.replace(/USDT$/, "").replace(/BUSD$/, "");
|
|
36
|
+
}
|
|
26
37
|
async init() {
|
|
27
38
|
// Verify connectivity by fetching server time
|
|
28
39
|
await this._publicGet("/fapi/v1/time");
|
|
@@ -70,7 +81,7 @@ export class AsterAdapter {
|
|
|
70
81
|
// Extract max leverage from leverage brackets if available
|
|
71
82
|
const maxLev = Number(s.maxLeverage ?? 50);
|
|
72
83
|
return {
|
|
73
|
-
symbol: sym,
|
|
84
|
+
symbol: this._fromApi(sym),
|
|
74
85
|
markPrice: String(premium?.markPrice ?? ticker?.lastPrice ?? "0"),
|
|
75
86
|
indexPrice: String(premium?.indexPrice ?? "0"),
|
|
76
87
|
fundingRate: String(premium?.lastFundingRate ?? "0"),
|
|
@@ -81,7 +92,7 @@ export class AsterAdapter {
|
|
|
81
92
|
});
|
|
82
93
|
}
|
|
83
94
|
async getOrderbook(symbol) {
|
|
84
|
-
const res = await this._publicGet("/fapi/v1/depth", { symbol:
|
|
95
|
+
const res = await this._publicGet("/fapi/v1/depth", { symbol: this._toApi(symbol), limit: "50" });
|
|
85
96
|
return {
|
|
86
97
|
bids: res?.bids ?? [],
|
|
87
98
|
asks: res?.asks ?? [],
|
|
@@ -89,12 +100,12 @@ export class AsterAdapter {
|
|
|
89
100
|
}
|
|
90
101
|
async getRecentTrades(symbol, limit = 20) {
|
|
91
102
|
const trades = await this._publicGet("/fapi/v1/trades", {
|
|
92
|
-
symbol:
|
|
103
|
+
symbol: this._toApi(symbol),
|
|
93
104
|
limit: String(limit),
|
|
94
105
|
});
|
|
95
106
|
return (trades ?? []).map((t) => ({
|
|
96
107
|
time: Number(t.time ?? 0),
|
|
97
|
-
symbol:
|
|
108
|
+
symbol: this._fromApi(String(t.symbol ?? symbol)),
|
|
98
109
|
side: t.isBuyerMaker ? "sell" : "buy",
|
|
99
110
|
price: String(t.price ?? "0"),
|
|
100
111
|
size: String(t.qty ?? "0"),
|
|
@@ -103,7 +114,7 @@ export class AsterAdapter {
|
|
|
103
114
|
}
|
|
104
115
|
async getFundingHistory(symbol, limit = 10) {
|
|
105
116
|
const data = await this._publicGet("/fapi/v1/fundingRate", {
|
|
106
|
-
symbol:
|
|
117
|
+
symbol: this._toApi(symbol),
|
|
107
118
|
limit: String(limit),
|
|
108
119
|
});
|
|
109
120
|
return (data ?? []).map((d) => ({
|
|
@@ -114,7 +125,7 @@ export class AsterAdapter {
|
|
|
114
125
|
}
|
|
115
126
|
async getKlines(symbol, interval, startTime, endTime) {
|
|
116
127
|
const data = await this._publicGet("/fapi/v1/klines", {
|
|
117
|
-
symbol:
|
|
128
|
+
symbol: this._toApi(symbol),
|
|
118
129
|
interval,
|
|
119
130
|
startTime: String(startTime),
|
|
120
131
|
endTime: String(endTime),
|
|
@@ -151,7 +162,7 @@ export class AsterAdapter {
|
|
|
151
162
|
.map((p) => {
|
|
152
163
|
const amt = Number(p.positionAmt ?? 0);
|
|
153
164
|
return {
|
|
154
|
-
symbol: String(p.symbol ?? ""),
|
|
165
|
+
symbol: this._fromApi(String(p.symbol ?? "")),
|
|
155
166
|
side: amt > 0 ? "long" : "short",
|
|
156
167
|
size: String(Math.abs(amt)),
|
|
157
168
|
entryPrice: String(p.entryPrice ?? "0"),
|
|
@@ -166,7 +177,7 @@ export class AsterAdapter {
|
|
|
166
177
|
const orders = await this._signedGet("/fapi/v1/openOrders");
|
|
167
178
|
return (orders ?? []).map((o) => ({
|
|
168
179
|
orderId: String(o.orderId ?? ""),
|
|
169
|
-
symbol: String(o.symbol ?? ""),
|
|
180
|
+
symbol: this._fromApi(String(o.symbol ?? "")),
|
|
170
181
|
side: String(o.side).toLowerCase(),
|
|
171
182
|
price: String(o.price ?? "0"),
|
|
172
183
|
size: String(o.origQty ?? "0"),
|
|
@@ -178,15 +189,15 @@ export class AsterAdapter {
|
|
|
178
189
|
async getOrderHistory(limit = 30) {
|
|
179
190
|
// allOrders requires symbol — get from positions or recent trades
|
|
180
191
|
const positions = await this.getPositions();
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
192
|
+
const apiSymbols = new Set(positions.map(p => this._toApi(p.symbol)));
|
|
193
|
+
if (apiSymbols.size === 0) {
|
|
183
194
|
// Fallback: query the most common perp symbols when no open positions exist
|
|
184
195
|
for (const s of ["BTCUSDT", "ETHUSDT", "SOLUSDT", "BNBUSDT", "XRPUSDT"]) {
|
|
185
|
-
|
|
196
|
+
apiSymbols.add(s);
|
|
186
197
|
}
|
|
187
198
|
}
|
|
188
199
|
const allOrders = [];
|
|
189
|
-
for (const sym of
|
|
200
|
+
for (const sym of apiSymbols) {
|
|
190
201
|
try {
|
|
191
202
|
const orders = await this._signedGet("/fapi/v1/allOrders", {
|
|
192
203
|
symbol: sym,
|
|
@@ -195,7 +206,7 @@ export class AsterAdapter {
|
|
|
195
206
|
for (const o of orders ?? []) {
|
|
196
207
|
allOrders.push({
|
|
197
208
|
orderId: String(o.orderId ?? ""),
|
|
198
|
-
symbol: String(o.symbol ?? ""),
|
|
209
|
+
symbol: this._fromApi(String(o.symbol ?? "")),
|
|
199
210
|
side: String(o.side).toLowerCase(),
|
|
200
211
|
price: String(o.price ?? "0"),
|
|
201
212
|
size: String(o.origQty ?? "0"),
|
|
@@ -211,11 +222,11 @@ export class AsterAdapter {
|
|
|
211
222
|
}
|
|
212
223
|
async getTradeHistory(limit = 30) {
|
|
213
224
|
const positions = await this.getPositions();
|
|
214
|
-
const
|
|
215
|
-
if (
|
|
216
|
-
|
|
225
|
+
const apiSymbols = new Set(positions.map(p => this._toApi(p.symbol)));
|
|
226
|
+
if (apiSymbols.size === 0)
|
|
227
|
+
apiSymbols.add("BTCUSDT");
|
|
217
228
|
const allTrades = [];
|
|
218
|
-
for (const sym of
|
|
229
|
+
for (const sym of apiSymbols) {
|
|
219
230
|
try {
|
|
220
231
|
const trades = await this._signedGet("/fapi/v1/userTrades", {
|
|
221
232
|
symbol: sym,
|
|
@@ -224,7 +235,7 @@ export class AsterAdapter {
|
|
|
224
235
|
for (const t of trades ?? []) {
|
|
225
236
|
allTrades.push({
|
|
226
237
|
time: Number(t.time ?? 0),
|
|
227
|
-
symbol: String(t.symbol ?? ""),
|
|
238
|
+
symbol: this._fromApi(String(t.symbol ?? "")),
|
|
228
239
|
side: t.buyer ? "buy" : "sell",
|
|
229
240
|
price: String(t.price ?? "0"),
|
|
230
241
|
size: String(t.qty ?? "0"),
|
|
@@ -243,14 +254,14 @@ export class AsterAdapter {
|
|
|
243
254
|
});
|
|
244
255
|
return (data ?? []).map((f) => ({
|
|
245
256
|
time: Number(f.time ?? 0),
|
|
246
|
-
symbol: String(f.symbol ?? ""),
|
|
257
|
+
symbol: this._fromApi(String(f.symbol ?? "")),
|
|
247
258
|
payment: String(f.income ?? "0"),
|
|
248
259
|
}));
|
|
249
260
|
}
|
|
250
261
|
// ── Trading ──
|
|
251
262
|
async marketOrder(symbol, side, size) {
|
|
252
263
|
return this._signedPost("/fapi/v1/order", {
|
|
253
|
-
symbol:
|
|
264
|
+
symbol: this._toApi(symbol),
|
|
254
265
|
side: side.toUpperCase(),
|
|
255
266
|
type: "MARKET",
|
|
256
267
|
quantity: size,
|
|
@@ -258,7 +269,7 @@ export class AsterAdapter {
|
|
|
258
269
|
}
|
|
259
270
|
async limitOrder(symbol, side, price, size, opts) {
|
|
260
271
|
const params = {
|
|
261
|
-
symbol:
|
|
272
|
+
symbol: this._toApi(symbol),
|
|
262
273
|
side: side.toUpperCase(),
|
|
263
274
|
type: "LIMIT",
|
|
264
275
|
price,
|
|
@@ -279,7 +290,7 @@ export class AsterAdapter {
|
|
|
279
290
|
}
|
|
280
291
|
async cancelOrder(symbol, orderId) {
|
|
281
292
|
return this._signedDelete("/fapi/v1/order", {
|
|
282
|
-
symbol:
|
|
293
|
+
symbol: this._toApi(symbol),
|
|
283
294
|
orderId,
|
|
284
295
|
});
|
|
285
296
|
}
|
|
@@ -287,14 +298,14 @@ export class AsterAdapter {
|
|
|
287
298
|
if (!symbol) {
|
|
288
299
|
// Cancel all for all symbols with open orders
|
|
289
300
|
const orders = await this.getOpenOrders();
|
|
290
|
-
const
|
|
301
|
+
const apiSymbols = new Set(orders.map(o => this._toApi(o.symbol)));
|
|
291
302
|
const results = [];
|
|
292
|
-
for (const sym of
|
|
303
|
+
for (const sym of apiSymbols) {
|
|
293
304
|
results.push(await this._signedDelete("/fapi/v1/allOpenOrders", { symbol: sym }));
|
|
294
305
|
}
|
|
295
306
|
return results;
|
|
296
307
|
}
|
|
297
|
-
return this._signedDelete("/fapi/v1/allOpenOrders", { symbol:
|
|
308
|
+
return this._signedDelete("/fapi/v1/allOpenOrders", { symbol: this._toApi(symbol) });
|
|
298
309
|
}
|
|
299
310
|
// ── Risk ──
|
|
300
311
|
async setLeverage(symbol, leverage, marginMode) {
|
|
@@ -302,7 +313,7 @@ export class AsterAdapter {
|
|
|
302
313
|
if (marginMode) {
|
|
303
314
|
try {
|
|
304
315
|
await this._signedPost("/fapi/v1/marginType", {
|
|
305
|
-
symbol:
|
|
316
|
+
symbol: this._toApi(symbol),
|
|
306
317
|
marginType: marginMode === "cross" ? "CROSSED" : "ISOLATED",
|
|
307
318
|
});
|
|
308
319
|
}
|
|
@@ -311,13 +322,13 @@ export class AsterAdapter {
|
|
|
311
322
|
}
|
|
312
323
|
}
|
|
313
324
|
return this._signedPost("/fapi/v1/leverage", {
|
|
314
|
-
symbol:
|
|
325
|
+
symbol: this._toApi(symbol),
|
|
315
326
|
leverage: String(leverage),
|
|
316
327
|
});
|
|
317
328
|
}
|
|
318
329
|
async stopOrder(symbol, side, size, triggerPrice, opts) {
|
|
319
330
|
const params = {
|
|
320
|
-
symbol:
|
|
331
|
+
symbol: this._toApi(symbol),
|
|
321
332
|
side: side.toUpperCase(),
|
|
322
333
|
quantity: size,
|
|
323
334
|
stopPrice: triggerPrice,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* edgeX DEX adapter — StarkEx-based perpetual futures exchange.
|
|
3
|
+
* Base: https://pro.edgex.exchange
|
|
4
|
+
*/
|
|
5
|
+
import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
|
|
6
|
+
export declare class EdgeXAdapter implements ExchangeAdapter {
|
|
7
|
+
readonly name = "edgex";
|
|
8
|
+
readonly chain = "starkex";
|
|
9
|
+
readonly aliases: readonly ["ex"];
|
|
10
|
+
private _accountId;
|
|
11
|
+
private _starkPrivateKey;
|
|
12
|
+
private _baseUrl;
|
|
13
|
+
private _contracts;
|
|
14
|
+
private _contractById;
|
|
15
|
+
private _marketsCache;
|
|
16
|
+
private static CACHE_TTL;
|
|
17
|
+
constructor(accountId?: string, starkPrivateKey?: string);
|
|
18
|
+
get isReadOnly(): boolean;
|
|
19
|
+
/** CLI symbol -> API symbol: ETH -> ETHUSD */
|
|
20
|
+
private _toApi;
|
|
21
|
+
/** API symbol -> CLI symbol: ETHUSD -> ETH, DOGE2USD -> DOGE2 */
|
|
22
|
+
private _fromApi;
|
|
23
|
+
private _getContract;
|
|
24
|
+
init(): Promise<void>;
|
|
25
|
+
getMarkets(): Promise<ExchangeMarketInfo[]>;
|
|
26
|
+
getOrderbook(symbol: string): Promise<{
|
|
27
|
+
bids: [string, string][];
|
|
28
|
+
asks: [string, string][];
|
|
29
|
+
}>;
|
|
30
|
+
getRecentTrades(symbol: string, limit?: number): Promise<ExchangeTrade[]>;
|
|
31
|
+
getFundingHistory(symbol: string, _limit?: number): Promise<{
|
|
32
|
+
time: number;
|
|
33
|
+
rate: string;
|
|
34
|
+
price: string | null;
|
|
35
|
+
}[]>;
|
|
36
|
+
getKlines(symbol: string, _interval: string, _startTime: number, _endTime: number): Promise<ExchangeKline[]>;
|
|
37
|
+
getBalance(): Promise<ExchangeBalance>;
|
|
38
|
+
getPositions(): Promise<ExchangePosition[]>;
|
|
39
|
+
getOpenOrders(): Promise<ExchangeOrder[]>;
|
|
40
|
+
getOrderHistory(_limit?: number): Promise<ExchangeOrder[]>;
|
|
41
|
+
getTradeHistory(_limit?: number): Promise<ExchangeTrade[]>;
|
|
42
|
+
getFundingPayments(_limit?: number): Promise<ExchangeFundingPayment[]>;
|
|
43
|
+
marketOrder(symbol: string, side: "buy" | "sell", size: string): Promise<unknown>;
|
|
44
|
+
limitOrder(symbol: string, side: "buy" | "sell", price: string, size: string, opts?: {
|
|
45
|
+
reduceOnly?: boolean;
|
|
46
|
+
tif?: string;
|
|
47
|
+
}): Promise<unknown>;
|
|
48
|
+
editOrder(symbol: string, orderId: string, price: string, size: string): Promise<unknown>;
|
|
49
|
+
cancelOrder(_symbol: string, orderId: string): Promise<unknown>;
|
|
50
|
+
cancelAllOrders(symbol?: string): Promise<unknown>;
|
|
51
|
+
setLeverage(symbol: string, leverage: number, _marginMode?: "cross" | "isolated"): Promise<unknown>;
|
|
52
|
+
stopOrder(symbol: string, side: "buy" | "sell", size: string, triggerPrice: string, opts?: {
|
|
53
|
+
limitPrice?: string;
|
|
54
|
+
reduceOnly?: boolean;
|
|
55
|
+
}): Promise<unknown>;
|
|
56
|
+
withdraw(_amount: string, _destination: string): Promise<unknown>;
|
|
57
|
+
private _computeL2OrderFields;
|
|
58
|
+
private _signRequest;
|
|
59
|
+
private _publicGet;
|
|
60
|
+
private _authGet;
|
|
61
|
+
private _authPost;
|
|
62
|
+
}
|