klingex 1.0.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 +310 -0
- package/dist/index.d.mts +895 -0
- package/dist/index.d.ts +895 -0
- package/dist/index.js +1098 -0
- package/dist/index.mjs +1061 -0
- package/package.json +60 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1098 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AuthenticationError: () => AuthenticationError,
|
|
24
|
+
InsufficientFundsError: () => InsufficientFundsError,
|
|
25
|
+
InvoicesEndpoint: () => InvoicesEndpoint,
|
|
26
|
+
KlingEx: () => KlingEx,
|
|
27
|
+
KlingExError: () => KlingExError,
|
|
28
|
+
KlingExWebSocket: () => KlingExWebSocket,
|
|
29
|
+
MarketsEndpoint: () => MarketsEndpoint,
|
|
30
|
+
OrdersEndpoint: () => OrdersEndpoint,
|
|
31
|
+
RateLimitError: () => RateLimitError,
|
|
32
|
+
ValidationError: () => ValidationError,
|
|
33
|
+
WalletEndpoint: () => WalletEndpoint,
|
|
34
|
+
default: () => KlingEx
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/types/index.ts
|
|
39
|
+
var KlingExError = class extends Error {
|
|
40
|
+
constructor(message, code, statusCode, details) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.code = code;
|
|
43
|
+
this.statusCode = statusCode;
|
|
44
|
+
this.details = details;
|
|
45
|
+
this.name = "KlingExError";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var AuthenticationError = class extends KlingExError {
|
|
49
|
+
constructor(message = "Authentication failed") {
|
|
50
|
+
super(message, "AUTH_ERROR", 401);
|
|
51
|
+
this.name = "AuthenticationError";
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var RateLimitError = class extends KlingExError {
|
|
55
|
+
constructor(message = "Rate limit exceeded", retryAfter) {
|
|
56
|
+
super(message, "RATE_LIMIT", 429);
|
|
57
|
+
this.retryAfter = retryAfter;
|
|
58
|
+
this.name = "RateLimitError";
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var ValidationError = class extends KlingExError {
|
|
62
|
+
constructor(message, details) {
|
|
63
|
+
super(message, "VALIDATION_ERROR", 400, details);
|
|
64
|
+
this.name = "ValidationError";
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var InsufficientFundsError = class extends KlingExError {
|
|
68
|
+
constructor(message = "Insufficient funds") {
|
|
69
|
+
super(message, "INSUFFICIENT_FUNDS", 400);
|
|
70
|
+
this.name = "InsufficientFundsError";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/http.ts
|
|
75
|
+
var HttpClient = class {
|
|
76
|
+
constructor(config) {
|
|
77
|
+
this.config = config;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Update authentication credentials
|
|
81
|
+
*/
|
|
82
|
+
setAuth(auth) {
|
|
83
|
+
if (auth.apiKey) this.config.apiKey = auth.apiKey;
|
|
84
|
+
if (auth.jwt) this.config.jwt = auth.jwt;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Make an HTTP request to the API
|
|
88
|
+
*/
|
|
89
|
+
async request(endpoint, options = {}) {
|
|
90
|
+
const { method = "GET", body, params, headers = {} } = options;
|
|
91
|
+
let url = `${this.config.baseUrl}${endpoint}`;
|
|
92
|
+
if (params) {
|
|
93
|
+
const searchParams = new URLSearchParams();
|
|
94
|
+
for (const [key, value] of Object.entries(params)) {
|
|
95
|
+
if (value !== void 0 && value !== null) {
|
|
96
|
+
searchParams.append(key, String(value));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const queryString = searchParams.toString();
|
|
100
|
+
if (queryString) {
|
|
101
|
+
url += `?${queryString}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const requestHeaders = {
|
|
105
|
+
"Content-Type": "application/json",
|
|
106
|
+
...headers
|
|
107
|
+
};
|
|
108
|
+
if (this.config.apiKey) {
|
|
109
|
+
requestHeaders["X-API-Key"] = this.config.apiKey;
|
|
110
|
+
} else if (this.config.jwt) {
|
|
111
|
+
requestHeaders["Authorization"] = `Bearer ${this.config.jwt}`;
|
|
112
|
+
}
|
|
113
|
+
const controller = new AbortController();
|
|
114
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
115
|
+
try {
|
|
116
|
+
const response = await fetch(url, {
|
|
117
|
+
method,
|
|
118
|
+
headers: requestHeaders,
|
|
119
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
120
|
+
signal: controller.signal
|
|
121
|
+
});
|
|
122
|
+
clearTimeout(timeoutId);
|
|
123
|
+
const contentType = response.headers.get("content-type");
|
|
124
|
+
let data;
|
|
125
|
+
if (contentType?.includes("application/json")) {
|
|
126
|
+
data = await response.json();
|
|
127
|
+
} else if (contentType?.includes("application/pdf")) {
|
|
128
|
+
data = await response.blob();
|
|
129
|
+
} else {
|
|
130
|
+
data = await response.text();
|
|
131
|
+
}
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
this.handleError(response.status, data);
|
|
134
|
+
}
|
|
135
|
+
return data;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
clearTimeout(timeoutId);
|
|
138
|
+
if (error instanceof KlingExError) {
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
if (error instanceof Error) {
|
|
142
|
+
if (error.name === "AbortError") {
|
|
143
|
+
throw new KlingExError("Request timeout", "TIMEOUT", 408);
|
|
144
|
+
}
|
|
145
|
+
throw new KlingExError(error.message, "NETWORK_ERROR");
|
|
146
|
+
}
|
|
147
|
+
throw new KlingExError("Unknown error occurred", "UNKNOWN");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Handle HTTP error responses
|
|
152
|
+
*/
|
|
153
|
+
handleError(status, data) {
|
|
154
|
+
const errorMessage = this.extractErrorMessage(data);
|
|
155
|
+
switch (status) {
|
|
156
|
+
case 401:
|
|
157
|
+
throw new AuthenticationError(errorMessage);
|
|
158
|
+
case 429:
|
|
159
|
+
const retryAfter = this.extractRetryAfter(data);
|
|
160
|
+
throw new RateLimitError(errorMessage, retryAfter);
|
|
161
|
+
case 400:
|
|
162
|
+
if (errorMessage.toLowerCase().includes("insufficient")) {
|
|
163
|
+
throw new InsufficientFundsError(errorMessage);
|
|
164
|
+
}
|
|
165
|
+
throw new ValidationError(errorMessage, data);
|
|
166
|
+
default:
|
|
167
|
+
throw new KlingExError(errorMessage, "API_ERROR", status, data);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Extract error message from response
|
|
172
|
+
*/
|
|
173
|
+
extractErrorMessage(data) {
|
|
174
|
+
if (typeof data === "string") return data;
|
|
175
|
+
if (typeof data === "object" && data !== null) {
|
|
176
|
+
const obj = data;
|
|
177
|
+
return String(obj.error || obj.message || obj.detail || "Unknown error");
|
|
178
|
+
}
|
|
179
|
+
return "Unknown error";
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Extract retry-after value from rate limit response
|
|
183
|
+
*/
|
|
184
|
+
extractRetryAfter(data) {
|
|
185
|
+
if (typeof data === "object" && data !== null) {
|
|
186
|
+
const obj = data;
|
|
187
|
+
if (typeof obj.retry_after === "number") {
|
|
188
|
+
return obj.retry_after;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
193
|
+
// Convenience methods
|
|
194
|
+
async get(endpoint, params) {
|
|
195
|
+
return this.request(endpoint, { method: "GET", params });
|
|
196
|
+
}
|
|
197
|
+
async post(endpoint, body) {
|
|
198
|
+
return this.request(endpoint, { method: "POST", body });
|
|
199
|
+
}
|
|
200
|
+
async put(endpoint, body) {
|
|
201
|
+
return this.request(endpoint, { method: "PUT", body });
|
|
202
|
+
}
|
|
203
|
+
async delete(endpoint, body) {
|
|
204
|
+
return this.request(endpoint, { method: "DELETE", body });
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// src/websocket.ts
|
|
209
|
+
var KlingExWebSocket = class {
|
|
210
|
+
constructor(url, auth, options = {}) {
|
|
211
|
+
this.ws = null;
|
|
212
|
+
this.subscriptions = /* @__PURE__ */ new Map();
|
|
213
|
+
this.reconnectAttempts = 0;
|
|
214
|
+
this.reconnectTimeout = null;
|
|
215
|
+
this.pingInterval = null;
|
|
216
|
+
this.isConnecting = false;
|
|
217
|
+
this.url = url;
|
|
218
|
+
this.apiKey = auth.apiKey;
|
|
219
|
+
this.jwt = auth.jwt;
|
|
220
|
+
this.options = {
|
|
221
|
+
reconnect: options.reconnect ?? true,
|
|
222
|
+
reconnectInterval: options.reconnectInterval ?? 5e3,
|
|
223
|
+
maxReconnectAttempts: options.maxReconnectAttempts ?? 10
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Connect to WebSocket server
|
|
228
|
+
*/
|
|
229
|
+
async connect() {
|
|
230
|
+
if (this.ws?.readyState === WebSocket.OPEN || this.isConnecting) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.isConnecting = true;
|
|
234
|
+
return new Promise((resolve, reject) => {
|
|
235
|
+
try {
|
|
236
|
+
const wsUrl = new URL(this.url);
|
|
237
|
+
if (this.apiKey) {
|
|
238
|
+
wsUrl.searchParams.set("apiKey", this.apiKey);
|
|
239
|
+
} else if (this.jwt) {
|
|
240
|
+
wsUrl.searchParams.set("token", this.jwt);
|
|
241
|
+
}
|
|
242
|
+
this.ws = new WebSocket(wsUrl.toString());
|
|
243
|
+
this.ws.onopen = () => {
|
|
244
|
+
this.isConnecting = false;
|
|
245
|
+
this.reconnectAttempts = 0;
|
|
246
|
+
this.startPingInterval();
|
|
247
|
+
this.resubscribeAll();
|
|
248
|
+
resolve();
|
|
249
|
+
};
|
|
250
|
+
this.ws.onclose = (event) => {
|
|
251
|
+
this.isConnecting = false;
|
|
252
|
+
this.stopPingInterval();
|
|
253
|
+
if (this.options.reconnect && !event.wasClean) {
|
|
254
|
+
this.scheduleReconnect();
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
this.ws.onerror = (_event) => {
|
|
258
|
+
this.isConnecting = false;
|
|
259
|
+
const err = new Error("WebSocket error");
|
|
260
|
+
this.errorHandler?.(err);
|
|
261
|
+
reject(err);
|
|
262
|
+
};
|
|
263
|
+
this.ws.onmessage = (event) => {
|
|
264
|
+
this.handleMessage(event.data);
|
|
265
|
+
};
|
|
266
|
+
} catch (error) {
|
|
267
|
+
this.isConnecting = false;
|
|
268
|
+
reject(error);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Disconnect from WebSocket server
|
|
274
|
+
*/
|
|
275
|
+
disconnect() {
|
|
276
|
+
this.options.reconnect = false;
|
|
277
|
+
this.stopPingInterval();
|
|
278
|
+
if (this.reconnectTimeout) {
|
|
279
|
+
clearTimeout(this.reconnectTimeout);
|
|
280
|
+
this.reconnectTimeout = null;
|
|
281
|
+
}
|
|
282
|
+
if (this.ws) {
|
|
283
|
+
this.ws.close(1e3, "Client disconnect");
|
|
284
|
+
this.ws = null;
|
|
285
|
+
}
|
|
286
|
+
this.subscriptions.clear();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Set error handler
|
|
290
|
+
*/
|
|
291
|
+
onError(handler) {
|
|
292
|
+
this.errorHandler = handler;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Subscribe to orderbook updates
|
|
296
|
+
* @param symbol - Trading pair symbol
|
|
297
|
+
* @param handler - Callback for orderbook updates
|
|
298
|
+
*/
|
|
299
|
+
orderbook(symbol, handler) {
|
|
300
|
+
return this.subscribe("orderbook", symbol, handler);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Subscribe to trade updates
|
|
304
|
+
* @param symbol - Trading pair symbol
|
|
305
|
+
* @param handler - Callback for trade updates
|
|
306
|
+
*/
|
|
307
|
+
trades(symbol, handler) {
|
|
308
|
+
return this.subscribe("trades", symbol, handler);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Subscribe to ticker updates
|
|
312
|
+
* @param symbol - Trading pair symbol
|
|
313
|
+
* @param handler - Callback for ticker updates
|
|
314
|
+
*/
|
|
315
|
+
ticker(symbol, handler) {
|
|
316
|
+
return this.subscribe("ticker", symbol, handler);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Subscribe to user order updates (requires auth)
|
|
320
|
+
* @param handler - Callback for order updates
|
|
321
|
+
*/
|
|
322
|
+
userOrders(handler) {
|
|
323
|
+
return this.subscribe("user.orders", void 0, handler);
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Subscribe to user balance updates (requires auth)
|
|
327
|
+
* @param handler - Callback for balance updates
|
|
328
|
+
*/
|
|
329
|
+
userBalances(handler) {
|
|
330
|
+
return this.subscribe("user.balances", void 0, handler);
|
|
331
|
+
}
|
|
332
|
+
// =========================================================================
|
|
333
|
+
// Private methods
|
|
334
|
+
// =========================================================================
|
|
335
|
+
subscribe(channel, symbol, handler) {
|
|
336
|
+
const key = symbol ? `${channel}:${symbol}` : channel;
|
|
337
|
+
this.subscriptions.set(key, {
|
|
338
|
+
channel,
|
|
339
|
+
symbol,
|
|
340
|
+
handler
|
|
341
|
+
});
|
|
342
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
343
|
+
this.sendSubscribe(channel, symbol);
|
|
344
|
+
}
|
|
345
|
+
return () => {
|
|
346
|
+
this.subscriptions.delete(key);
|
|
347
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
348
|
+
this.sendUnsubscribe(channel, symbol);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
sendSubscribe(channel, symbol) {
|
|
353
|
+
this.send({
|
|
354
|
+
action: "subscribe",
|
|
355
|
+
channel,
|
|
356
|
+
symbol
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
sendUnsubscribe(channel, symbol) {
|
|
360
|
+
this.send({
|
|
361
|
+
action: "unsubscribe",
|
|
362
|
+
channel,
|
|
363
|
+
symbol
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
send(data) {
|
|
367
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
368
|
+
this.ws.send(JSON.stringify(data));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
handleMessage(data) {
|
|
372
|
+
try {
|
|
373
|
+
const message = JSON.parse(data);
|
|
374
|
+
if (message.type === "pong") {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const key = message.data && typeof message.data === "object" && "symbol" in message.data ? `${message.channel}:${message.data.symbol}` : message.channel;
|
|
378
|
+
const subscription = this.subscriptions.get(key) || this.subscriptions.get(message.channel);
|
|
379
|
+
if (subscription) {
|
|
380
|
+
subscription.handler(message.data);
|
|
381
|
+
}
|
|
382
|
+
} catch (error) {
|
|
383
|
+
this.errorHandler?.(error instanceof Error ? error : new Error("Failed to parse message"));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
resubscribeAll() {
|
|
387
|
+
for (const [, subscription] of this.subscriptions) {
|
|
388
|
+
this.sendSubscribe(subscription.channel, subscription.symbol);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
scheduleReconnect() {
|
|
392
|
+
if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
|
|
393
|
+
this.errorHandler?.(new Error("Max reconnection attempts reached"));
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
this.reconnectAttempts++;
|
|
397
|
+
const delay = this.options.reconnectInterval * Math.pow(1.5, this.reconnectAttempts - 1);
|
|
398
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
399
|
+
this.connect().catch((error) => {
|
|
400
|
+
this.errorHandler?.(error instanceof Error ? error : new Error("Reconnection failed"));
|
|
401
|
+
});
|
|
402
|
+
}, delay);
|
|
403
|
+
}
|
|
404
|
+
startPingInterval() {
|
|
405
|
+
this.pingInterval = setInterval(() => {
|
|
406
|
+
this.send({ type: "ping" });
|
|
407
|
+
}, 3e4);
|
|
408
|
+
}
|
|
409
|
+
stopPingInterval() {
|
|
410
|
+
if (this.pingInterval) {
|
|
411
|
+
clearInterval(this.pingInterval);
|
|
412
|
+
this.pingInterval = null;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
// src/endpoints/markets.ts
|
|
418
|
+
var MarketsEndpoint = class {
|
|
419
|
+
constructor(http) {
|
|
420
|
+
this.http = http;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Get all available markets/trading pairs
|
|
424
|
+
* @example
|
|
425
|
+
* const markets = await client.markets.list();
|
|
426
|
+
* // Returns full market info including:
|
|
427
|
+
* // - base_asset_symbol, quote_asset_symbol
|
|
428
|
+
* // - maker_fee_rate, taker_fee_rate
|
|
429
|
+
* // - last_price, volume_24h, priceChange24h
|
|
430
|
+
*/
|
|
431
|
+
async list() {
|
|
432
|
+
return this.http.get("/api/markets");
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Get a specific market by ID
|
|
436
|
+
* @param marketId - The market/trading pair ID
|
|
437
|
+
*/
|
|
438
|
+
async get(marketId) {
|
|
439
|
+
const markets = await this.list();
|
|
440
|
+
return markets.find((m) => m.id === marketId);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Find a market by symbol pair
|
|
444
|
+
* @param baseSymbol - Base asset symbol (e.g., "BTC")
|
|
445
|
+
* @param quoteSymbol - Quote asset symbol (e.g., "USDT")
|
|
446
|
+
*/
|
|
447
|
+
async findBySymbols(baseSymbol, quoteSymbol) {
|
|
448
|
+
const markets = await this.list();
|
|
449
|
+
return markets.find(
|
|
450
|
+
(m) => m.base_asset_symbol.toUpperCase() === baseSymbol.toUpperCase() && m.quote_asset_symbol.toUpperCase() === quoteSymbol.toUpperCase()
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Get all tickers with 24h price data (CMC format)
|
|
455
|
+
* @example
|
|
456
|
+
* const tickers = await client.markets.tickers();
|
|
457
|
+
* // Returns ticker_id as "BTC_USDT" format
|
|
458
|
+
*/
|
|
459
|
+
async tickers() {
|
|
460
|
+
return this.http.get("/api/tickers");
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Get ticker for a specific symbol pair
|
|
464
|
+
* @param tickerId - Ticker ID in CMC format (e.g., "BTC_USDT")
|
|
465
|
+
*/
|
|
466
|
+
async ticker(tickerId) {
|
|
467
|
+
const tickers = await this.tickers();
|
|
468
|
+
return tickers.find((t) => t.ticker_id === tickerId);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Get ticker by base and quote currency
|
|
472
|
+
* @param baseCurrency - Base currency symbol (e.g., "BTC")
|
|
473
|
+
* @param targetCurrency - Target/quote currency symbol (e.g., "USDT")
|
|
474
|
+
*/
|
|
475
|
+
async tickerByPair(baseCurrency, targetCurrency) {
|
|
476
|
+
const tickers = await this.tickers();
|
|
477
|
+
return tickers.find(
|
|
478
|
+
(t) => t.base_currency.toUpperCase() === baseCurrency.toUpperCase() && t.target_currency.toUpperCase() === targetCurrency.toUpperCase()
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Get orderbook for a trading pair
|
|
483
|
+
* @param marketId - The market/trading pair ID
|
|
484
|
+
* @param options - Options for the orderbook request
|
|
485
|
+
* @example
|
|
486
|
+
* const orderbook = await client.markets.orderbook(1);
|
|
487
|
+
* console.log('Best bid:', orderbook.bids[0]);
|
|
488
|
+
* console.log('Best ask:', orderbook.asks[0]);
|
|
489
|
+
*/
|
|
490
|
+
async orderbook(marketId, options = {}) {
|
|
491
|
+
const response = await this.http.get("/api/orderbook", {
|
|
492
|
+
marketId,
|
|
493
|
+
isCmc: options.isCmc ?? false
|
|
494
|
+
});
|
|
495
|
+
return {
|
|
496
|
+
trading_pair_id: response.trading_pair_id,
|
|
497
|
+
base_symbol: response.base_symbol,
|
|
498
|
+
quote_symbol: response.quote_symbol,
|
|
499
|
+
bids: (response.bids || []).map(([price, quantity]) => ({ price, quantity })),
|
|
500
|
+
asks: (response.asks || []).map(([price, quantity]) => ({ price, quantity }))
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Get raw orderbook (original API format with arrays)
|
|
505
|
+
* @param marketId - The market/trading pair ID
|
|
506
|
+
*/
|
|
507
|
+
async orderbookRaw(marketId, options = {}) {
|
|
508
|
+
return this.http.get("/api/orderbook", {
|
|
509
|
+
marketId,
|
|
510
|
+
isCmc: options.isCmc ?? false
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Get OHLCV (candlestick) data
|
|
515
|
+
* @param marketId - Trading pair ID
|
|
516
|
+
* @param timeframe - Candle timeframe (e.g., "1h", "1d")
|
|
517
|
+
* @param options - Additional options
|
|
518
|
+
* @example
|
|
519
|
+
* const candles = await client.markets.ohlcv(1, '1h');
|
|
520
|
+
*/
|
|
521
|
+
async ohlcv(marketId, timeframe, options = {}) {
|
|
522
|
+
return this.http.get("/api/ohlcv", {
|
|
523
|
+
marketId,
|
|
524
|
+
timeframe,
|
|
525
|
+
limit: options.limit,
|
|
526
|
+
startDate: options.startDate,
|
|
527
|
+
endDate: options.endDate
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Get all available assets
|
|
532
|
+
* @example
|
|
533
|
+
* const assets = await client.markets.assets();
|
|
534
|
+
*/
|
|
535
|
+
async assets() {
|
|
536
|
+
const response = await this.http.get("/api/assets");
|
|
537
|
+
return response.assets || [];
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Get a specific asset by symbol
|
|
541
|
+
* @param symbol - Asset symbol (e.g., "BTC")
|
|
542
|
+
*/
|
|
543
|
+
async asset(symbol) {
|
|
544
|
+
const assets = await this.assets();
|
|
545
|
+
return assets.find((a) => a.symbol.toUpperCase() === symbol.toUpperCase());
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Get recent trades for a trading pair
|
|
549
|
+
* @param marketId - Trading pair ID
|
|
550
|
+
* @param limit - Number of trades to return
|
|
551
|
+
*/
|
|
552
|
+
async trades(marketId, limit = 50) {
|
|
553
|
+
return this.http.get("/api/trades", { marketId, limit });
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
// src/endpoints/orders.ts
|
|
558
|
+
var OrdersEndpoint = class {
|
|
559
|
+
constructor(http, humanReadableDefault = true) {
|
|
560
|
+
this.http = http;
|
|
561
|
+
this.humanReadableDefault = humanReadableDefault;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Submit a new order
|
|
565
|
+
* @param params - Order parameters
|
|
566
|
+
* @example
|
|
567
|
+
* // Buy 1.5 BTC at $50,000 (human-readable values)
|
|
568
|
+
* const order = await client.orders.submit({
|
|
569
|
+
* symbol: 'BTC-USDT',
|
|
570
|
+
* tradingPairId: 1,
|
|
571
|
+
* side: 'BUY',
|
|
572
|
+
* quantity: '1.5',
|
|
573
|
+
* price: '50000.00'
|
|
574
|
+
* });
|
|
575
|
+
*
|
|
576
|
+
* @example
|
|
577
|
+
* // Market order (price = 0)
|
|
578
|
+
* const order = await client.orders.submit({
|
|
579
|
+
* symbol: 'BTC-USDT',
|
|
580
|
+
* tradingPairId: 1,
|
|
581
|
+
* side: 'BUY',
|
|
582
|
+
* quantity: '1.0',
|
|
583
|
+
* price: '0',
|
|
584
|
+
* slippage: 0.01 // 1% slippage tolerance
|
|
585
|
+
* });
|
|
586
|
+
*/
|
|
587
|
+
async submit(params) {
|
|
588
|
+
const rawValues = params.rawValues ?? !this.humanReadableDefault;
|
|
589
|
+
return this.http.post("/api/submit-order", {
|
|
590
|
+
symbol: params.symbol,
|
|
591
|
+
tradingPairId: params.tradingPairId,
|
|
592
|
+
side: params.side.toUpperCase(),
|
|
593
|
+
quantity: params.quantity,
|
|
594
|
+
price: params.price,
|
|
595
|
+
rawValues,
|
|
596
|
+
slippage: params.slippage
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Cancel an existing order
|
|
601
|
+
* @param params - Order ID and trading pair ID
|
|
602
|
+
* @example
|
|
603
|
+
* const result = await client.orders.cancel({
|
|
604
|
+
* orderId: '7c9e6679-7425-40de-944b-e07fc1f90ae7',
|
|
605
|
+
* tradingPairId: 1
|
|
606
|
+
* });
|
|
607
|
+
* console.log(`Released balance: ${result.released_balance}`);
|
|
608
|
+
*/
|
|
609
|
+
async cancel(params) {
|
|
610
|
+
return this.http.post("/api/cancel-order", {
|
|
611
|
+
orderId: params.orderId,
|
|
612
|
+
tradingPairId: params.tradingPairId
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Cancel all open orders for a trading pair
|
|
617
|
+
* @param tradingPairId - Trading pair ID
|
|
618
|
+
* @example
|
|
619
|
+
* const result = await client.orders.cancelAll(1);
|
|
620
|
+
* console.log(`Cancelled ${result.cancelledCount} orders`);
|
|
621
|
+
*/
|
|
622
|
+
async cancelAll(tradingPairId) {
|
|
623
|
+
return this.http.post("/api/cancel-all-orders", { tradingPairId });
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Get your open orders
|
|
627
|
+
* @param params - Filter parameters
|
|
628
|
+
* @example
|
|
629
|
+
* // Get all open orders
|
|
630
|
+
* const orders = await client.orders.list();
|
|
631
|
+
*
|
|
632
|
+
* // Get orders for specific trading pair
|
|
633
|
+
* const orders = await client.orders.list({ tradingPairId: 1 });
|
|
634
|
+
*/
|
|
635
|
+
async list(params = {}) {
|
|
636
|
+
const response = await this.http.get("/api/user-orders", {
|
|
637
|
+
tradingPairId: params.tradingPairId,
|
|
638
|
+
status: params.status,
|
|
639
|
+
limit: params.limit || 50
|
|
640
|
+
});
|
|
641
|
+
return response.orders || [];
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Get order history (including filled/cancelled orders)
|
|
645
|
+
* @param params - Filter and pagination parameters
|
|
646
|
+
*/
|
|
647
|
+
async history(params = {}) {
|
|
648
|
+
return this.http.get("/api/orders-history", {
|
|
649
|
+
tradingPairId: params.tradingPairId,
|
|
650
|
+
status: params.status,
|
|
651
|
+
limit: params.limit || 50,
|
|
652
|
+
offset: params.offset || 0
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Get a specific order by ID
|
|
657
|
+
* @param orderId - Order UUID
|
|
658
|
+
*/
|
|
659
|
+
async get(orderId) {
|
|
660
|
+
const orders = await this.list();
|
|
661
|
+
return orders.find((o) => o.id === orderId);
|
|
662
|
+
}
|
|
663
|
+
// =========================================================================
|
|
664
|
+
// Convenience methods for common order types
|
|
665
|
+
// =========================================================================
|
|
666
|
+
/**
|
|
667
|
+
* Place a limit buy order (human-readable values)
|
|
668
|
+
* @param symbol - Trading pair symbol (e.g., "BTC-USDT")
|
|
669
|
+
* @param tradingPairId - Trading pair ID
|
|
670
|
+
* @param quantity - Amount to buy
|
|
671
|
+
* @param price - Price per unit
|
|
672
|
+
*/
|
|
673
|
+
async limitBuy(symbol, tradingPairId, quantity, price) {
|
|
674
|
+
return this.submit({
|
|
675
|
+
symbol,
|
|
676
|
+
tradingPairId,
|
|
677
|
+
side: "BUY",
|
|
678
|
+
quantity,
|
|
679
|
+
price
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Place a limit sell order (human-readable values)
|
|
684
|
+
* @param symbol - Trading pair symbol (e.g., "BTC-USDT")
|
|
685
|
+
* @param tradingPairId - Trading pair ID
|
|
686
|
+
* @param quantity - Amount to sell
|
|
687
|
+
* @param price - Price per unit
|
|
688
|
+
*/
|
|
689
|
+
async limitSell(symbol, tradingPairId, quantity, price) {
|
|
690
|
+
return this.submit({
|
|
691
|
+
symbol,
|
|
692
|
+
tradingPairId,
|
|
693
|
+
side: "SELL",
|
|
694
|
+
quantity,
|
|
695
|
+
price
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Place a market buy order
|
|
700
|
+
* @param symbol - Trading pair symbol (e.g., "BTC-USDT")
|
|
701
|
+
* @param tradingPairId - Trading pair ID
|
|
702
|
+
* @param quantity - Amount to buy
|
|
703
|
+
* @param slippage - Slippage tolerance (0-1, e.g., 0.01 for 1%)
|
|
704
|
+
*/
|
|
705
|
+
async marketBuy(symbol, tradingPairId, quantity, slippage = 0.01) {
|
|
706
|
+
return this.submit({
|
|
707
|
+
symbol,
|
|
708
|
+
tradingPairId,
|
|
709
|
+
side: "BUY",
|
|
710
|
+
quantity,
|
|
711
|
+
price: "0",
|
|
712
|
+
slippage
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Place a market sell order
|
|
717
|
+
* @param symbol - Trading pair symbol (e.g., "BTC-USDT")
|
|
718
|
+
* @param tradingPairId - Trading pair ID
|
|
719
|
+
* @param quantity - Amount to sell
|
|
720
|
+
* @param slippage - Slippage tolerance (0-1, e.g., 0.01 for 1%)
|
|
721
|
+
*/
|
|
722
|
+
async marketSell(symbol, tradingPairId, quantity, slippage = 0.01) {
|
|
723
|
+
return this.submit({
|
|
724
|
+
symbol,
|
|
725
|
+
tradingPairId,
|
|
726
|
+
side: "SELL",
|
|
727
|
+
quantity,
|
|
728
|
+
price: "0",
|
|
729
|
+
slippage
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
// src/endpoints/wallet.ts
|
|
735
|
+
var WalletEndpoint = class {
|
|
736
|
+
constructor(http) {
|
|
737
|
+
this.http = http;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Get all wallet balances
|
|
741
|
+
* Each balance includes:
|
|
742
|
+
* - balance: Total balance (raw value)
|
|
743
|
+
* - locked_balance: Locked in orders (raw value)
|
|
744
|
+
* - wallet_id: UUID of the wallet
|
|
745
|
+
* - deposit_address: Deposit address for this asset
|
|
746
|
+
* - id, symbol, name, decimals: Asset info
|
|
747
|
+
* - min_deposit, min_withdrawal, withdrawal_fee: Limits
|
|
748
|
+
*
|
|
749
|
+
* @example
|
|
750
|
+
* const balances = await client.wallet.balances();
|
|
751
|
+
* const ethBalance = balances.find(b => b.symbol === 'ETH');
|
|
752
|
+
* console.log(`ETH Balance: ${ethBalance?.balance}`);
|
|
753
|
+
* console.log(`Deposit Address: ${ethBalance?.deposit_address}`);
|
|
754
|
+
*/
|
|
755
|
+
async balances() {
|
|
756
|
+
const balances = await this.http.get("/api/user-balances");
|
|
757
|
+
return balances.map((b) => {
|
|
758
|
+
const balance = BigInt(b.balance);
|
|
759
|
+
const locked = BigInt(b.locked_balance);
|
|
760
|
+
const available = balance - locked;
|
|
761
|
+
const decimals = b.decimals;
|
|
762
|
+
return {
|
|
763
|
+
...b,
|
|
764
|
+
available_balance: available.toString(),
|
|
765
|
+
human_balance: this.formatUnits(b.balance, decimals),
|
|
766
|
+
human_locked: this.formatUnits(b.locked_balance, decimals),
|
|
767
|
+
human_available: this.formatUnits(available.toString(), decimals)
|
|
768
|
+
};
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Get balance for a specific asset
|
|
773
|
+
* @param symbol - Asset symbol (e.g., "BTC", "ETH", "USDT")
|
|
774
|
+
*/
|
|
775
|
+
async balance(symbol) {
|
|
776
|
+
const balances = await this.balances();
|
|
777
|
+
return balances.find((b) => b.symbol.toUpperCase() === symbol.toUpperCase());
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Get deposit address for an asset (from balance data)
|
|
781
|
+
* The deposit_address is included in the balance response
|
|
782
|
+
* @param symbol - Asset symbol (e.g., "BTC")
|
|
783
|
+
* @example
|
|
784
|
+
* const address = await client.wallet.depositAddress('ETH');
|
|
785
|
+
* console.log(`Send ETH to: ${address.address}`);
|
|
786
|
+
*/
|
|
787
|
+
async depositAddress(symbol) {
|
|
788
|
+
const balances = await this.http.get("/api/user-balances");
|
|
789
|
+
const balance = balances.find((b) => b.symbol.toUpperCase() === symbol.toUpperCase());
|
|
790
|
+
if (!balance) {
|
|
791
|
+
return void 0;
|
|
792
|
+
}
|
|
793
|
+
return {
|
|
794
|
+
address: balance.deposit_address
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Generate a new deposit address (if supported)
|
|
799
|
+
* @param assetId - Asset ID
|
|
800
|
+
*/
|
|
801
|
+
async generateDepositAddress(assetId) {
|
|
802
|
+
const response = await this.http.post("/api/generate-deposit-address", {
|
|
803
|
+
assetId
|
|
804
|
+
});
|
|
805
|
+
return {
|
|
806
|
+
address: response.address,
|
|
807
|
+
memo: response.memo
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Submit a withdrawal request
|
|
812
|
+
* @param params - Withdrawal parameters
|
|
813
|
+
* @example
|
|
814
|
+
* const result = await client.wallet.withdraw({
|
|
815
|
+
* assetId: 2,
|
|
816
|
+
* symbol: 'ETH',
|
|
817
|
+
* address: '0x...',
|
|
818
|
+
* amount: '0.1'
|
|
819
|
+
* });
|
|
820
|
+
*
|
|
821
|
+
* if (result.requires_2fa) {
|
|
822
|
+
* // Need to complete 2FA verification
|
|
823
|
+
* await client.wallet.confirm2FA(result.session_token, '123456');
|
|
824
|
+
* }
|
|
825
|
+
*/
|
|
826
|
+
async withdraw(params) {
|
|
827
|
+
return this.http.post("/api/submit-withdraw", {
|
|
828
|
+
assetId: params.assetId,
|
|
829
|
+
symbol: params.symbol,
|
|
830
|
+
address: params.address,
|
|
831
|
+
amount: params.amount,
|
|
832
|
+
destinationTag: params.memo
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Complete withdrawal 2FA verification
|
|
837
|
+
* @param sessionToken - Session token from withdraw response
|
|
838
|
+
* @param code - 2FA code from authenticator app
|
|
839
|
+
*/
|
|
840
|
+
async confirm2FA(sessionToken, code) {
|
|
841
|
+
return this.http.post("/api/withdrawal/complete-2fa", {
|
|
842
|
+
sessionToken,
|
|
843
|
+
code
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Get deposit history
|
|
848
|
+
* @param options - Pagination options
|
|
849
|
+
*/
|
|
850
|
+
async deposits(options = {}) {
|
|
851
|
+
return this.http.get("/api/deposits", {
|
|
852
|
+
limit: options.limit || 50,
|
|
853
|
+
offset: options.offset || 0
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Get withdrawal history
|
|
858
|
+
* @param options - Pagination options
|
|
859
|
+
*/
|
|
860
|
+
async withdrawals(options = {}) {
|
|
861
|
+
return this.http.get("/api/withdrawals", {
|
|
862
|
+
limit: options.limit || 50,
|
|
863
|
+
offset: options.offset || 0
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Get transaction history (deposits + withdrawals + trades)
|
|
868
|
+
*/
|
|
869
|
+
async history() {
|
|
870
|
+
return this.http.get("/api/history");
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Format raw units to human-readable decimal string
|
|
874
|
+
* @param value - Raw value as string
|
|
875
|
+
* @param decimals - Number of decimals
|
|
876
|
+
*/
|
|
877
|
+
formatUnits(value, decimals) {
|
|
878
|
+
if (decimals === 0) return value;
|
|
879
|
+
const str = value.padStart(decimals + 1, "0");
|
|
880
|
+
const intPart = str.slice(0, -decimals) || "0";
|
|
881
|
+
const decPart = str.slice(-decimals);
|
|
882
|
+
const trimmedDec = decPart.replace(/0+$/, "");
|
|
883
|
+
return trimmedDec ? `${intPart}.${trimmedDec}` : intPart;
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
|
|
887
|
+
// src/endpoints/invoices.ts
|
|
888
|
+
var InvoicesEndpoint = class {
|
|
889
|
+
constructor(http) {
|
|
890
|
+
this.http = http;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Create a new payment invoice
|
|
894
|
+
* @param params - Invoice parameters
|
|
895
|
+
* @example
|
|
896
|
+
* const invoice = await client.invoices.create({
|
|
897
|
+
* amount: '100.00',
|
|
898
|
+
* asset: 'USDT',
|
|
899
|
+
* description: 'Order #12345',
|
|
900
|
+
* external_id: 'order-12345',
|
|
901
|
+
* webhook_url: 'https://yoursite.com/webhook'
|
|
902
|
+
* });
|
|
903
|
+
*
|
|
904
|
+
* console.log(`Payment address: ${invoice.payment_address}`);
|
|
905
|
+
* console.log(`Expires: ${invoice.expires_at}`);
|
|
906
|
+
*/
|
|
907
|
+
async create(params) {
|
|
908
|
+
const response = await this.http.post("/api/invoices", {
|
|
909
|
+
amount: params.amount,
|
|
910
|
+
asset: params.asset,
|
|
911
|
+
description: params.description,
|
|
912
|
+
external_id: params.external_id,
|
|
913
|
+
webhook_url: params.webhook_url,
|
|
914
|
+
redirect_url: params.redirect_url,
|
|
915
|
+
expires_in: params.expires_in
|
|
916
|
+
});
|
|
917
|
+
if (!response.data) {
|
|
918
|
+
throw new Error("Failed to create invoice");
|
|
919
|
+
}
|
|
920
|
+
return response.data;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Get all invoices
|
|
924
|
+
* @param options - Pagination and filter options
|
|
925
|
+
*/
|
|
926
|
+
async list(options = {}) {
|
|
927
|
+
return this.http.get("/api/invoices", {
|
|
928
|
+
limit: options.limit || 50,
|
|
929
|
+
offset: options.offset || 0,
|
|
930
|
+
status: options.status
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Get a specific invoice by ID
|
|
935
|
+
* @param invoiceId - Invoice UUID
|
|
936
|
+
*/
|
|
937
|
+
async get(invoiceId) {
|
|
938
|
+
const response = await this.http.get(`/api/invoices/${invoiceId}`);
|
|
939
|
+
if (!response.data) {
|
|
940
|
+
throw new Error("Invoice not found");
|
|
941
|
+
}
|
|
942
|
+
return response.data;
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Get invoice status (for polling)
|
|
946
|
+
* @param invoiceId - Invoice UUID
|
|
947
|
+
*/
|
|
948
|
+
async status(invoiceId) {
|
|
949
|
+
return this.http.get(`/api/invoices/${invoiceId}/status`);
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Cancel a pending invoice
|
|
953
|
+
* @param invoiceId - Invoice UUID
|
|
954
|
+
*/
|
|
955
|
+
async cancel(invoiceId) {
|
|
956
|
+
return this.http.post(`/api/invoices/${invoiceId}/cancel`);
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Get invoice PDF
|
|
960
|
+
* @param invoiceId - Invoice UUID
|
|
961
|
+
* @returns PDF blob
|
|
962
|
+
*/
|
|
963
|
+
async pdf(invoiceId) {
|
|
964
|
+
return this.http.get(`/api/invoices/${invoiceId}/pdf`);
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Get estimated fees for an invoice
|
|
968
|
+
* @param asset - Asset symbol
|
|
969
|
+
* @param amount - Invoice amount
|
|
970
|
+
*/
|
|
971
|
+
async fees(asset, amount) {
|
|
972
|
+
const response = await this.http.get("/api/invoices/fees", {
|
|
973
|
+
asset,
|
|
974
|
+
amount
|
|
975
|
+
});
|
|
976
|
+
if (!response.data) {
|
|
977
|
+
return {
|
|
978
|
+
network_fee: "0",
|
|
979
|
+
service_fee: "0",
|
|
980
|
+
total_fee: "0"
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
return response.data;
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Get public invoice payment page data (no auth required)
|
|
987
|
+
* @param invoiceId - Invoice UUID
|
|
988
|
+
*/
|
|
989
|
+
async paymentPage(invoiceId) {
|
|
990
|
+
return this.http.get(`/api/invoices/${invoiceId}/pay`);
|
|
991
|
+
}
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
// src/client.ts
|
|
995
|
+
var DEFAULT_BASE_URL = "https://api.klingex.io";
|
|
996
|
+
var DEFAULT_WS_URL = "wss://api.klingex.io/ws";
|
|
997
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
998
|
+
var KlingEx = class {
|
|
999
|
+
constructor(config = {}) {
|
|
1000
|
+
this._ws = null;
|
|
1001
|
+
this.config = {
|
|
1002
|
+
apiKey: config.apiKey,
|
|
1003
|
+
jwt: config.jwt,
|
|
1004
|
+
baseUrl: config.baseUrl || DEFAULT_BASE_URL,
|
|
1005
|
+
wsUrl: config.wsUrl || DEFAULT_WS_URL,
|
|
1006
|
+
timeout: config.timeout || DEFAULT_TIMEOUT,
|
|
1007
|
+
humanReadable: config.humanReadable ?? true
|
|
1008
|
+
};
|
|
1009
|
+
this.http = new HttpClient({
|
|
1010
|
+
baseUrl: this.config.baseUrl,
|
|
1011
|
+
apiKey: this.config.apiKey,
|
|
1012
|
+
jwt: this.config.jwt,
|
|
1013
|
+
timeout: this.config.timeout
|
|
1014
|
+
});
|
|
1015
|
+
this.markets = new MarketsEndpoint(this.http);
|
|
1016
|
+
this.orders = new OrdersEndpoint(this.http, this.config.humanReadable);
|
|
1017
|
+
this.wallet = new WalletEndpoint(this.http);
|
|
1018
|
+
this.invoices = new InvoicesEndpoint(this.http);
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* WebSocket client for real-time data
|
|
1022
|
+
* Note: Call ws.connect() before subscribing to channels
|
|
1023
|
+
*/
|
|
1024
|
+
get ws() {
|
|
1025
|
+
if (!this._ws) {
|
|
1026
|
+
this._ws = new KlingExWebSocket(
|
|
1027
|
+
this.config.wsUrl,
|
|
1028
|
+
{ apiKey: this.config.apiKey, jwt: this.config.jwt }
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
return this._ws;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Create WebSocket connection with custom options
|
|
1035
|
+
*/
|
|
1036
|
+
createWebSocket(options) {
|
|
1037
|
+
return new KlingExWebSocket(
|
|
1038
|
+
this.config.wsUrl,
|
|
1039
|
+
{ apiKey: this.config.apiKey, jwt: this.config.jwt },
|
|
1040
|
+
options
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Update authentication credentials
|
|
1045
|
+
*/
|
|
1046
|
+
setAuth(auth) {
|
|
1047
|
+
if (auth.apiKey) this.config.apiKey = auth.apiKey;
|
|
1048
|
+
if (auth.jwt) this.config.jwt = auth.jwt;
|
|
1049
|
+
this.http.setAuth(auth);
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Check if client has authentication configured
|
|
1053
|
+
*/
|
|
1054
|
+
get isAuthenticated() {
|
|
1055
|
+
return !!(this.config.apiKey || this.config.jwt);
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Get the configured base URL
|
|
1059
|
+
*/
|
|
1060
|
+
get baseUrl() {
|
|
1061
|
+
return this.config.baseUrl;
|
|
1062
|
+
}
|
|
1063
|
+
// =========================================================================
|
|
1064
|
+
// Account endpoints (directly on client for convenience)
|
|
1065
|
+
// =========================================================================
|
|
1066
|
+
/**
|
|
1067
|
+
* Get current user profile
|
|
1068
|
+
*/
|
|
1069
|
+
async getProfile() {
|
|
1070
|
+
return this.http.get("/api/profile");
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Get current user info
|
|
1074
|
+
*/
|
|
1075
|
+
async getUser() {
|
|
1076
|
+
return this.http.get("/api/user");
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Get API key statistics
|
|
1080
|
+
*/
|
|
1081
|
+
async getApiKeyStats() {
|
|
1082
|
+
return this.http.get("/api/api-keys/stats");
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1086
|
+
0 && (module.exports = {
|
|
1087
|
+
AuthenticationError,
|
|
1088
|
+
InsufficientFundsError,
|
|
1089
|
+
InvoicesEndpoint,
|
|
1090
|
+
KlingEx,
|
|
1091
|
+
KlingExError,
|
|
1092
|
+
KlingExWebSocket,
|
|
1093
|
+
MarketsEndpoint,
|
|
1094
|
+
OrdersEndpoint,
|
|
1095
|
+
RateLimitError,
|
|
1096
|
+
ValidationError,
|
|
1097
|
+
WalletEndpoint
|
|
1098
|
+
});
|