better-bitkub-client 0.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 ADDED
@@ -0,0 +1,42 @@
1
+ # better-bitkub-client
2
+
3
+ TypeScript rewrite of the repository's C# `bitkubwrapper` library.
4
+
5
+ ## What it includes
6
+
7
+ - `BitkubV3Client` for V3 market, user, trading, and fiat endpoints
8
+ - `BitkubV4Client` for V4 crypto endpoints
9
+ - shared HMAC-SHA256 signing logic
10
+ - typed request and response models matching the current API surface
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install
16
+ npm run build
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```ts
22
+ import { BitkubV3Client, BitkubV4Client } from "./dist/index.js";
23
+
24
+ const v3 = new BitkubV3Client({
25
+ apiKey: process.env.BITKUB_KEY!,
26
+ apiSecret: process.env.BITKUB_SECRET!
27
+ });
28
+
29
+ const v4 = new BitkubV4Client({
30
+ apiKey: process.env.BITKUB_KEY!,
31
+ apiSecret: process.env.BITKUB_SECRET!
32
+ });
33
+
34
+ const symbols = await v3.getSymbols();
35
+ const withdraws = await v4.getCryptoWithdraws({ limit: 50 });
36
+ ```
37
+
38
+ ## Notes
39
+
40
+ - Requires Node 18+ for the built-in `fetch` API.
41
+ - The default base URL is `https://api.bitkub.com`.
42
+ - DTOs keep Bitkub's field names to make request/response handling predictable.
@@ -0,0 +1,35 @@
1
+ export interface BitkubClientOptions {
2
+ apiKey: string;
3
+ apiSecret: string;
4
+ baseUrl?: string;
5
+ fetchImpl?: typeof fetch;
6
+ }
7
+ type QueryValue = string | number | boolean | null | undefined;
8
+ type QueryParams = Record<string, QueryValue>;
9
+ export declare class BitkubApiError extends Error {
10
+ readonly status: number;
11
+ readonly responseBody: string;
12
+ constructor(status: number, responseBody: string);
13
+ }
14
+ export declare abstract class BitkubBaseClient {
15
+ protected readonly apiKey: string;
16
+ protected readonly apiSecret: string;
17
+ protected readonly baseUrl: string;
18
+ private readonly fetchImpl;
19
+ constructor(options: BitkubClientOptions);
20
+ getServerTime(): Promise<number>;
21
+ protected sendRequest<T>(method: string, path: string, options?: {
22
+ body?: unknown;
23
+ queryParams?: QueryParams;
24
+ }): Promise<T>;
25
+ protected sendSecureRequest<T>(method: string, path: string, options?: {
26
+ body?: unknown;
27
+ queryParams?: QueryParams;
28
+ }): Promise<T>;
29
+ private buildPath;
30
+ private serializeBody;
31
+ private buildHeaders;
32
+ private resolveRequestBody;
33
+ private readJson;
34
+ }
35
+ export {};
@@ -0,0 +1,109 @@
1
+ import { generateSignature } from "./utils/signature.js";
2
+ export class BitkubApiError extends Error {
3
+ status;
4
+ responseBody;
5
+ constructor(status, responseBody) {
6
+ super(`API request failed with status ${status}: ${responseBody}`);
7
+ this.name = "BitkubApiError";
8
+ this.status = status;
9
+ this.responseBody = responseBody;
10
+ }
11
+ }
12
+ export class BitkubBaseClient {
13
+ apiKey;
14
+ apiSecret;
15
+ baseUrl;
16
+ fetchImpl;
17
+ constructor(options) {
18
+ if (!options.apiKey) {
19
+ throw new Error("apiKey is required");
20
+ }
21
+ if (!options.apiSecret) {
22
+ throw new Error("apiSecret is required");
23
+ }
24
+ this.apiKey = options.apiKey;
25
+ this.apiSecret = options.apiSecret;
26
+ this.baseUrl = options.baseUrl ?? "https://api.bitkub.com";
27
+ this.fetchImpl = options.fetchImpl ?? fetch;
28
+ }
29
+ async getServerTime() {
30
+ const response = await this.fetchImpl(`${this.baseUrl}/api/v3/servertime`, {
31
+ method: "GET",
32
+ headers: {
33
+ Accept: "application/json"
34
+ }
35
+ });
36
+ const text = await response.text();
37
+ if (!response.ok) {
38
+ throw new BitkubApiError(response.status, text);
39
+ }
40
+ return Number.parseInt(text.trim(), 10);
41
+ }
42
+ async sendRequest(method, path, options) {
43
+ const fullPath = this.buildPath(path, options?.queryParams);
44
+ const bodyJson = this.serializeBody(options?.body);
45
+ const requestBody = this.resolveRequestBody(method, bodyJson);
46
+ const response = await this.fetchImpl(`${this.baseUrl}${fullPath}`, {
47
+ method,
48
+ headers: this.buildHeaders(false, undefined, undefined, Boolean(requestBody)),
49
+ body: requestBody
50
+ });
51
+ return this.readJson(response);
52
+ }
53
+ async sendSecureRequest(method, path, options) {
54
+ const timestamp = String(await this.getServerTime());
55
+ const fullPath = this.buildPath(path, options?.queryParams);
56
+ const bodyJson = this.serializeBody(options?.body);
57
+ const requestBody = this.resolveRequestBody(method, bodyJson);
58
+ const signature = generateSignature(timestamp, method, fullPath, bodyJson, this.apiSecret);
59
+ const response = await this.fetchImpl(`${this.baseUrl}${fullPath}`, {
60
+ method,
61
+ headers: this.buildHeaders(true, timestamp, signature, Boolean(requestBody)),
62
+ body: requestBody
63
+ });
64
+ return this.readJson(response);
65
+ }
66
+ buildPath(path, queryParams) {
67
+ if (!queryParams) {
68
+ return path;
69
+ }
70
+ const pairs = Object.entries(queryParams).filter(([, value]) => value !== undefined && value !== null);
71
+ if (pairs.length === 0) {
72
+ return path;
73
+ }
74
+ const query = pairs
75
+ .map(([key, value]) => `${key}=${encodeURIComponent(String(value))}`)
76
+ .join("&");
77
+ return `${path}?${query}`;
78
+ }
79
+ serializeBody(body) {
80
+ return body === undefined ? "" : JSON.stringify(body);
81
+ }
82
+ buildHeaders(secure, timestamp, signature, hasJsonBody = false) {
83
+ const headers = {
84
+ Accept: "application/json"
85
+ };
86
+ if (hasJsonBody) {
87
+ headers["Content-Type"] = "application/json";
88
+ }
89
+ if (secure) {
90
+ headers["X-BTK-APIKEY"] = this.apiKey;
91
+ headers["X-BTK-TIMESTAMP"] = timestamp ?? "";
92
+ headers["X-BTK-SIGN"] = signature ?? "";
93
+ }
94
+ return headers;
95
+ }
96
+ resolveRequestBody(method, bodyJson) {
97
+ if (method.toUpperCase() !== "POST" || !bodyJson) {
98
+ return undefined;
99
+ }
100
+ return bodyJson;
101
+ }
102
+ async readJson(response) {
103
+ const text = await response.text();
104
+ if (!response.ok) {
105
+ throw new BitkubApiError(response.status, text);
106
+ }
107
+ return JSON.parse(text);
108
+ }
109
+ }
@@ -0,0 +1,6 @@
1
+ export { BitkubApiError, type BitkubClientOptions } from "./base-client.js";
2
+ export { BitkubV3Client } from "./v3-client.js";
3
+ export { BitkubV4Client } from "./v4-client.js";
4
+ export { generateSignature } from "./utils/signature.js";
5
+ export type * from "./types/v3.js";
6
+ export type * from "./types/v4.js";
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { BitkubApiError } from "./base-client.js";
2
+ export { BitkubV3Client } from "./v3-client.js";
3
+ export { BitkubV4Client } from "./v4-client.js";
4
+ export { generateSignature } from "./utils/signature.js";
@@ -0,0 +1,240 @@
1
+ export interface BitkubV3Response<T> {
2
+ error: number;
3
+ result?: T;
4
+ pagination?: PaginationInfo;
5
+ }
6
+ export interface PaginationInfo {
7
+ page?: number;
8
+ last?: number;
9
+ next?: number;
10
+ prev?: number;
11
+ cursor?: string;
12
+ has_next?: boolean;
13
+ }
14
+ export interface StatusResponse {
15
+ name?: string;
16
+ status?: string;
17
+ message?: string;
18
+ }
19
+ export interface SymbolInfo {
20
+ base_asset: string;
21
+ base_asset_scale: number;
22
+ buy_price_gap_as_percent: number;
23
+ created_at: string;
24
+ description: string;
25
+ freeze_buy: boolean;
26
+ freeze_cancel: boolean;
27
+ freeze_sell: boolean;
28
+ market_segment: string;
29
+ min_quote_size: number;
30
+ modified_at: string;
31
+ name: string;
32
+ pairing_id: number;
33
+ price_scale: number;
34
+ price_step: string;
35
+ quantity_scale: number;
36
+ quantity_step: string;
37
+ quote_asset: string;
38
+ quote_asset_scale: number;
39
+ sell_price_gap_as_percent: number;
40
+ status: string;
41
+ symbol: string;
42
+ source: string;
43
+ }
44
+ export interface Ticker {
45
+ symbol: string;
46
+ base_volume: string;
47
+ high_24_hr: string;
48
+ highest_bid: string;
49
+ last: string;
50
+ low_24_hr: string;
51
+ lowest_ask: string;
52
+ percent_change: string;
53
+ quote_volume: string;
54
+ }
55
+ export interface OrderBookEntry {
56
+ order_id: string;
57
+ price: string;
58
+ side: string;
59
+ size: string;
60
+ timestamp: number;
61
+ volume: string;
62
+ }
63
+ export interface Depth {
64
+ asks: number[][];
65
+ bids: number[][];
66
+ }
67
+ export type RawTrade = Array<string | number | boolean | null>;
68
+ export interface LimitsResponse {
69
+ limits: LimitsData;
70
+ usage: UsageData;
71
+ rate: number;
72
+ }
73
+ export interface LimitsData {
74
+ crypto: LimitInfo;
75
+ fiat: LimitInfo;
76
+ }
77
+ export interface LimitInfo {
78
+ deposit: number;
79
+ withdraw: number;
80
+ }
81
+ export interface UsageData {
82
+ crypto: UsageInfo;
83
+ fiat: UsageInfo;
84
+ }
85
+ export interface UsageInfo {
86
+ deposit: number;
87
+ withdraw: number;
88
+ deposit_percentage: number;
89
+ withdraw_percentage: number;
90
+ deposit_thb_equivalent?: number | null;
91
+ withdraw_thb_equivalent?: number | null;
92
+ }
93
+ export interface CoinConvertHistoryItem {
94
+ transaction_id: string;
95
+ status: string;
96
+ amount: string;
97
+ from_currency: string;
98
+ trading_fee_received: string;
99
+ timestamp: number;
100
+ }
101
+ export interface BalanceInfo {
102
+ available: number;
103
+ reserved: number;
104
+ }
105
+ export interface PlaceOrderRequest {
106
+ sym: string;
107
+ amt: number;
108
+ rat: number;
109
+ typ?: string;
110
+ client_id?: string;
111
+ post_only?: boolean;
112
+ }
113
+ export interface PlaceOrderResponse {
114
+ id: string;
115
+ typ: string;
116
+ amt: number;
117
+ rat: number;
118
+ fee: number;
119
+ cre: number;
120
+ rec: number;
121
+ ts: string;
122
+ ci?: string | null;
123
+ }
124
+ export interface CancelOrderRequest {
125
+ sym: string;
126
+ id: string;
127
+ sd: string;
128
+ }
129
+ export interface OpenOrder {
130
+ id: string;
131
+ side: string;
132
+ type: string;
133
+ rate: string;
134
+ fee: string;
135
+ credit: string;
136
+ amount: string;
137
+ receive: string;
138
+ parent_id: string;
139
+ super_id: string;
140
+ client_id?: string | null;
141
+ ts: number;
142
+ }
143
+ export interface OrderHistoryItem {
144
+ txn_id: string;
145
+ order_id: string;
146
+ parent_order_id: string;
147
+ super_order_id: string;
148
+ client_id?: string | null;
149
+ taken_by_me: boolean;
150
+ is_maker: boolean;
151
+ side: string;
152
+ type: string;
153
+ rate: string;
154
+ fee: string;
155
+ credit: string;
156
+ amount: string;
157
+ ts: number;
158
+ order_closed_at?: number | null;
159
+ }
160
+ export interface OrderHistoryItemWithSymbol extends OrderHistoryItem {
161
+ symbol: string;
162
+ }
163
+ export interface OrderInfo {
164
+ id: string;
165
+ first: string;
166
+ parent: string;
167
+ last: string;
168
+ client_id: string;
169
+ post_only: boolean;
170
+ amount: string;
171
+ rate: number;
172
+ fee: number;
173
+ credit: number;
174
+ filled: number;
175
+ total: number;
176
+ status: string;
177
+ partial_filled: boolean;
178
+ remaining: number;
179
+ history: OrderInfoHistory[];
180
+ }
181
+ export interface OrderInfoHistory {
182
+ amount: number;
183
+ credit: number;
184
+ fee: number;
185
+ id: string;
186
+ rate: number;
187
+ timestamp: number;
188
+ txn_id: string;
189
+ }
190
+ export interface BankAccount {
191
+ id: string;
192
+ bank: string;
193
+ name: string;
194
+ time: number;
195
+ }
196
+ export interface FiatWithdrawRequest {
197
+ id: string;
198
+ amt: number;
199
+ }
200
+ export interface FiatWithdrawResponse {
201
+ txn: string;
202
+ acc: string;
203
+ cur: string;
204
+ amt: number;
205
+ fee: number;
206
+ rec: number;
207
+ ts: number;
208
+ }
209
+ export interface FiatDepositHistoryItem {
210
+ txn_id: string;
211
+ currency: string;
212
+ amount: number;
213
+ status: string;
214
+ time: number;
215
+ }
216
+ export interface FiatWithdrawHistoryItem {
217
+ txn_id: string;
218
+ currency: string;
219
+ amount: string;
220
+ fee: number;
221
+ status: string;
222
+ time: number;
223
+ }
224
+ export interface CoinConvertHistoryOptions {
225
+ page?: number;
226
+ limit?: number;
227
+ sort?: number;
228
+ status?: string;
229
+ symbol?: string;
230
+ start?: number;
231
+ end?: number;
232
+ }
233
+ export interface OrderHistoryOptions {
234
+ page?: number;
235
+ limit?: number;
236
+ cursor?: string;
237
+ start?: string;
238
+ end?: string;
239
+ pagination_type?: string;
240
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,152 @@
1
+ export interface BitkubV4Response<T> {
2
+ code: string;
3
+ message: string;
4
+ data?: T;
5
+ }
6
+ export interface CryptoAddress {
7
+ symbol: string;
8
+ network: string;
9
+ address: string;
10
+ memo: string;
11
+ created_at?: string | null;
12
+ }
13
+ export interface CryptoAddressesResponse {
14
+ page: number;
15
+ total_page: number;
16
+ total_item: number;
17
+ items: CryptoAddress[];
18
+ }
19
+ export interface CreateCryptoAddressRequest {
20
+ symbol: string;
21
+ network: string;
22
+ }
23
+ export interface CryptoDeposit {
24
+ hash: string;
25
+ symbol: string;
26
+ network: string;
27
+ amount: string;
28
+ from_address: string;
29
+ to_address: string;
30
+ confirmations: number;
31
+ status: string;
32
+ created_at: string;
33
+ completed_at?: string | null;
34
+ }
35
+ export interface CryptoDepositsResponse {
36
+ page: number;
37
+ total_page: number;
38
+ total_item: number;
39
+ items: CryptoDeposit[];
40
+ }
41
+ export interface CryptoWithdraw {
42
+ txn_id: string;
43
+ external_ref?: string | null;
44
+ hash?: string | null;
45
+ symbol: string;
46
+ network: string;
47
+ amount: string;
48
+ fee: string;
49
+ address: string;
50
+ memo: string;
51
+ status: string;
52
+ created_at: string;
53
+ completed_at?: string | null;
54
+ }
55
+ export interface CryptoWithdrawsResponse {
56
+ page: number;
57
+ total_page: number;
58
+ total_item: number;
59
+ items: CryptoWithdraw[];
60
+ }
61
+ export interface CreateCryptoWithdrawRequest {
62
+ symbol: string;
63
+ amount: string;
64
+ address: string;
65
+ memo?: string;
66
+ network: string;
67
+ }
68
+ export interface CreateCryptoWithdrawResponse {
69
+ txn_id: string;
70
+ symbol: string;
71
+ network: string;
72
+ amount: string;
73
+ fee: string;
74
+ address: string;
75
+ memo: string;
76
+ created_at: string;
77
+ }
78
+ export interface CoinNetwork {
79
+ name: string;
80
+ network: string;
81
+ address_regex: string;
82
+ memo_regex: string;
83
+ explorer: string;
84
+ contract_address: string;
85
+ withdraw_min: string;
86
+ withdraw_fee: string;
87
+ withdraw_internal_min: string;
88
+ withdraw_internal_fee: string;
89
+ withdraw_decimal_places: number;
90
+ min_confirm: number;
91
+ decimal: number;
92
+ deposit_enable: boolean;
93
+ withdraw_enable: boolean;
94
+ is_memo: boolean;
95
+ }
96
+ export interface Coin {
97
+ name: string;
98
+ symbol: string;
99
+ networks: CoinNetwork[];
100
+ deposit_enable: boolean;
101
+ withdraw_enable: boolean;
102
+ }
103
+ export interface CoinsResponse {
104
+ items: Coin[];
105
+ }
106
+ export interface Compensation {
107
+ txn_id: string;
108
+ symbol: string;
109
+ type: string;
110
+ amount: string;
111
+ status: string;
112
+ created_at: string;
113
+ completed_at?: string | null;
114
+ }
115
+ export interface CompensationsResponse {
116
+ page: number;
117
+ total_page: number;
118
+ total_item: number;
119
+ items: Compensation[];
120
+ }
121
+ export interface ListOptions {
122
+ page?: number;
123
+ limit?: number;
124
+ }
125
+ export interface CryptoAddressesOptions extends ListOptions {
126
+ symbol?: string;
127
+ network?: string;
128
+ memo?: string;
129
+ }
130
+ export interface CryptoDepositsOptions extends ListOptions {
131
+ symbol?: string;
132
+ status?: string;
133
+ created_start?: string;
134
+ created_end?: string;
135
+ }
136
+ export interface CryptoWithdrawsOptions extends ListOptions {
137
+ symbol?: string;
138
+ status?: string;
139
+ created_start?: string;
140
+ created_end?: string;
141
+ }
142
+ export interface CoinsOptions {
143
+ symbol?: string;
144
+ network?: string;
145
+ }
146
+ export interface CompensationsOptions extends ListOptions {
147
+ symbol?: string;
148
+ type?: string;
149
+ status?: string;
150
+ created_start?: string;
151
+ created_end?: string;
152
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function generateSignature(timestamp: string, method: string, path: string, body?: string, apiSecret?: string): string;
@@ -0,0 +1,10 @@
1
+ import { createHmac } from "node:crypto";
2
+ export function generateSignature(timestamp, method, path, body = "", apiSecret = "") {
3
+ if (!apiSecret) {
4
+ throw new Error("API secret cannot be null or empty");
5
+ }
6
+ const payload = `${timestamp}${method}${path}${body}`;
7
+ return createHmac("sha256", Buffer.from(apiSecret, "utf8"))
8
+ .update(Buffer.from(payload, "utf8"))
9
+ .digest("hex");
10
+ }
@@ -0,0 +1,27 @@
1
+ import { BitkubBaseClient, type BitkubClientOptions } from "./base-client.js";
2
+ import type { BalanceInfo, BankAccount, BitkubV3Response, CancelOrderRequest, CoinConvertHistoryItem, CoinConvertHistoryOptions, Depth, FiatDepositHistoryItem, FiatWithdrawHistoryItem, FiatWithdrawRequest, FiatWithdrawResponse, LimitsResponse, OpenOrder, OrderBookEntry, OrderHistoryItem, OrderHistoryOptions, OrderInfo, PlaceOrderRequest, PlaceOrderResponse, RawTrade, StatusResponse, SymbolInfo, Ticker } from "./types/v3.js";
3
+ export declare class BitkubV3Client extends BitkubBaseClient {
4
+ constructor(options: BitkubClientOptions);
5
+ getStatus(): Promise<StatusResponse[]>;
6
+ getSymbols(): Promise<BitkubV3Response<SymbolInfo[]>>;
7
+ getTicker(symbol?: string): Promise<Ticker[]>;
8
+ getBids(symbol: string, limit?: number): Promise<BitkubV3Response<OrderBookEntry[]>>;
9
+ getAsks(symbol: string, limit?: number): Promise<BitkubV3Response<OrderBookEntry[]>>;
10
+ getDepth(symbol: string, limit?: number): Promise<BitkubV3Response<Depth>>;
11
+ getTrades(symbol: string, limit?: number): Promise<BitkubV3Response<RawTrade[]>>;
12
+ getTradingCredits(): Promise<BitkubV3Response<number>>;
13
+ getLimits(): Promise<BitkubV3Response<LimitsResponse>>;
14
+ getCoinConvertHistory(options?: CoinConvertHistoryOptions): Promise<BitkubV3Response<CoinConvertHistoryItem[]>>;
15
+ getWallet(): Promise<BitkubV3Response<Record<string, number>>>;
16
+ getBalances(): Promise<BitkubV3Response<Record<string, BalanceInfo>>>;
17
+ placeBid(request: PlaceOrderRequest): Promise<BitkubV3Response<PlaceOrderResponse>>;
18
+ placeAsk(request: PlaceOrderRequest): Promise<BitkubV3Response<PlaceOrderResponse>>;
19
+ cancelOrder(request: CancelOrderRequest): Promise<BitkubV3Response<unknown>>;
20
+ getMyOpenOrders(symbol: string): Promise<BitkubV3Response<OpenOrder[]>>;
21
+ getMyOrderHistory(symbol: string, options?: OrderHistoryOptions): Promise<BitkubV3Response<OrderHistoryItem[]>>;
22
+ getOrderInfo(symbol: string, orderId: string, side: string): Promise<BitkubV3Response<OrderInfo>>;
23
+ getFiatAccounts(page?: number, limit?: number): Promise<BitkubV3Response<BankAccount[]>>;
24
+ fiatWithdraw(request: FiatWithdrawRequest): Promise<BitkubV3Response<FiatWithdrawResponse>>;
25
+ getFiatDepositHistory(page?: number, limit?: number): Promise<BitkubV3Response<FiatDepositHistoryItem[]>>;
26
+ getFiatWithdrawHistory(page?: number, limit?: number): Promise<BitkubV3Response<FiatWithdrawHistoryItem[]>>;
27
+ }
@@ -0,0 +1,124 @@
1
+ import { BitkubBaseClient } from "./base-client.js";
2
+ export class BitkubV3Client extends BitkubBaseClient {
3
+ constructor(options) {
4
+ super(options);
5
+ }
6
+ async getStatus() {
7
+ return this.sendRequest("GET", "/api/status");
8
+ }
9
+ async getSymbols() {
10
+ return this.sendRequest("GET", "/api/v3/market/symbols");
11
+ }
12
+ async getTicker(symbol) {
13
+ return this.sendRequest("GET", "/api/v3/market/ticker", {
14
+ queryParams: symbol ? { sym: symbol } : undefined
15
+ });
16
+ }
17
+ async getBids(symbol, limit) {
18
+ return this.sendRequest("GET", "/api/v3/market/bids", {
19
+ queryParams: { sym: symbol, lmt: limit }
20
+ });
21
+ }
22
+ async getAsks(symbol, limit) {
23
+ return this.sendRequest("GET", "/api/v3/market/asks", {
24
+ queryParams: { sym: symbol, lmt: limit }
25
+ });
26
+ }
27
+ async getDepth(symbol, limit) {
28
+ return this.sendRequest("GET", "/api/v3/market/depth", {
29
+ queryParams: { sym: symbol, lmt: limit }
30
+ });
31
+ }
32
+ async getTrades(symbol, limit) {
33
+ return this.sendRequest("GET", "/api/v3/market/trades", {
34
+ queryParams: { sym: symbol, lmt: limit }
35
+ });
36
+ }
37
+ async getTradingCredits() {
38
+ return this.sendSecureRequest("POST", "/api/v3/user/trading-credits");
39
+ }
40
+ async getLimits() {
41
+ return this.sendSecureRequest("POST", "/api/v3/user/limits");
42
+ }
43
+ async getCoinConvertHistory(options = {}) {
44
+ return this.sendSecureRequest("GET", "/api/v3/user/coin-convert-history", {
45
+ queryParams: {
46
+ p: options.page,
47
+ lmt: options.limit,
48
+ sort: options.sort,
49
+ status: options.status,
50
+ sym: options.symbol,
51
+ start: options.start,
52
+ end: options.end
53
+ }
54
+ });
55
+ }
56
+ async getWallet() {
57
+ return this.sendSecureRequest("POST", "/api/v3/market/wallet");
58
+ }
59
+ async getBalances() {
60
+ return this.sendSecureRequest("POST", "/api/v3/market/balances");
61
+ }
62
+ async placeBid(request) {
63
+ return this.sendSecureRequest("POST", "/api/v3/market/place-bid", {
64
+ body: { typ: "limit", ...request }
65
+ });
66
+ }
67
+ async placeAsk(request) {
68
+ return this.sendSecureRequest("POST", "/api/v3/market/place-ask", {
69
+ body: { typ: "limit", ...request }
70
+ });
71
+ }
72
+ async cancelOrder(request) {
73
+ return this.sendSecureRequest("POST", "/api/v3/market/cancel-order", {
74
+ body: request
75
+ });
76
+ }
77
+ async getMyOpenOrders(symbol) {
78
+ return this.sendSecureRequest("GET", "/api/v3/market/my-open-orders", {
79
+ queryParams: { sym: symbol }
80
+ });
81
+ }
82
+ async getMyOrderHistory(symbol, options = {}) {
83
+ return this.sendSecureRequest("GET", "/api/v3/market/my-order-history", {
84
+ queryParams: {
85
+ sym: symbol,
86
+ p: options.page,
87
+ lmt: options.limit,
88
+ cursor: options.cursor,
89
+ start: options.start,
90
+ end: options.end,
91
+ pagination_type: options.pagination_type
92
+ }
93
+ });
94
+ }
95
+ async getOrderInfo(symbol, orderId, side) {
96
+ return this.sendSecureRequest("GET", "/api/v3/market/order-info", {
97
+ queryParams: {
98
+ sym: symbol,
99
+ id: orderId,
100
+ sd: side
101
+ }
102
+ });
103
+ }
104
+ async getFiatAccounts(page, limit) {
105
+ return this.sendSecureRequest("POST", "/api/v3/fiat/accounts", {
106
+ queryParams: { p: page, lmt: limit }
107
+ });
108
+ }
109
+ async fiatWithdraw(request) {
110
+ return this.sendSecureRequest("POST", "/api/v3/fiat/withdraw", {
111
+ body: request
112
+ });
113
+ }
114
+ async getFiatDepositHistory(page, limit) {
115
+ return this.sendSecureRequest("POST", "/api/v3/fiat/deposit-history", {
116
+ queryParams: { p: page, lmt: limit }
117
+ });
118
+ }
119
+ async getFiatWithdrawHistory(page, limit) {
120
+ return this.sendSecureRequest("POST", "/api/v3/fiat/withdraw-history", {
121
+ queryParams: { p: page, lmt: limit }
122
+ });
123
+ }
124
+ }
@@ -0,0 +1,12 @@
1
+ import { BitkubBaseClient, type BitkubClientOptions } from "./base-client.js";
2
+ import type { BitkubV4Response, CoinsOptions, CoinsResponse, CompensationsOptions, CompensationsResponse, CreateCryptoAddressRequest, CreateCryptoWithdrawRequest, CreateCryptoWithdrawResponse, CryptoAddress, CryptoAddressesOptions, CryptoAddressesResponse, CryptoDepositsOptions, CryptoDepositsResponse, CryptoWithdrawsOptions, CryptoWithdrawsResponse } from "./types/v4.js";
3
+ export declare class BitkubV4Client extends BitkubBaseClient {
4
+ constructor(options: BitkubClientOptions);
5
+ getCryptoAddresses(options?: CryptoAddressesOptions): Promise<BitkubV4Response<CryptoAddressesResponse>>;
6
+ createCryptoAddress(request: CreateCryptoAddressRequest): Promise<BitkubV4Response<CryptoAddress[]>>;
7
+ getCryptoDeposits(options?: CryptoDepositsOptions): Promise<BitkubV4Response<CryptoDepositsResponse>>;
8
+ getCryptoWithdraws(options?: CryptoWithdrawsOptions): Promise<BitkubV4Response<CryptoWithdrawsResponse>>;
9
+ createCryptoWithdraw(request: CreateCryptoWithdrawRequest): Promise<BitkubV4Response<CreateCryptoWithdrawResponse>>;
10
+ getCoins(options?: CoinsOptions): Promise<BitkubV4Response<CoinsResponse>>;
11
+ getCompensations(options?: CompensationsOptions): Promise<BitkubV4Response<CompensationsResponse>>;
12
+ }
@@ -0,0 +1,72 @@
1
+ import { BitkubBaseClient } from "./base-client.js";
2
+ export class BitkubV4Client extends BitkubBaseClient {
3
+ constructor(options) {
4
+ super(options);
5
+ }
6
+ async getCryptoAddresses(options = {}) {
7
+ return this.sendSecureRequest("GET", "/api/v4/crypto/addresses", {
8
+ queryParams: {
9
+ page: options.page,
10
+ limit: options.limit,
11
+ symbol: options.symbol,
12
+ network: options.network,
13
+ memo: options.memo
14
+ }
15
+ });
16
+ }
17
+ async createCryptoAddress(request) {
18
+ return this.sendSecureRequest("POST", "/api/v4/crypto/addresses", {
19
+ body: request
20
+ });
21
+ }
22
+ async getCryptoDeposits(options = {}) {
23
+ return this.sendSecureRequest("GET", "/api/v4/crypto/deposits", {
24
+ queryParams: {
25
+ page: options.page,
26
+ limit: options.limit,
27
+ symbol: options.symbol,
28
+ status: options.status,
29
+ created_start: options.created_start,
30
+ created_end: options.created_end
31
+ }
32
+ });
33
+ }
34
+ async getCryptoWithdraws(options = {}) {
35
+ return this.sendSecureRequest("GET", "/api/v4/crypto/withdraws", {
36
+ queryParams: {
37
+ page: options.page,
38
+ limit: options.limit,
39
+ symbol: options.symbol,
40
+ status: options.status,
41
+ created_start: options.created_start,
42
+ created_end: options.created_end
43
+ }
44
+ });
45
+ }
46
+ async createCryptoWithdraw(request) {
47
+ return this.sendSecureRequest("POST", "/api/v4/crypto/withdraws", {
48
+ body: request
49
+ });
50
+ }
51
+ async getCoins(options = {}) {
52
+ return this.sendSecureRequest("GET", "/api/v4/crypto/coins", {
53
+ queryParams: {
54
+ symbol: options.symbol,
55
+ network: options.network
56
+ }
57
+ });
58
+ }
59
+ async getCompensations(options = {}) {
60
+ return this.sendSecureRequest("GET", "/api/v4/crypto/compensations", {
61
+ queryParams: {
62
+ page: options.page,
63
+ limit: options.limit,
64
+ symbol: options.symbol,
65
+ type: options.type,
66
+ status: options.status,
67
+ created_start: options.created_start,
68
+ created_end: options.created_end
69
+ }
70
+ });
71
+ }
72
+ }
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "better-bitkub-client",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript client for Bitkub V3 and V4 APIs",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "ssh://git@github.com:manooi/better-bitkub-client.git"
9
+ },
10
+ "type": "module",
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.json"
18
+ },
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^24.5.2",
24
+ "typescript": "^5.8.3"
25
+ }
26
+ }