@guiie/buda-mcp 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/marketplace-docs-sync.mdc +32 -0
- package/CHANGELOG.md +75 -0
- package/PUBLISH_CHECKLIST.md +48 -89
- package/README.md +446 -78
- package/dist/audit.d.ts +21 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +14 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -1
- package/dist/http.js +65 -7
- package/dist/index.js +12 -3
- package/dist/tools/account.js +1 -1
- package/dist/tools/arbitrage.js +1 -1
- package/dist/tools/balance.js +1 -1
- package/dist/tools/balances.js +1 -1
- package/dist/tools/banks.js +1 -1
- package/dist/tools/batch_orders.d.ts +6 -1
- package/dist/tools/batch_orders.d.ts.map +1 -1
- package/dist/tools/batch_orders.js +47 -3
- package/dist/tools/cancel_all_orders.d.ts +1 -1
- package/dist/tools/cancel_all_orders.d.ts.map +1 -1
- package/dist/tools/cancel_all_orders.js +10 -13
- package/dist/tools/cancel_order.d.ts +1 -1
- package/dist/tools/cancel_order.d.ts.map +1 -1
- package/dist/tools/cancel_order.js +10 -10
- package/dist/tools/cancel_order_by_client_id.d.ts +1 -1
- package/dist/tools/cancel_order_by_client_id.d.ts.map +1 -1
- package/dist/tools/cancel_order_by_client_id.js +9 -9
- package/dist/tools/compare_markets.d.ts +9 -0
- package/dist/tools/compare_markets.d.ts.map +1 -1
- package/dist/tools/compare_markets.js +63 -53
- package/dist/tools/dead_mans_switch.d.ts +2 -2
- package/dist/tools/dead_mans_switch.d.ts.map +1 -1
- package/dist/tools/dead_mans_switch.js +68 -6
- package/dist/tools/deposits.js +2 -2
- package/dist/tools/fees.js +1 -1
- package/dist/tools/lightning.d.ts +1 -1
- package/dist/tools/lightning.d.ts.map +1 -1
- package/dist/tools/lightning.js +25 -9
- package/dist/tools/market_sentiment.js +1 -1
- package/dist/tools/market_summary.js +1 -1
- package/dist/tools/markets.js +1 -1
- package/dist/tools/order_lookup.js +2 -2
- package/dist/tools/orderbook.js +1 -1
- package/dist/tools/orders.js +1 -1
- package/dist/tools/place_order.d.ts +1 -1
- package/dist/tools/place_order.d.ts.map +1 -1
- package/dist/tools/place_order.js +53 -4
- package/dist/tools/price_history.js +1 -1
- package/dist/tools/quotation.js +1 -1
- package/dist/tools/receive_addresses.d.ts +6 -1
- package/dist/tools/receive_addresses.d.ts.map +1 -1
- package/dist/tools/receive_addresses.js +37 -13
- package/dist/tools/remittance_recipients.js +2 -2
- package/dist/tools/remittances.d.ts +7 -2
- package/dist/tools/remittances.d.ts.map +1 -1
- package/dist/tools/remittances.js +46 -23
- package/dist/tools/simulate_order.js +1 -1
- package/dist/tools/spread.js +1 -1
- package/dist/tools/technical_indicators.d.ts.map +1 -1
- package/dist/tools/technical_indicators.js +3 -2
- package/dist/tools/ticker.js +1 -1
- package/dist/tools/trades.js +1 -1
- package/dist/tools/volume.js +1 -1
- package/dist/tools/withdrawals.d.ts +1 -1
- package/dist/tools/withdrawals.d.ts.map +1 -1
- package/dist/tools/withdrawals.js +21 -11
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +29 -1
- package/dist/validation.d.ts +6 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +26 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +8 -1
- package/marketplace/README.md +1 -1
- package/marketplace/claude-listing.md +75 -4
- package/marketplace/gemini-tools.json +325 -2
- package/marketplace/openapi.yaml +160 -1
- package/package.json +2 -1
- package/server.json +2 -2
- package/src/audit.ts +24 -0
- package/src/client.ts +3 -1
- package/src/http.ts +75 -7
- package/src/index.ts +10 -3
- package/src/tools/account.ts +1 -1
- package/src/tools/arbitrage.ts +1 -1
- package/src/tools/balance.ts +1 -1
- package/src/tools/balances.ts +1 -1
- package/src/tools/banks.ts +1 -1
- package/src/tools/batch_orders.ts +52 -2
- package/src/tools/cancel_all_orders.ts +10 -12
- package/src/tools/cancel_order.ts +10 -9
- package/src/tools/cancel_order_by_client_id.ts +9 -8
- package/src/tools/compare_markets.ts +78 -61
- package/src/tools/dead_mans_switch.ts +76 -5
- package/src/tools/deposits.ts +2 -2
- package/src/tools/fees.ts +1 -1
- package/src/tools/lightning.ts +28 -9
- package/src/tools/market_sentiment.ts +1 -1
- package/src/tools/market_summary.ts +1 -1
- package/src/tools/markets.ts +1 -1
- package/src/tools/order_lookup.ts +2 -2
- package/src/tools/orderbook.ts +1 -1
- package/src/tools/orders.ts +1 -1
- package/src/tools/place_order.ts +56 -5
- package/src/tools/price_history.ts +1 -1
- package/src/tools/quotation.ts +1 -1
- package/src/tools/receive_addresses.ts +40 -13
- package/src/tools/remittance_recipients.ts +2 -2
- package/src/tools/remittances.ts +49 -22
- package/src/tools/simulate_order.ts +1 -1
- package/src/tools/spread.ts +1 -1
- package/src/tools/technical_indicators.ts +3 -2
- package/src/tools/ticker.ts +1 -1
- package/src/tools/trades.ts +1 -1
- package/src/tools/volume.ts +1 -1
- package/src/tools/withdrawals.ts +22 -10
- package/src/utils.ts +36 -1
- package/src/validation.ts +29 -0
- package/src/version.ts +11 -3
- package/test/unit.ts +623 -22
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { BudaApiError } from "../client.js";
|
|
3
3
|
import { validateCurrency } from "../validation.js";
|
|
4
|
+
import { logAudit } from "../audit.js";
|
|
4
5
|
export const createReceiveAddressToolSchema = {
|
|
5
6
|
name: "create_receive_address",
|
|
6
7
|
description: "Generates a new receive address for a crypto currency. " +
|
|
7
8
|
"Creates a new blockchain deposit address for the given currency. " +
|
|
8
9
|
"Each call generates a distinct address. Not idempotent. " +
|
|
10
|
+
"IMPORTANT: Pass confirmation_token='CONFIRM' to execute. " +
|
|
9
11
|
"Only applicable to crypto currencies (BTC, ETH, etc.). " +
|
|
10
12
|
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
11
13
|
"Example: 'Give me a fresh Bitcoin deposit address.'",
|
|
@@ -16,8 +18,12 @@ export const createReceiveAddressToolSchema = {
|
|
|
16
18
|
type: "string",
|
|
17
19
|
description: "Currency code (e.g. 'BTC', 'ETH').",
|
|
18
20
|
},
|
|
21
|
+
confirmation_token: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to generate a new address.",
|
|
24
|
+
},
|
|
19
25
|
},
|
|
20
|
-
required: ["currency"],
|
|
26
|
+
required: ["currency", "confirmation_token"],
|
|
21
27
|
},
|
|
22
28
|
};
|
|
23
29
|
export const listReceiveAddressesToolSchema = {
|
|
@@ -88,7 +94,7 @@ export async function handleListReceiveAddresses(args, client) {
|
|
|
88
94
|
}
|
|
89
95
|
catch (err) {
|
|
90
96
|
const msg = err instanceof BudaApiError
|
|
91
|
-
? { error: err.message, code: err.status
|
|
97
|
+
? { error: err.message, code: err.status }
|
|
92
98
|
: { error: String(err), code: "UNKNOWN" };
|
|
93
99
|
return {
|
|
94
100
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -113,7 +119,7 @@ export async function handleGetReceiveAddress(args, client) {
|
|
|
113
119
|
}
|
|
114
120
|
catch (err) {
|
|
115
121
|
const msg = err instanceof BudaApiError
|
|
116
|
-
? { error: err.message, code: err.status
|
|
122
|
+
? { error: err.message, code: err.status }
|
|
117
123
|
: { error: String(err), code: "UNKNOWN" };
|
|
118
124
|
return {
|
|
119
125
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -121,8 +127,24 @@ export async function handleGetReceiveAddress(args, client) {
|
|
|
121
127
|
};
|
|
122
128
|
}
|
|
123
129
|
}
|
|
124
|
-
export async function handleCreateReceiveAddress(args, client) {
|
|
125
|
-
const { currency } = args;
|
|
130
|
+
export async function handleCreateReceiveAddress(args, client, transport = "stdio") {
|
|
131
|
+
const { currency, confirmation_token } = args;
|
|
132
|
+
if (confirmation_token !== "CONFIRM") {
|
|
133
|
+
return {
|
|
134
|
+
content: [
|
|
135
|
+
{
|
|
136
|
+
type: "text",
|
|
137
|
+
text: JSON.stringify({
|
|
138
|
+
error: "Address not generated. confirmation_token must equal 'CONFIRM' to execute. " +
|
|
139
|
+
"Each call creates a distinct address — review and set confirmation_token='CONFIRM' to proceed.",
|
|
140
|
+
code: "CONFIRMATION_REQUIRED",
|
|
141
|
+
preview: { currency },
|
|
142
|
+
}),
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
isError: true,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
126
148
|
const validationError = validateCurrency(currency);
|
|
127
149
|
if (validationError) {
|
|
128
150
|
return {
|
|
@@ -132,18 +154,17 @@ export async function handleCreateReceiveAddress(args, client) {
|
|
|
132
154
|
}
|
|
133
155
|
try {
|
|
134
156
|
const data = await client.post(`/currencies/${currency.toUpperCase()}/receive_addresses`, {});
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
157
|
+
const result = { content: [{ type: "text", text: JSON.stringify(normalizeAddress(data.receive_address), null, 2) }] };
|
|
158
|
+
logAudit({ ts: new Date().toISOString(), tool: "create_receive_address", transport, args_summary: { currency }, success: true });
|
|
159
|
+
return result;
|
|
138
160
|
}
|
|
139
161
|
catch (err) {
|
|
140
162
|
const msg = err instanceof BudaApiError
|
|
141
|
-
? { error: err.message, code: err.status
|
|
163
|
+
? { error: err.message, code: err.status }
|
|
142
164
|
: { error: String(err), code: "UNKNOWN" };
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
};
|
|
165
|
+
const result = { content: [{ type: "text", text: JSON.stringify(msg) }], isError: true };
|
|
166
|
+
logAudit({ ts: new Date().toISOString(), tool: "create_receive_address", transport, args_summary: { currency }, success: false, error_code: msg.code });
|
|
167
|
+
return result;
|
|
147
168
|
}
|
|
148
169
|
}
|
|
149
170
|
export function register(server, client) {
|
|
@@ -156,6 +177,9 @@ export function register(server, client) {
|
|
|
156
177
|
}, (args) => handleGetReceiveAddress(args, client));
|
|
157
178
|
server.tool(createReceiveAddressToolSchema.name, createReceiveAddressToolSchema.description, {
|
|
158
179
|
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'ETH')."),
|
|
180
|
+
confirmation_token: z
|
|
181
|
+
.string()
|
|
182
|
+
.describe("Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to generate a new address."),
|
|
159
183
|
}, (args) => handleCreateReceiveAddress(args, client));
|
|
160
184
|
}
|
|
161
185
|
//# sourceMappingURL=receive_addresses.js.map
|
|
@@ -69,7 +69,7 @@ export async function handleListRemittanceRecipients(args, client) {
|
|
|
69
69
|
}
|
|
70
70
|
catch (err) {
|
|
71
71
|
const msg = err instanceof BudaApiError
|
|
72
|
-
? { error: err.message, code: err.status
|
|
72
|
+
? { error: err.message, code: err.status }
|
|
73
73
|
: { error: String(err), code: "UNKNOWN" };
|
|
74
74
|
return {
|
|
75
75
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -86,7 +86,7 @@ export async function handleGetRemittanceRecipient(args, client) {
|
|
|
86
86
|
}
|
|
87
87
|
catch (err) {
|
|
88
88
|
const msg = err instanceof BudaApiError
|
|
89
|
-
? { error: err.message, code: err.status
|
|
89
|
+
? { error: err.message, code: err.status }
|
|
90
90
|
: { error: String(err), code: "UNKNOWN" };
|
|
91
91
|
return {
|
|
92
92
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -35,6 +35,10 @@ export declare const quoteRemittanceToolSchema: {
|
|
|
35
35
|
type: string;
|
|
36
36
|
description: string;
|
|
37
37
|
};
|
|
38
|
+
confirmation_token: {
|
|
39
|
+
type: string;
|
|
40
|
+
description: string;
|
|
41
|
+
};
|
|
38
42
|
};
|
|
39
43
|
required: string[];
|
|
40
44
|
};
|
|
@@ -94,7 +98,8 @@ export declare function handleQuoteRemittance(args: {
|
|
|
94
98
|
currency: string;
|
|
95
99
|
amount: number;
|
|
96
100
|
recipient_id: number;
|
|
97
|
-
|
|
101
|
+
confirmation_token: string;
|
|
102
|
+
}, client: BudaClient, transport?: "http" | "stdio"): Promise<{
|
|
98
103
|
content: Array<{
|
|
99
104
|
type: "text";
|
|
100
105
|
text: string;
|
|
@@ -104,7 +109,7 @@ export declare function handleQuoteRemittance(args: {
|
|
|
104
109
|
export declare function handleAcceptRemittanceQuote(args: {
|
|
105
110
|
id: number;
|
|
106
111
|
confirmation_token: string;
|
|
107
|
-
}, client: BudaClient): Promise<{
|
|
112
|
+
}, client: BudaClient, transport?: "http" | "stdio"): Promise<{
|
|
108
113
|
content: Array<{
|
|
109
114
|
type: "text";
|
|
110
115
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remittances.d.ts","sourceRoot":"","sources":["../../src/tools/remittances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"remittances.d.ts","sourceRoot":"","sources":["../../src/tools/remittances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAMxD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;CAoBrC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;CAiCrC,CAAC;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;CAuB3C,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;CAiBnC,CAAC;AAgBF,wBAAsB,qBAAqB,CACzC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACrC,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAoChF;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAgBhF;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,EAC5F,MAAM,EAAE,UAAU,EAClB,SAAS,GAAE,MAAM,GAAG,OAAiB,GACpC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAiDhF;AAED,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,EAChD,MAAM,EAAE,UAAU,EAClB,SAAS,GAAE,MAAM,GAAG,OAAiB,GACpC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAoChF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CA2CpE"}
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { BudaApiError } from "../client.js";
|
|
3
3
|
import { flattenAmount } from "../utils.js";
|
|
4
4
|
import { validateCurrency } from "../validation.js";
|
|
5
|
+
import { logAudit } from "../audit.js";
|
|
5
6
|
export const listRemittancesToolSchema = {
|
|
6
7
|
name: "list_remittances",
|
|
7
8
|
description: "Returns all fiat remittance transfers for the authenticated Buda.com account. " +
|
|
@@ -28,7 +29,8 @@ export const quoteRemittanceToolSchema = {
|
|
|
28
29
|
"Requests a price quote for a fiat remittance to a saved recipient. " +
|
|
29
30
|
"Returns a remittance object in 'quoted' state with an expiry timestamp. " +
|
|
30
31
|
"NOT idempotent — creates a new remittance record each call. " +
|
|
31
|
-
"
|
|
32
|
+
"IMPORTANT: Pass confirmation_token='CONFIRM' to execute. " +
|
|
33
|
+
"To execute the transfer, call accept_remittance_quote with the returned ID before it expires. " +
|
|
32
34
|
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
33
35
|
"Example: 'Get a remittance quote to send 100000 CLP to recipient 5.'",
|
|
34
36
|
inputSchema: {
|
|
@@ -46,8 +48,12 @@ export const quoteRemittanceToolSchema = {
|
|
|
46
48
|
type: "number",
|
|
47
49
|
description: "ID of the saved remittance recipient.",
|
|
48
50
|
},
|
|
51
|
+
confirmation_token: {
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to create the quote.",
|
|
54
|
+
},
|
|
49
55
|
},
|
|
50
|
-
required: ["currency", "amount", "recipient_id"],
|
|
56
|
+
required: ["currency", "amount", "recipient_id", "confirmation_token"],
|
|
51
57
|
},
|
|
52
58
|
};
|
|
53
59
|
export const acceptRemittanceQuoteToolSchema = {
|
|
@@ -125,7 +131,7 @@ export async function handleListRemittances(args, client) {
|
|
|
125
131
|
}
|
|
126
132
|
catch (err) {
|
|
127
133
|
const msg = err instanceof BudaApiError
|
|
128
|
-
? { error: err.message, code: err.status
|
|
134
|
+
? { error: err.message, code: err.status }
|
|
129
135
|
: { error: String(err), code: "UNKNOWN" };
|
|
130
136
|
return {
|
|
131
137
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -142,7 +148,7 @@ export async function handleGetRemittance(args, client) {
|
|
|
142
148
|
}
|
|
143
149
|
catch (err) {
|
|
144
150
|
const msg = err instanceof BudaApiError
|
|
145
|
-
? { error: err.message, code: err.status
|
|
151
|
+
? { error: err.message, code: err.status }
|
|
146
152
|
: { error: String(err), code: "UNKNOWN" };
|
|
147
153
|
return {
|
|
148
154
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -150,8 +156,24 @@ export async function handleGetRemittance(args, client) {
|
|
|
150
156
|
};
|
|
151
157
|
}
|
|
152
158
|
}
|
|
153
|
-
export async function handleQuoteRemittance(args, client) {
|
|
154
|
-
const { currency, amount, recipient_id } = args;
|
|
159
|
+
export async function handleQuoteRemittance(args, client, transport = "stdio") {
|
|
160
|
+
const { currency, amount, recipient_id, confirmation_token } = args;
|
|
161
|
+
if (confirmation_token !== "CONFIRM") {
|
|
162
|
+
return {
|
|
163
|
+
content: [
|
|
164
|
+
{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: JSON.stringify({
|
|
167
|
+
error: "Remittance quote not created. confirmation_token must equal 'CONFIRM' to execute. " +
|
|
168
|
+
"Review the details and set confirmation_token='CONFIRM' to proceed.",
|
|
169
|
+
code: "CONFIRMATION_REQUIRED",
|
|
170
|
+
preview: { currency, amount, recipient_id },
|
|
171
|
+
}),
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
isError: true,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
155
177
|
const validationError = validateCurrency(currency);
|
|
156
178
|
if (validationError) {
|
|
157
179
|
return {
|
|
@@ -167,21 +189,20 @@ export async function handleQuoteRemittance(args, client) {
|
|
|
167
189
|
recipient_id,
|
|
168
190
|
},
|
|
169
191
|
});
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
192
|
+
const result = { content: [{ type: "text", text: JSON.stringify(normalizeRemittance(data.remittance), null, 2) }] };
|
|
193
|
+
logAudit({ ts: new Date().toISOString(), tool: "quote_remittance", transport, args_summary: { currency, amount, recipient_id }, success: true });
|
|
194
|
+
return result;
|
|
173
195
|
}
|
|
174
196
|
catch (err) {
|
|
175
197
|
const msg = err instanceof BudaApiError
|
|
176
|
-
? { error: err.message, code: err.status
|
|
198
|
+
? { error: err.message, code: err.status }
|
|
177
199
|
: { error: String(err), code: "UNKNOWN" };
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
};
|
|
200
|
+
const result = { content: [{ type: "text", text: JSON.stringify(msg) }], isError: true };
|
|
201
|
+
logAudit({ ts: new Date().toISOString(), tool: "quote_remittance", transport, args_summary: { currency, amount, recipient_id }, success: false, error_code: msg.code });
|
|
202
|
+
return result;
|
|
182
203
|
}
|
|
183
204
|
}
|
|
184
|
-
export async function handleAcceptRemittanceQuote(args, client) {
|
|
205
|
+
export async function handleAcceptRemittanceQuote(args, client, transport = "stdio") {
|
|
185
206
|
const { id, confirmation_token } = args;
|
|
186
207
|
if (confirmation_token !== "CONFIRM") {
|
|
187
208
|
return {
|
|
@@ -202,18 +223,17 @@ export async function handleAcceptRemittanceQuote(args, client) {
|
|
|
202
223
|
const data = await client.put(`/remittances/${id}`, {
|
|
203
224
|
remittance: { state: "confirming" },
|
|
204
225
|
});
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
226
|
+
const result = { content: [{ type: "text", text: JSON.stringify(normalizeRemittance(data.remittance), null, 2) }] };
|
|
227
|
+
logAudit({ ts: new Date().toISOString(), tool: "accept_remittance_quote", transport, args_summary: { remittance_id: id }, success: true });
|
|
228
|
+
return result;
|
|
208
229
|
}
|
|
209
230
|
catch (err) {
|
|
210
231
|
const msg = err instanceof BudaApiError
|
|
211
|
-
? { error: err.message, code: err.status
|
|
232
|
+
? { error: err.message, code: err.status }
|
|
212
233
|
: { error: String(err), code: "UNKNOWN" };
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
};
|
|
234
|
+
const result = { content: [{ type: "text", text: JSON.stringify(msg) }], isError: true };
|
|
235
|
+
logAudit({ ts: new Date().toISOString(), tool: "accept_remittance_quote", transport, args_summary: { remittance_id: id }, success: false, error_code: msg.code });
|
|
236
|
+
return result;
|
|
217
237
|
}
|
|
218
238
|
}
|
|
219
239
|
export function register(server, client) {
|
|
@@ -228,6 +248,9 @@ export function register(server, client) {
|
|
|
228
248
|
currency: z.string().min(2).max(10).describe("Fiat currency code (e.g. 'CLP', 'COP')."),
|
|
229
249
|
amount: z.number().positive().describe("Amount to remit (positive number)."),
|
|
230
250
|
recipient_id: z.number().int().positive().describe("ID of the saved remittance recipient."),
|
|
251
|
+
confirmation_token: z
|
|
252
|
+
.string()
|
|
253
|
+
.describe("Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to create the quote."),
|
|
231
254
|
}, (args) => handleQuoteRemittance(args, client));
|
|
232
255
|
server.tool(acceptRemittanceQuoteToolSchema.name, acceptRemittanceQuoteToolSchema.description, {
|
|
233
256
|
id: z.number().int().positive().describe("The numeric ID of the remittance quote to accept."),
|
|
@@ -110,7 +110,7 @@ export async function handleSimulateOrder(args, client, cache) {
|
|
|
110
110
|
}
|
|
111
111
|
catch (err) {
|
|
112
112
|
const msg = err instanceof BudaApiError
|
|
113
|
-
? { error: err.message, code: err.status
|
|
113
|
+
? { error: err.message, code: err.status }
|
|
114
114
|
: { error: String(err), code: "UNKNOWN" };
|
|
115
115
|
return {
|
|
116
116
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
package/dist/tools/spread.js
CHANGED
|
@@ -67,7 +67,7 @@ export function register(server, client, cache) {
|
|
|
67
67
|
}
|
|
68
68
|
catch (err) {
|
|
69
69
|
const msg = err instanceof BudaApiError
|
|
70
|
-
? { error: err.message, code: err.status
|
|
70
|
+
? { error: err.message, code: err.status }
|
|
71
71
|
: { error: String(err), code: "UNKNOWN" };
|
|
72
72
|
return {
|
|
73
73
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"technical_indicators.d.ts","sourceRoot":"","sources":["../../src/tools/technical_indicators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;CA8BtB,CAAC;AAsGF,KAAK,uBAAuB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,uBAAuB,EAC7B,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"technical_indicators.d.ts","sourceRoot":"","sources":["../../src/tools/technical_indicators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;CA8BtB,CAAC;AAsGF,KAAK,uBAAuB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,uBAAuB,EAC7B,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CA4GhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAyBpE"}
|
|
@@ -146,7 +146,7 @@ export async function handleTechnicalIndicators(args, client) {
|
|
|
146
146
|
const macdResult = macd(closes, 12, 26, 9);
|
|
147
147
|
const bbResult = bollingerBands(closes, 20, 2);
|
|
148
148
|
const sma20 = parseFloat(sma(closes, 20).toFixed(2));
|
|
149
|
-
const sma50 = parseFloat(sma(closes, 50).toFixed(2));
|
|
149
|
+
const sma50 = closes.length >= 50 ? parseFloat(sma(closes, 50).toFixed(2)) : null;
|
|
150
150
|
const lastClose = closes[closes.length - 1];
|
|
151
151
|
// Signal interpretations
|
|
152
152
|
const rsiSignal = rsiValue !== null && rsiValue > 70
|
|
@@ -180,6 +180,7 @@ export async function handleTechnicalIndicators(args, client) {
|
|
|
180
180
|
bollinger_bands: bbResult,
|
|
181
181
|
sma_20: sma20,
|
|
182
182
|
sma_50: sma50,
|
|
183
|
+
sma_50_warning: sma50 === null ? `insufficient data (need 50 candles, have ${closes.length})` : undefined,
|
|
183
184
|
},
|
|
184
185
|
signals: {
|
|
185
186
|
rsi_signal: rsiSignal,
|
|
@@ -194,7 +195,7 @@ export async function handleTechnicalIndicators(args, client) {
|
|
|
194
195
|
}
|
|
195
196
|
catch (err) {
|
|
196
197
|
const msg = err instanceof BudaApiError
|
|
197
|
-
? { error: err.message, code: err.status
|
|
198
|
+
? { error: err.message, code: err.status }
|
|
198
199
|
: { error: String(err), code: "UNKNOWN" };
|
|
199
200
|
return {
|
|
200
201
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
package/dist/tools/ticker.js
CHANGED
|
@@ -60,7 +60,7 @@ export function register(server, client, cache) {
|
|
|
60
60
|
}
|
|
61
61
|
catch (err) {
|
|
62
62
|
const msg = err instanceof BudaApiError
|
|
63
|
-
? { error: err.message, code: err.status
|
|
63
|
+
? { error: err.message, code: err.status }
|
|
64
64
|
: { error: String(err), code: "UNKNOWN" };
|
|
65
65
|
return {
|
|
66
66
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
package/dist/tools/trades.js
CHANGED
|
@@ -76,7 +76,7 @@ export function register(server, client, _cache) {
|
|
|
76
76
|
}
|
|
77
77
|
catch (err) {
|
|
78
78
|
const msg = err instanceof BudaApiError
|
|
79
|
-
? { error: err.message, code: err.status
|
|
79
|
+
? { error: err.message, code: err.status }
|
|
80
80
|
: { error: String(err), code: "UNKNOWN" };
|
|
81
81
|
return {
|
|
82
82
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
package/dist/tools/volume.js
CHANGED
|
@@ -55,7 +55,7 @@ export function register(server, client, _cache) {
|
|
|
55
55
|
}
|
|
56
56
|
catch (err) {
|
|
57
57
|
const msg = err instanceof BudaApiError
|
|
58
|
-
? { error: err.message, code: err.status
|
|
58
|
+
? { error: err.message, code: err.status }
|
|
59
59
|
: { error: String(err), code: "UNKNOWN" };
|
|
60
60
|
return {
|
|
61
61
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -81,7 +81,7 @@ type CreateWithdrawalArgs = {
|
|
|
81
81
|
bank_account_id?: number;
|
|
82
82
|
confirmation_token: string;
|
|
83
83
|
};
|
|
84
|
-
export declare function handleCreateWithdrawal(args: CreateWithdrawalArgs, client: BudaClient): Promise<{
|
|
84
|
+
export declare function handleCreateWithdrawal(args: CreateWithdrawalArgs, client: BudaClient, transport?: "http" | "stdio"): Promise<{
|
|
85
85
|
content: Array<{
|
|
86
86
|
type: "text";
|
|
87
87
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withdrawals.d.ts","sourceRoot":"","sources":["../../src/tools/withdrawals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"withdrawals.d.ts","sourceRoot":"","sources":["../../src/tools/withdrawals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAMxD,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;CA8B1C,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,mBAAmB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAqBF,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,wBAAwB,EAC9B,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CA+ChF;AAED,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBtC,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,oBAAoB,EAC1B,MAAM,EAAE,UAAU,EAClB,SAAS,GAAE,MAAM,GAAG,OAAiB,GACpC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAkGhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CA+BpE"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { BudaApiError } from "../client.js";
|
|
3
|
-
import { validateCurrency } from "../validation.js";
|
|
3
|
+
import { validateCurrency, validateCryptoAddress } from "../validation.js";
|
|
4
4
|
import { flattenAmount } from "../utils.js";
|
|
5
|
+
import { logAudit } from "../audit.js";
|
|
5
6
|
export const getWithdrawalHistoryToolSchema = {
|
|
6
7
|
name: "get_withdrawal_history",
|
|
7
8
|
description: "Returns withdrawal history for a currency on the authenticated Buda.com account. " +
|
|
@@ -81,7 +82,7 @@ export async function handleGetWithdrawalHistory(args, client) {
|
|
|
81
82
|
}
|
|
82
83
|
catch (err) {
|
|
83
84
|
const msg = err instanceof BudaApiError
|
|
84
|
-
? { error: err.message, code: err.status
|
|
85
|
+
? { error: err.message, code: err.status }
|
|
85
86
|
: { error: String(err), code: "UNKNOWN" };
|
|
86
87
|
return {
|
|
87
88
|
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
@@ -93,6 +94,7 @@ export const createWithdrawalToolSchema = {
|
|
|
93
94
|
name: "create_withdrawal",
|
|
94
95
|
description: "Create a withdrawal on Buda.com. Supports both crypto (address) and fiat (bank_account_id) withdrawals. " +
|
|
95
96
|
"Exactly one of address or bank_account_id must be provided. " +
|
|
97
|
+
"WARNING: Crypto withdrawals are irreversible — verify the destination address carefully before confirming. " +
|
|
96
98
|
"IMPORTANT: Pass confirmation_token='CONFIRM' to execute. " +
|
|
97
99
|
"Requires BUDA_API_KEY and BUDA_API_SECRET.",
|
|
98
100
|
inputSchema: {
|
|
@@ -111,7 +113,7 @@ export const createWithdrawalToolSchema = {
|
|
|
111
113
|
required: ["currency", "amount", "confirmation_token"],
|
|
112
114
|
},
|
|
113
115
|
};
|
|
114
|
-
export async function handleCreateWithdrawal(args, client) {
|
|
116
|
+
export async function handleCreateWithdrawal(args, client, transport = "stdio") {
|
|
115
117
|
const { currency, amount, address, network, bank_account_id, confirmation_token } = args;
|
|
116
118
|
if (confirmation_token !== "CONFIRM") {
|
|
117
119
|
return {
|
|
@@ -166,6 +168,15 @@ export async function handleCreateWithdrawal(args, client) {
|
|
|
166
168
|
isError: true,
|
|
167
169
|
};
|
|
168
170
|
}
|
|
171
|
+
if (hasAddress) {
|
|
172
|
+
const addrError = validateCryptoAddress(address, currency);
|
|
173
|
+
if (addrError) {
|
|
174
|
+
return {
|
|
175
|
+
content: [{ type: "text", text: JSON.stringify({ error: addrError, code: "INVALID_ADDRESS" }) }],
|
|
176
|
+
isError: true,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
169
180
|
try {
|
|
170
181
|
const payload = { amount: String(amount) };
|
|
171
182
|
if (hasAddress) {
|
|
@@ -177,18 +188,17 @@ export async function handleCreateWithdrawal(args, client) {
|
|
|
177
188
|
payload.bank_account_id = bank_account_id;
|
|
178
189
|
}
|
|
179
190
|
const data = await client.post(`/currencies/${currency.toUpperCase()}/withdrawals`, payload);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
191
|
+
const result = { content: [{ type: "text", text: JSON.stringify(normalizeWithdrawal(data.withdrawal), null, 2) }] };
|
|
192
|
+
logAudit({ ts: new Date().toISOString(), tool: "create_withdrawal", transport, args_summary: { currency, amount, type: hasAddress ? "crypto" : "fiat" }, success: true });
|
|
193
|
+
return result;
|
|
183
194
|
}
|
|
184
195
|
catch (err) {
|
|
185
196
|
const msg = err instanceof BudaApiError
|
|
186
|
-
? { error: err.message, code: err.status
|
|
197
|
+
? { error: err.message, code: err.status }
|
|
187
198
|
: { error: String(err), code: "UNKNOWN" };
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
};
|
|
199
|
+
const result = { content: [{ type: "text", text: JSON.stringify(msg) }], isError: true };
|
|
200
|
+
logAudit({ ts: new Date().toISOString(), tool: "create_withdrawal", transport, args_summary: { currency, amount, type: hasAddress ? "crypto" : "fiat" }, success: false, error_code: msg.code });
|
|
201
|
+
return result;
|
|
192
202
|
}
|
|
193
203
|
}
|
|
194
204
|
export function register(server, client) {
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { Amount, OhlcvCandle } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Constant-time string comparison to prevent timing attacks on bearer tokens.
|
|
4
|
+
*/
|
|
5
|
+
export declare function safeTokenEqual(a: string, b: string): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Parses a raw string (from an environment variable) as an integer within [min, max].
|
|
8
|
+
* Returns the fallback when raw is undefined.
|
|
9
|
+
* Throws a descriptive Error if the value is non-numeric or out of range.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseEnvInt(raw: string | undefined, fallback: number, min: number, max: number, name: string): number;
|
|
2
12
|
/**
|
|
3
13
|
* Flattens a Buda API Amount tuple [value_string, currency] into a typed object.
|
|
4
14
|
* All numeric strings are cast to float via parseFloat.
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtD;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAK5D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,MAAM,CASR;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAIjF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAI/E;AAWD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAC3C,MAAM,EAAE,MAAM,GACb,WAAW,EAAE,CAoCf"}
|
package/dist/utils.js
CHANGED
|
@@ -1,9 +1,37 @@
|
|
|
1
|
+
import { timingSafeEqual } from "crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Constant-time string comparison to prevent timing attacks on bearer tokens.
|
|
4
|
+
*/
|
|
5
|
+
export function safeTokenEqual(a, b) {
|
|
6
|
+
const aBuf = Buffer.from(a);
|
|
7
|
+
const bBuf = Buffer.from(b);
|
|
8
|
+
if (aBuf.length !== bBuf.length)
|
|
9
|
+
return false;
|
|
10
|
+
return timingSafeEqual(aBuf, bBuf);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parses a raw string (from an environment variable) as an integer within [min, max].
|
|
14
|
+
* Returns the fallback when raw is undefined.
|
|
15
|
+
* Throws a descriptive Error if the value is non-numeric or out of range.
|
|
16
|
+
*/
|
|
17
|
+
export function parseEnvInt(raw, fallback, min, max, name) {
|
|
18
|
+
if (raw === undefined)
|
|
19
|
+
return fallback;
|
|
20
|
+
const n = parseInt(raw, 10);
|
|
21
|
+
if (isNaN(n) || n < min || n > max) {
|
|
22
|
+
throw new Error(`[buda-mcp] Invalid ${name} "${raw}". Must be an integer between ${min} and ${max}.`);
|
|
23
|
+
}
|
|
24
|
+
return n;
|
|
25
|
+
}
|
|
1
26
|
/**
|
|
2
27
|
* Flattens a Buda API Amount tuple [value_string, currency] into a typed object.
|
|
3
28
|
* All numeric strings are cast to float via parseFloat.
|
|
4
29
|
*/
|
|
5
30
|
export function flattenAmount(amount) {
|
|
6
|
-
|
|
31
|
+
const value = parseFloat(amount[0]);
|
|
32
|
+
if (isNaN(value))
|
|
33
|
+
throw new Error(`Invalid amount value: "${amount[0]}"`);
|
|
34
|
+
return { value, currency: amount[1] };
|
|
7
35
|
}
|
|
8
36
|
/**
|
|
9
37
|
* Returns a liquidity rating based on the bid/ask spread percentage.
|
package/dist/validation.d.ts
CHANGED
|
@@ -8,4 +8,10 @@ export declare function validateMarketId(id: string): string | null;
|
|
|
8
8
|
* Returns an error message string if invalid, or null if valid.
|
|
9
9
|
*/
|
|
10
10
|
export declare function validateCurrency(id: string): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Validates a crypto withdrawal address against known per-currency formats.
|
|
13
|
+
* Returns an error message string if the address is invalid, or null if valid
|
|
14
|
+
* (including null for unknown currencies, where the exchange is the last line of defence).
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateCryptoAddress(address: string, currency: string): string | null;
|
|
11
17
|
//# sourceMappingURL=validation.d.ts.map
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS1D;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ1D"}
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS1D;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ1D;AAcD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUtF"}
|
package/dist/validation.js
CHANGED
|
@@ -23,4 +23,30 @@ export function validateCurrency(id) {
|
|
|
23
23
|
}
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
26
|
+
// Per-currency address format rules.
|
|
27
|
+
// Unknown currencies pass through (undefined rule) — the exchange validates those.
|
|
28
|
+
const ADDRESS_RULES = {
|
|
29
|
+
BTC: /^(bc1[a-z0-9]{6,87}|[13][a-zA-HJ-NP-Z0-9]{25,34})$/,
|
|
30
|
+
ETH: /^0x[0-9a-fA-F]{40}$/,
|
|
31
|
+
USDC: /^0x[0-9a-fA-F]{40}$/,
|
|
32
|
+
USDT: /^0x[0-9a-fA-F]{40}$/,
|
|
33
|
+
LTC: /^(ltc1[a-z0-9]{6,87}|[LM3][a-zA-HJ-NP-Z0-9]{25,34})$/,
|
|
34
|
+
BCH: /^(bitcoincash:)?[qp][a-z0-9]{41}$/,
|
|
35
|
+
XRP: /^r[1-9A-HJ-NP-Za-km-z]{24,33}$/,
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Validates a crypto withdrawal address against known per-currency formats.
|
|
39
|
+
* Returns an error message string if the address is invalid, or null if valid
|
|
40
|
+
* (including null for unknown currencies, where the exchange is the last line of defence).
|
|
41
|
+
*/
|
|
42
|
+
export function validateCryptoAddress(address, currency) {
|
|
43
|
+
const rule = ADDRESS_RULES[currency.toUpperCase()];
|
|
44
|
+
if (!rule)
|
|
45
|
+
return null;
|
|
46
|
+
if (!rule.test(address)) {
|
|
47
|
+
return (`Invalid ${currency.toUpperCase()} address format. ` +
|
|
48
|
+
`Double-check the destination address — crypto withdrawals are irreversible.`);
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
26
52
|
//# sourceMappingURL=validation.js.map
|
package/dist/version.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,OAAO,EAAE,MAAiB,CAAC"}
|
package/dist/version.js
CHANGED
|
@@ -2,5 +2,12 @@ import { readFileSync } from "fs";
|
|
|
2
2
|
import { fileURLToPath } from "url";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
4
|
const _dir = dirname(fileURLToPath(import.meta.url));
|
|
5
|
-
|
|
5
|
+
let _version = "unknown";
|
|
6
|
+
try {
|
|
7
|
+
_version = JSON.parse(readFileSync(join(_dir, "../package.json"), "utf8")).version;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
// package.json not found in deployment — use fallback
|
|
11
|
+
}
|
|
12
|
+
export const VERSION = _version;
|
|
6
13
|
//# sourceMappingURL=version.js.map
|
package/marketplace/README.md
CHANGED