@guiie/buda-mcp 1.4.2 → 1.5.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/CHANGELOG.md +39 -0
- package/dist/cache.d.ts +1 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +16 -0
- package/dist/http.js +55 -0
- package/dist/index.js +30 -0
- package/dist/tools/account.d.ts +19 -0
- package/dist/tools/account.d.ts.map +1 -0
- package/dist/tools/account.js +49 -0
- package/dist/tools/balance.d.ts +29 -0
- package/dist/tools/balance.d.ts.map +1 -0
- package/dist/tools/balance.js +72 -0
- package/dist/tools/banks.d.ts +28 -0
- package/dist/tools/banks.d.ts.map +1 -0
- package/dist/tools/banks.js +68 -0
- package/dist/tools/batch_orders.d.ts +77 -0
- package/dist/tools/batch_orders.d.ts.map +1 -0
- package/dist/tools/batch_orders.js +154 -0
- package/dist/tools/cancel_all_orders.d.ts +34 -0
- package/dist/tools/cancel_all_orders.d.ts.map +1 -0
- package/dist/tools/cancel_all_orders.js +89 -0
- package/dist/tools/cancel_order_by_client_id.d.ts +34 -0
- package/dist/tools/cancel_order_by_client_id.d.ts.map +1 -0
- package/dist/tools/cancel_order_by_client_id.js +102 -0
- package/dist/tools/deposits.d.ts +83 -0
- package/dist/tools/deposits.d.ts.map +1 -0
- package/dist/tools/deposits.js +174 -0
- package/dist/tools/fees.d.ts +34 -0
- package/dist/tools/fees.d.ts.map +1 -0
- package/dist/tools/fees.js +72 -0
- package/dist/tools/lightning.d.ts +68 -0
- package/dist/tools/lightning.d.ts.map +1 -0
- package/dist/tools/lightning.js +171 -0
- package/dist/tools/order_lookup.d.ts +50 -0
- package/dist/tools/order_lookup.d.ts.map +1 -0
- package/dist/tools/order_lookup.js +112 -0
- package/dist/tools/place_order.d.ts +30 -0
- package/dist/tools/place_order.d.ts.map +1 -1
- package/dist/tools/place_order.js +100 -2
- package/dist/tools/quotation.d.ts +44 -0
- package/dist/tools/quotation.d.ts.map +1 -0
- package/dist/tools/quotation.js +99 -0
- package/dist/tools/receive_addresses.d.ts +78 -0
- package/dist/tools/receive_addresses.d.ts.map +1 -0
- package/dist/tools/receive_addresses.js +161 -0
- package/dist/tools/remittance_recipients.d.ts +54 -0
- package/dist/tools/remittance_recipients.d.ts.map +1 -0
- package/dist/tools/remittance_recipients.js +106 -0
- package/dist/tools/remittances.d.ts +115 -0
- package/dist/tools/remittances.d.ts.map +1 -0
- package/dist/tools/remittances.js +237 -0
- package/dist/tools/simulate_order.d.ts.map +1 -1
- package/dist/tools/simulate_order.js +2 -1
- package/dist/tools/withdrawals.d.ts +93 -0
- package/dist/tools/withdrawals.d.ts.map +1 -0
- package/dist/tools/withdrawals.js +215 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +5 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +12 -0
- package/marketplace/README.md +1 -1
- package/marketplace/claude-listing.md +30 -2
- package/marketplace/gemini-tools.json +155 -1
- package/marketplace/openapi.yaml +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/cache.ts +1 -0
- package/src/client.ts +20 -0
- package/src/http.ts +55 -0
- package/src/index.ts +30 -0
- package/src/tools/account.ts +66 -0
- package/src/tools/balance.ts +94 -0
- package/src/tools/banks.ts +94 -0
- package/src/tools/batch_orders.ts +199 -0
- package/src/tools/cancel_all_orders.ts +117 -0
- package/src/tools/cancel_order_by_client_id.ts +132 -0
- package/src/tools/deposits.ts +230 -0
- package/src/tools/fees.ts +91 -0
- package/src/tools/lightning.ts +231 -0
- package/src/tools/order_lookup.ts +139 -0
- package/src/tools/place_order.ts +119 -2
- package/src/tools/quotation.ts +124 -0
- package/src/tools/receive_addresses.ts +216 -0
- package/src/tools/remittance_recipients.ts +139 -0
- package/src/tools/remittances.ts +299 -0
- package/src/tools/simulate_order.ts +1 -0
- package/src/tools/withdrawals.ts +276 -0
- package/src/types.ts +210 -0
- package/src/validation.ts +16 -0
- package/test/run-all.ts +16 -0
- package/test/unit.ts +1905 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { BudaClient, BudaApiError } from "../client.js";
|
|
4
|
+
import { validateCurrency } from "../validation.js";
|
|
5
|
+
import { flattenAmount } from "../utils.js";
|
|
6
|
+
import type { WithdrawalsResponse, SingleWithdrawalResponse, Withdrawal } from "../types.js";
|
|
7
|
+
|
|
8
|
+
export const getWithdrawalHistoryToolSchema = {
|
|
9
|
+
name: "get_withdrawal_history",
|
|
10
|
+
description:
|
|
11
|
+
"Returns withdrawal history for a currency on the authenticated Buda.com account. " +
|
|
12
|
+
"Supports state filtering and pagination. All amounts are floats with separate _currency fields. " +
|
|
13
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
14
|
+
"Example: 'Show my pending CLP withdrawals.'",
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: "object" as const,
|
|
17
|
+
properties: {
|
|
18
|
+
currency: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Currency code (e.g. 'BTC', 'CLP').",
|
|
21
|
+
},
|
|
22
|
+
state: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description:
|
|
25
|
+
"Filter by state: 'pending_signature', 'pending', 'confirmed', 'rejected', 'anulled'.",
|
|
26
|
+
},
|
|
27
|
+
per: {
|
|
28
|
+
type: "number",
|
|
29
|
+
description: "Results per page (default: 20, max: 300).",
|
|
30
|
+
},
|
|
31
|
+
page: {
|
|
32
|
+
type: "number",
|
|
33
|
+
description: "Page number (default: 1).",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ["currency"],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
type GetWithdrawalHistoryArgs = {
|
|
41
|
+
currency: string;
|
|
42
|
+
state?: "pending_signature" | "pending" | "confirmed" | "rejected" | "anulled";
|
|
43
|
+
per?: number;
|
|
44
|
+
page?: number;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
function normalizeWithdrawal(w: Withdrawal) {
|
|
48
|
+
const amount = flattenAmount(w.amount);
|
|
49
|
+
const fee = flattenAmount(w.fee);
|
|
50
|
+
return {
|
|
51
|
+
id: w.id,
|
|
52
|
+
state: w.state,
|
|
53
|
+
currency: w.currency,
|
|
54
|
+
amount: amount.value,
|
|
55
|
+
amount_currency: amount.currency,
|
|
56
|
+
fee: fee.value,
|
|
57
|
+
fee_currency: fee.currency,
|
|
58
|
+
address: w.address,
|
|
59
|
+
tx_hash: w.tx_hash,
|
|
60
|
+
bank_account_id: w.bank_account_id,
|
|
61
|
+
created_at: w.created_at,
|
|
62
|
+
updated_at: w.updated_at,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function handleGetWithdrawalHistory(
|
|
67
|
+
args: GetWithdrawalHistoryArgs,
|
|
68
|
+
client: BudaClient,
|
|
69
|
+
): Promise<{ content: Array<{ type: "text"; text: string }>; isError?: boolean }> {
|
|
70
|
+
const { currency, state, per, page } = args;
|
|
71
|
+
|
|
72
|
+
const validationError = validateCurrency(currency);
|
|
73
|
+
if (validationError) {
|
|
74
|
+
return {
|
|
75
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
76
|
+
isError: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const params: Record<string, string | number> = {};
|
|
82
|
+
if (state) params.state = state;
|
|
83
|
+
if (per !== undefined) params.per = per;
|
|
84
|
+
if (page !== undefined) params.page = page;
|
|
85
|
+
|
|
86
|
+
const data = await client.get<WithdrawalsResponse>(
|
|
87
|
+
`/currencies/${currency.toUpperCase()}/withdrawals`,
|
|
88
|
+
Object.keys(params).length > 0 ? params : undefined,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: "text",
|
|
95
|
+
text: JSON.stringify(
|
|
96
|
+
{
|
|
97
|
+
withdrawals: data.withdrawals.map(normalizeWithdrawal),
|
|
98
|
+
meta: data.meta,
|
|
99
|
+
},
|
|
100
|
+
null,
|
|
101
|
+
2,
|
|
102
|
+
),
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
} catch (err) {
|
|
107
|
+
const msg =
|
|
108
|
+
err instanceof BudaApiError
|
|
109
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
110
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
113
|
+
isError: true,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export const createWithdrawalToolSchema = {
|
|
119
|
+
name: "create_withdrawal",
|
|
120
|
+
description:
|
|
121
|
+
"Create a withdrawal on Buda.com. Supports both crypto (address) and fiat (bank_account_id) withdrawals. " +
|
|
122
|
+
"Exactly one of address or bank_account_id must be provided. " +
|
|
123
|
+
"IMPORTANT: Pass confirmation_token='CONFIRM' to execute. " +
|
|
124
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET.",
|
|
125
|
+
inputSchema: {
|
|
126
|
+
type: "object" as const,
|
|
127
|
+
properties: {
|
|
128
|
+
currency: { type: "string", description: "Currency code (e.g. 'BTC', 'CLP')." },
|
|
129
|
+
amount: { type: "number", description: "Withdrawal amount." },
|
|
130
|
+
address: { type: "string", description: "Destination crypto address. Mutually exclusive with bank_account_id." },
|
|
131
|
+
network: { type: "string", description: "Blockchain network for crypto withdrawals (e.g. 'bitcoin', 'ethereum')." },
|
|
132
|
+
bank_account_id: { type: "number", description: "Fiat bank account ID. Mutually exclusive with address." },
|
|
133
|
+
confirmation_token: {
|
|
134
|
+
type: "string",
|
|
135
|
+
description: "Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to execute.",
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
required: ["currency", "amount", "confirmation_token"],
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
type CreateWithdrawalArgs = {
|
|
143
|
+
currency: string;
|
|
144
|
+
amount: number;
|
|
145
|
+
address?: string;
|
|
146
|
+
network?: string;
|
|
147
|
+
bank_account_id?: number;
|
|
148
|
+
confirmation_token: string;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export async function handleCreateWithdrawal(
|
|
152
|
+
args: CreateWithdrawalArgs,
|
|
153
|
+
client: BudaClient,
|
|
154
|
+
): Promise<{ content: Array<{ type: "text"; text: string }>; isError?: boolean }> {
|
|
155
|
+
const { currency, amount, address, network, bank_account_id, confirmation_token } = args;
|
|
156
|
+
|
|
157
|
+
if (confirmation_token !== "CONFIRM") {
|
|
158
|
+
return {
|
|
159
|
+
content: [
|
|
160
|
+
{
|
|
161
|
+
type: "text",
|
|
162
|
+
text: JSON.stringify({
|
|
163
|
+
error:
|
|
164
|
+
"Withdrawal not created. confirmation_token must equal 'CONFIRM' to execute. " +
|
|
165
|
+
"Review the details and set confirmation_token='CONFIRM' to proceed.",
|
|
166
|
+
code: "CONFIRMATION_REQUIRED",
|
|
167
|
+
preview: { currency, amount, destination: address ?? bank_account_id },
|
|
168
|
+
}),
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
isError: true,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const hasAddress = address !== undefined;
|
|
176
|
+
const hasBankAccount = bank_account_id !== undefined;
|
|
177
|
+
|
|
178
|
+
if (hasAddress && hasBankAccount) {
|
|
179
|
+
return {
|
|
180
|
+
content: [
|
|
181
|
+
{
|
|
182
|
+
type: "text",
|
|
183
|
+
text: JSON.stringify({
|
|
184
|
+
error: "Provide either address (crypto) or bank_account_id (fiat), not both.",
|
|
185
|
+
code: "VALIDATION_ERROR",
|
|
186
|
+
}),
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
isError: true,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!hasAddress && !hasBankAccount) {
|
|
194
|
+
return {
|
|
195
|
+
content: [
|
|
196
|
+
{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: JSON.stringify({
|
|
199
|
+
error: "Either address (crypto) or bank_account_id (fiat) must be provided.",
|
|
200
|
+
code: "VALIDATION_ERROR",
|
|
201
|
+
}),
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
isError: true,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const validationError = validateCurrency(currency);
|
|
209
|
+
if (validationError) {
|
|
210
|
+
return {
|
|
211
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
212
|
+
isError: true,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
const payload: Record<string, unknown> = { amount: String(amount) };
|
|
218
|
+
if (hasAddress) {
|
|
219
|
+
payload.address = address;
|
|
220
|
+
if (network) payload.network = network;
|
|
221
|
+
} else {
|
|
222
|
+
payload.bank_account_id = bank_account_id;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const data = await client.post<SingleWithdrawalResponse>(
|
|
226
|
+
`/currencies/${currency.toUpperCase()}/withdrawals`,
|
|
227
|
+
payload,
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
content: [{ type: "text", text: JSON.stringify(normalizeWithdrawal(data.withdrawal), null, 2) }],
|
|
232
|
+
};
|
|
233
|
+
} catch (err) {
|
|
234
|
+
const msg =
|
|
235
|
+
err instanceof BudaApiError
|
|
236
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
237
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
238
|
+
return {
|
|
239
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
240
|
+
isError: true,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function register(server: McpServer, client: BudaClient): void {
|
|
246
|
+
server.tool(
|
|
247
|
+
getWithdrawalHistoryToolSchema.name,
|
|
248
|
+
getWithdrawalHistoryToolSchema.description,
|
|
249
|
+
{
|
|
250
|
+
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'CLP')."),
|
|
251
|
+
state: z
|
|
252
|
+
.enum(["pending_signature", "pending", "confirmed", "rejected", "anulled"])
|
|
253
|
+
.optional()
|
|
254
|
+
.describe("Filter by state."),
|
|
255
|
+
per: z.number().int().min(1).max(300).optional().describe("Results per page (default: 20, max: 300)."),
|
|
256
|
+
page: z.number().int().min(1).optional().describe("Page number (default: 1)."),
|
|
257
|
+
},
|
|
258
|
+
(args) => handleGetWithdrawalHistory(args, client),
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
server.tool(
|
|
262
|
+
createWithdrawalToolSchema.name,
|
|
263
|
+
createWithdrawalToolSchema.description,
|
|
264
|
+
{
|
|
265
|
+
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'CLP')."),
|
|
266
|
+
amount: z.number().positive().describe("Withdrawal amount."),
|
|
267
|
+
address: z.string().optional().describe("Destination crypto address. Mutually exclusive with bank_account_id."),
|
|
268
|
+
network: z.string().optional().describe("Blockchain network for crypto withdrawals (e.g. 'bitcoin', 'ethereum')."),
|
|
269
|
+
bank_account_id: z.number().int().positive().optional().describe("Fiat bank account ID. Mutually exclusive with address."),
|
|
270
|
+
confirmation_token: z
|
|
271
|
+
.string()
|
|
272
|
+
.describe("Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to execute."),
|
|
273
|
+
},
|
|
274
|
+
(args) => handleCreateWithdrawal(args, client),
|
|
275
|
+
);
|
|
276
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -145,3 +145,213 @@ export interface OhlcvCandle {
|
|
|
145
145
|
volume: number;
|
|
146
146
|
trade_count: number;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
// ----- Pagination -----
|
|
150
|
+
|
|
151
|
+
export interface PaginationMeta {
|
|
152
|
+
current_page: number;
|
|
153
|
+
total_count: number;
|
|
154
|
+
total_pages: number;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ----- Account (private) -----
|
|
158
|
+
|
|
159
|
+
export interface MeResponse {
|
|
160
|
+
me: {
|
|
161
|
+
id: number;
|
|
162
|
+
email: string;
|
|
163
|
+
name: string | null;
|
|
164
|
+
monthly_transacted: Amount;
|
|
165
|
+
pubsub_key: string | null;
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ----- Single Balance (private) -----
|
|
170
|
+
|
|
171
|
+
export interface SingleBalanceResponse {
|
|
172
|
+
balance: Balance;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ----- Network Fees (private) -----
|
|
176
|
+
|
|
177
|
+
export interface Fee {
|
|
178
|
+
name: string;
|
|
179
|
+
fee_type: string;
|
|
180
|
+
base_fee: Amount;
|
|
181
|
+
percent: string | null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface FeesResponse {
|
|
185
|
+
fees: Fee[];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ----- Deposits (private) -----
|
|
189
|
+
|
|
190
|
+
export interface Deposit {
|
|
191
|
+
id: number;
|
|
192
|
+
state: string;
|
|
193
|
+
currency: string;
|
|
194
|
+
amount: Amount;
|
|
195
|
+
fee: Amount;
|
|
196
|
+
created_at: string;
|
|
197
|
+
updated_at: string;
|
|
198
|
+
transfer_account_id: number | null;
|
|
199
|
+
transaction_hash: string | null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface DepositsResponse {
|
|
203
|
+
deposits: Deposit[];
|
|
204
|
+
meta: PaginationMeta;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface SingleDepositResponse {
|
|
208
|
+
deposit: Deposit;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ----- Withdrawals (private) -----
|
|
212
|
+
|
|
213
|
+
export interface Withdrawal {
|
|
214
|
+
id: number;
|
|
215
|
+
state: string;
|
|
216
|
+
currency: string;
|
|
217
|
+
amount: Amount;
|
|
218
|
+
fee: Amount;
|
|
219
|
+
address: string | null;
|
|
220
|
+
tx_hash: string | null;
|
|
221
|
+
bank_account_id: number | null;
|
|
222
|
+
created_at: string;
|
|
223
|
+
updated_at: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface WithdrawalsResponse {
|
|
227
|
+
withdrawals: Withdrawal[];
|
|
228
|
+
meta: PaginationMeta;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface SingleWithdrawalResponse {
|
|
232
|
+
withdrawal: Withdrawal;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ----- Receive Addresses (private) -----
|
|
236
|
+
|
|
237
|
+
export interface ReceiveAddress {
|
|
238
|
+
id: number;
|
|
239
|
+
address: string;
|
|
240
|
+
currency: string;
|
|
241
|
+
created_at: string;
|
|
242
|
+
label: string | null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface ReceiveAddressesResponse {
|
|
246
|
+
receive_addresses: ReceiveAddress[];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface SingleReceiveAddressResponse {
|
|
250
|
+
receive_address: ReceiveAddress;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ----- Remittances (private) -----
|
|
254
|
+
|
|
255
|
+
export interface Remittance {
|
|
256
|
+
id: number;
|
|
257
|
+
state: string;
|
|
258
|
+
currency: string;
|
|
259
|
+
amount: Amount;
|
|
260
|
+
recipient_id: number | null;
|
|
261
|
+
created_at: string;
|
|
262
|
+
expires_at: string | null;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface RemittancesResponse {
|
|
266
|
+
remittances: Remittance[];
|
|
267
|
+
meta: PaginationMeta;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface SingleRemittanceResponse {
|
|
271
|
+
remittance: Remittance;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ----- Remittance Recipients (private) -----
|
|
275
|
+
|
|
276
|
+
export interface RemittanceRecipient {
|
|
277
|
+
id: number;
|
|
278
|
+
name: string;
|
|
279
|
+
bank: string;
|
|
280
|
+
account_number: string;
|
|
281
|
+
currency: string;
|
|
282
|
+
country: string | null;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface RemittanceRecipientsResponse {
|
|
286
|
+
remittance_recipients: RemittanceRecipient[];
|
|
287
|
+
meta: PaginationMeta;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export interface SingleRemittanceRecipientResponse {
|
|
291
|
+
remittance_recipient: RemittanceRecipient;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ----- Quotations (public) -----
|
|
295
|
+
|
|
296
|
+
export interface Quotation {
|
|
297
|
+
id: number | null;
|
|
298
|
+
type: string;
|
|
299
|
+
market_id: string;
|
|
300
|
+
amount: Amount;
|
|
301
|
+
limit: Amount | null;
|
|
302
|
+
base_balance_change: Amount;
|
|
303
|
+
quote_balance_change: Amount;
|
|
304
|
+
fee_amount: Amount;
|
|
305
|
+
order_amount: Amount;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export interface QuotationResponse {
|
|
309
|
+
quotation: Quotation;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ----- Banks (public) -----
|
|
313
|
+
|
|
314
|
+
export interface Bank {
|
|
315
|
+
id: string;
|
|
316
|
+
name: string;
|
|
317
|
+
country: string | null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export interface BanksResponse {
|
|
321
|
+
banks: Bank[];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ----- Cancel All Orders (private) -----
|
|
325
|
+
|
|
326
|
+
export interface CancelAllOrdersResponse {
|
|
327
|
+
canceled_count: number;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// ----- Lightning (private) -----
|
|
331
|
+
|
|
332
|
+
export interface LightningWithdrawal {
|
|
333
|
+
id: number;
|
|
334
|
+
state: string;
|
|
335
|
+
amount: Amount;
|
|
336
|
+
fee: Amount;
|
|
337
|
+
payment_hash: string;
|
|
338
|
+
created_at: string;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export interface LightningWithdrawalResponse {
|
|
342
|
+
lightning_withdrawal: LightningWithdrawal;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export interface LightningInvoice {
|
|
346
|
+
id: number;
|
|
347
|
+
payment_request: string;
|
|
348
|
+
amount: Amount;
|
|
349
|
+
description: string | null;
|
|
350
|
+
expires_at: string;
|
|
351
|
+
state: string;
|
|
352
|
+
created_at: string;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export interface LightningInvoiceResponse {
|
|
356
|
+
lightning_network_invoice: LightningInvoice;
|
|
357
|
+
}
|
package/src/validation.ts
CHANGED
|
@@ -14,3 +14,19 @@ export function validateMarketId(id: string): string | null {
|
|
|
14
14
|
}
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
const CURRENCY_RE = /^[A-Z0-9]{2,10}$/i;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Validates a currency code (e.g. "BTC", "CLP", "USDC").
|
|
22
|
+
* Returns an error message string if invalid, or null if valid.
|
|
23
|
+
*/
|
|
24
|
+
export function validateCurrency(id: string): string | null {
|
|
25
|
+
if (!CURRENCY_RE.test(id)) {
|
|
26
|
+
return (
|
|
27
|
+
`Invalid currency "${id}". ` +
|
|
28
|
+
`Expected 2–10 alphanumeric characters (e.g. "BTC", "CLP", "USDC").`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
package/test/run-all.ts
CHANGED
|
@@ -3,9 +3,25 @@
|
|
|
3
3
|
* and prints a summary of the results.
|
|
4
4
|
*
|
|
5
5
|
* Run with: npm run test:integration
|
|
6
|
+
* Auth tools (balances, orders, DMS) are tested automatically if a .env file with
|
|
7
|
+
* BUDA_API_KEY and BUDA_API_SECRET exists in the project root (already in .gitignore).
|
|
6
8
|
* Skipped automatically when the Buda API is unreachable (CI without network).
|
|
7
9
|
*/
|
|
8
10
|
|
|
11
|
+
// Load .env if present (never committed — see .gitignore)
|
|
12
|
+
import { existsSync, readFileSync } from "fs";
|
|
13
|
+
if (existsSync(".env")) {
|
|
14
|
+
for (const line of readFileSync(".env", "utf8").split("\n")) {
|
|
15
|
+
const trimmed = line.trim();
|
|
16
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
17
|
+
const eqIdx = trimmed.indexOf("=");
|
|
18
|
+
if (eqIdx === -1) continue;
|
|
19
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
20
|
+
const val = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
|
|
21
|
+
if (key && !(key in process.env)) process.env[key] = val;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
9
25
|
// Connectivity pre-check — skip gracefully instead of failing CI when the API is unreachable.
|
|
10
26
|
try {
|
|
11
27
|
await fetch("https://www.buda.com/api/v2/markets.json", {
|