@guiie/buda-mcp 1.0.0 → 1.1.1

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.
Files changed (77) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/PUBLISH_CHECKLIST.md +192 -0
  3. package/README.md +308 -70
  4. package/dist/cache.d.ts +13 -0
  5. package/dist/cache.d.ts.map +1 -0
  6. package/dist/cache.js +25 -0
  7. package/dist/client.d.ts +9 -8
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +95 -12
  10. package/dist/http.d.ts +2 -0
  11. package/dist/http.d.ts.map +1 -0
  12. package/dist/http.js +262 -0
  13. package/dist/index.js +53 -9
  14. package/dist/tools/balances.d.ts +4 -0
  15. package/dist/tools/balances.d.ts.map +1 -0
  16. package/dist/tools/balances.js +23 -0
  17. package/dist/tools/cancel_order.d.ts +4 -0
  18. package/dist/tools/cancel_order.d.ts.map +1 -0
  19. package/dist/tools/cancel_order.js +53 -0
  20. package/dist/tools/compare_markets.d.ts +5 -0
  21. package/dist/tools/compare_markets.d.ts.map +1 -0
  22. package/dist/tools/compare_markets.js +65 -0
  23. package/dist/tools/markets.d.ts +2 -1
  24. package/dist/tools/markets.d.ts.map +1 -1
  25. package/dist/tools/markets.js +22 -8
  26. package/dist/tools/orderbook.d.ts +2 -1
  27. package/dist/tools/orderbook.d.ts.map +1 -1
  28. package/dist/tools/orderbook.js +27 -13
  29. package/dist/tools/orders.d.ts +4 -0
  30. package/dist/tools/orders.d.ts.map +1 -0
  31. package/dist/tools/orders.js +57 -0
  32. package/dist/tools/place_order.d.ts +4 -0
  33. package/dist/tools/place_order.d.ts.map +1 -0
  34. package/dist/tools/place_order.js +88 -0
  35. package/dist/tools/price_history.d.ts +5 -0
  36. package/dist/tools/price_history.d.ts.map +1 -0
  37. package/dist/tools/price_history.js +97 -0
  38. package/dist/tools/spread.d.ts +5 -0
  39. package/dist/tools/spread.d.ts.map +1 -0
  40. package/dist/tools/spread.js +55 -0
  41. package/dist/tools/ticker.d.ts +2 -1
  42. package/dist/tools/ticker.d.ts.map +1 -1
  43. package/dist/tools/ticker.js +19 -5
  44. package/dist/tools/trades.d.ts +2 -1
  45. package/dist/tools/trades.d.ts.map +1 -1
  46. package/dist/tools/trades.js +22 -10
  47. package/dist/tools/volume.d.ts +2 -1
  48. package/dist/tools/volume.d.ts.map +1 -1
  49. package/dist/tools/volume.js +17 -5
  50. package/dist/types.d.ts +42 -1
  51. package/dist/types.d.ts.map +1 -1
  52. package/marketplace/claude-listing.md +72 -4
  53. package/marketplace/cursor-mcp.json +1 -1
  54. package/marketplace/gemini-tools.json +51 -1
  55. package/marketplace/openapi.yaml +203 -3
  56. package/package.json +6 -2
  57. package/railway.json +12 -0
  58. package/server.json +3 -3
  59. package/src/cache.ts +34 -0
  60. package/src/client.ts +107 -12
  61. package/src/http.ts +305 -0
  62. package/src/index.ts +77 -9
  63. package/src/tools/balances.ts +30 -0
  64. package/src/tools/cancel_order.ts +65 -0
  65. package/src/tools/compare_markets.ts +82 -0
  66. package/src/tools/markets.ts +30 -11
  67. package/src/tools/orderbook.ts +31 -16
  68. package/src/tools/orders.ts +68 -0
  69. package/src/tools/place_order.ts +107 -0
  70. package/src/tools/price_history.ts +124 -0
  71. package/src/tools/spread.ts +71 -0
  72. package/src/tools/ticker.ts +23 -8
  73. package/src/tools/trades.ts +24 -12
  74. package/src/tools/volume.ts +20 -8
  75. package/src/types.ts +52 -1
  76. package/test/run-all.ts +122 -1
  77. package/tsconfig.json +1 -1
package/README.md CHANGED
@@ -1,122 +1,360 @@
1
1
  # buda-mcp
2
2
 
3
- A production-ready [MCP](https://modelcontextprotocol.io/) server for the [Buda.com](https://www.buda.com/) cryptocurrency exchange public API. Exposes real-time market data tools to any MCP-compatible AI client (Claude Code, Cursor, ChatGPT, etc.).
3
+ [![npm version](https://img.shields.io/npm/v/@guiie/buda-mcp)](https://www.npmjs.com/package/@guiie/buda-mcp)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Node.js >=18](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org/)
4
6
 
5
- ## Tools
6
-
7
- | Tool | Description |
8
- |---|---|
9
- | `get_markets` | List all trading pairs, or get details for one market |
10
- | `get_ticker` | Current price, bid/ask, volume, and price change for a market |
11
- | `get_orderbook` | Full order book (bids + asks) for a market |
12
- | `get_trades` | Recent trade history for a market |
13
- | `get_market_volume` | 24h and 7-day transacted volume for a market |
7
+ MCP server for [Buda.com](https://www.buda.com/) — the leading cryptocurrency exchange in Chile, Colombia, and Peru. Gives any MCP-compatible AI assistant live access to market data, order books, trade history, spreads, and (when credentials are provided) private account tools.
14
8
 
15
- All tools use Buda.com's **public** endpoints — no API key required.
9
+ ---
16
10
 
17
- ## Requirements
11
+ ## Quick Start
18
12
 
19
- - Node.js 18+
20
- - npm 8+
13
+ ```bash
14
+ npx @guiie/buda-mcp
15
+ ```
21
16
 
22
- ## Installation
17
+ Or install permanently:
23
18
 
24
19
  ```bash
25
- git clone https://github.com/gtorreal/buda-mcp.git
26
- cd buda-mcp
27
- npm install
28
- npm run build
20
+ npm install -g @guiie/buda-mcp
21
+ buda-mcp
29
22
  ```
30
23
 
31
- ## Running the test suite
24
+ ---
25
+
26
+ ## Install in your MCP client
32
27
 
33
- Calls each tool against the live Buda API and prints the results:
28
+ ### Claude Code
34
29
 
35
30
  ```bash
36
- npm test
31
+ claude mcp add buda-mcp -- npx -y @guiie/buda-mcp
37
32
  ```
38
33
 
39
- ## Usage
34
+ ### Claude Desktop (`claude_desktop_config.json`)
40
35
 
41
- ### Claude Code
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "buda-mcp": {
40
+ "command": "npx",
41
+ "args": ["-y", "@guiie/buda-mcp"]
42
+ }
43
+ }
44
+ }
45
+ ```
42
46
 
43
- Add the server with the `claude` CLI:
47
+ ### Cursor (`~/.cursor/mcp.json`)
44
48
 
45
- ```bash
46
- claude mcp add buda-mcp -- node /absolute/path/to/buda-mcp/dist/index.js
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "buda-mcp": {
53
+ "command": "npx",
54
+ "args": ["-y", "@guiie/buda-mcp"]
55
+ }
56
+ }
57
+ }
47
58
  ```
48
59
 
49
- Then ask Claude things like:
60
+ ---
61
+
62
+ ## Tools
63
+
64
+ ### Public tools (no credentials required)
65
+
66
+ #### `get_markets`
67
+ List all 26 trading pairs on Buda.com, or get details for a specific market.
68
+
69
+ | Parameter | Type | Required | Description |
70
+ |-----------|------|----------|-------------|
71
+ | `market_id` | string | No | Market ID (e.g. `BTC-CLP`). Omit to list all markets. |
72
+
73
+ **Example prompts:**
74
+ - *"List all markets available on Buda.com"*
75
+ - *"What are the trading fees for BTC-CLP?"*
76
+ - *"What's the minimum order size for ETH-COP?"*
77
+
78
+ ---
79
+
80
+ #### `get_ticker`
81
+ Current snapshot: last price, best bid/ask, 24h volume, and price change over 24h and 7d.
82
+
83
+ | Parameter | Type | Required | Description |
84
+ |-----------|------|----------|-------------|
85
+ | `market_id` | string | Yes | Market ID (e.g. `BTC-CLP`, `ETH-COP`). |
86
+
87
+ **Example prompts:**
88
+ - *"What is the current Bitcoin price in Chilean pesos?"*
89
+ - *"Show me the ETH-COP ticker"*
90
+ - *"How much has BTC changed in the last 7 days on Buda?"*
91
+
92
+ ---
93
+
94
+ #### `get_orderbook`
95
+ Current order book: sorted bids and asks as `[price, amount]` pairs.
96
+
97
+ | Parameter | Type | Required | Description |
98
+ |-----------|------|----------|-------------|
99
+ | `market_id` | string | Yes | Market ID. |
100
+ | `limit` | number | No | Max price levels per side (default: all). |
101
+
102
+ **Example prompts:**
103
+ - *"Show me the BTC-CLP order book — top 10 bids and asks"*
104
+ - *"How deep is the ETH-BTC order book?"*
105
+
106
+ ---
107
+
108
+ #### `get_trades`
109
+ Recent trade history. Each entry: `[timestamp_ms, amount, price, direction]`.
110
+
111
+ | Parameter | Type | Required | Description |
112
+ |-----------|------|----------|-------------|
113
+ | `market_id` | string | Yes | Market ID. |
114
+ | `limit` | number | No | Number of trades (default 50, max 100). |
115
+ | `timestamp` | number | No | Unix seconds — returns trades older than this (pagination). |
116
+
117
+ **Example prompts:**
118
+ - *"Show the last 20 trades on BTC-CLP"*
119
+ - *"Were there more buys or sells in the last 50 BTC-COP trades?"*
120
+
121
+ ---
122
+
123
+ #### `get_market_volume`
124
+ 24h and 7-day transacted volume by side (bid = buys, ask = sells).
125
+
126
+ | Parameter | Type | Required | Description |
127
+ |-----------|------|----------|-------------|
128
+ | `market_id` | string | Yes | Market ID. |
129
+
130
+ **Example prompts:**
131
+ - *"How much ETH was traded on Buda in the last 7 days?"*
132
+ - *"What's the BTC-CLP buy vs sell volume over 24 hours?"*
133
+
134
+ ---
135
+
136
+ #### `get_spread`
137
+ Bid/ask spread: absolute value and percentage of the ask price.
138
+
139
+ | Parameter | Type | Required | Description |
140
+ |-----------|------|----------|-------------|
141
+ | `market_id` | string | Yes | Market ID. |
142
+
143
+ **Example prompts:**
144
+ - *"What's the spread on BTC-COP right now?"*
145
+ - *"Is the ETH-CLP spread tighter than BTC-CLP?"*
146
+
147
+ ---
148
+
149
+ #### `compare_markets`
150
+ Side-by-side ticker data for all pairs of a given base currency (CLP, COP, PEN, USDC…).
50
151
 
51
- > What is the current BTC-CLP price?
52
- > Show me the order book for ETH-CLP.
53
- > How much Bitcoin was traded in the last 7 days on BTC-CLP?
152
+ | Parameter | Type | Required | Description |
153
+ |-----------|------|----------|-------------|
154
+ | `base_currency` | string | Yes | Base currency to compare (e.g. `BTC`, `ETH`). |
54
155
 
55
- ### Cursor
156
+ **Example prompts:**
157
+ - *"Compare the Bitcoin price across all Buda markets"*
158
+ - *"Show me ETH in CLP, COP, and PEN side by side"*
159
+ - *"Which Buda market has the highest BTC trading volume?"*
56
160
 
57
- Add to `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally):
161
+ ---
162
+
163
+ #### `get_price_history`
164
+ OHLCV candles derived from recent trade history (no native candlestick endpoint exists on Buda — candles are aggregated client-side from up to 100 raw trades).
165
+
166
+ | Parameter | Type | Required | Description |
167
+ |-----------|------|----------|-------------|
168
+ | `market_id` | string | Yes | Market ID. |
169
+ | `period` | `1h` \| `4h` \| `1d` | No | Candle period (default `1h`). |
170
+ | `limit` | number | No | Raw trades to fetch before aggregation (default 100, max 100). |
171
+
172
+ **Example prompts:**
173
+ - *"Show me hourly price candles for BTC-CLP"*
174
+ - *"What were the daily open/high/low/close for ETH-COP?"*
175
+
176
+ ---
177
+
178
+ ### Authenticated tools
179
+
180
+ Available only when `BUDA_API_KEY` and `BUDA_API_SECRET` environment variables are set. See [Authentication mode](#authentication-mode) below.
181
+
182
+ > **Warning:** Authenticated instances must be run **locally only**. Never expose a server with API credentials to the internet.
183
+
184
+ #### `get_balances`
185
+ All currency balances: total, available, frozen, and pending withdrawal.
186
+
187
+ **Example prompts:**
188
+ - *"What's my BTC balance on Buda?"*
189
+ - *"Show all my balances"*
190
+
191
+ ---
192
+
193
+ #### `get_orders`
194
+ Orders for a given market, filterable by state.
195
+
196
+ | Parameter | Type | Required | Description |
197
+ |-----------|------|----------|-------------|
198
+ | `market_id` | string | Yes | Market ID. |
199
+ | `state` | string | No | `pending`, `active`, `traded`, `canceled`, `canceled_and_traded`. |
200
+ | `per` | number | No | Results per page (default 20, max 300). |
201
+ | `page` | number | No | Page number (default 1). |
202
+
203
+ **Example prompts:**
204
+ - *"Show my open orders on BTC-CLP"*
205
+ - *"List my last 10 traded orders on ETH-COP"*
206
+
207
+ ---
208
+
209
+ #### `place_order`
210
+ Place a limit or market order.
211
+
212
+ **Requires `confirmation_token="CONFIRM"`** — prevents accidental execution from ambiguous prompts.
213
+
214
+ | Parameter | Type | Required | Description |
215
+ |-----------|------|----------|-------------|
216
+ | `market_id` | string | Yes | Market ID. |
217
+ | `type` | `Bid` \| `Ask` | Yes | Order side. |
218
+ | `price_type` | `limit` \| `market` | Yes | Order type. |
219
+ | `amount` | number | Yes | Order size in base currency. |
220
+ | `limit_price` | number | No | Required for limit orders. |
221
+ | `confirmation_token` | string | Yes | Must equal `"CONFIRM"` to execute. |
222
+
223
+ **Example prompts:**
224
+ - *"Place a limit buy order for 0.001 BTC at 60,000,000 CLP on BTC-CLP, confirmation_token=CONFIRM"*
225
+
226
+ ---
227
+
228
+ #### `cancel_order`
229
+ Cancel an open order by ID.
230
+
231
+ **Requires `confirmation_token="CONFIRM"`**.
232
+
233
+ | Parameter | Type | Required | Description |
234
+ |-----------|------|----------|-------------|
235
+ | `order_id` | number | Yes | Numeric order ID. |
236
+ | `confirmation_token` | string | Yes | Must equal `"CONFIRM"` to cancel. |
237
+
238
+ ---
239
+
240
+ ## MCP Resources
241
+
242
+ In addition to tools, the server exposes two MCP Resources that clients can read directly:
243
+
244
+ | URI | Description |
245
+ |-----|-------------|
246
+ | `buda://markets` | JSON list of all Buda.com markets |
247
+ | `buda://ticker/{market}` | JSON ticker for a specific market (e.g. `buda://ticker/BTC-CLP`) |
248
+
249
+ ---
250
+
251
+ ## Authentication mode
252
+
253
+ The server defaults to **public-only mode** — no API key needed, no breaking changes for existing users.
254
+
255
+ To enable authenticated tools, set environment variables before running:
256
+
257
+ ```bash
258
+ BUDA_API_KEY=your_api_key BUDA_API_SECRET=your_api_secret npx @guiie/buda-mcp
259
+ ```
260
+
261
+ Or in Claude Desktop config:
58
262
 
59
263
  ```json
60
264
  {
61
265
  "mcpServers": {
62
266
  "buda-mcp": {
63
- "command": "node",
64
- "args": ["/absolute/path/to/buda-mcp/dist/index.js"]
267
+ "command": "npx",
268
+ "args": ["-y", "@guiie/buda-mcp"],
269
+ "env": {
270
+ "BUDA_API_KEY": "your_api_key",
271
+ "BUDA_API_SECRET": "your_api_secret"
272
+ }
65
273
  }
66
274
  }
67
275
  }
68
276
  ```
69
277
 
70
- Restart Cursor and the tools will be available to the AI agent in chat.
278
+ Authentication uses HMAC-SHA384 signing per the [Buda API docs](https://api.buda.com/en/#authentication). Keys are never logged.
71
279
 
72
- ### ChatGPT (Actions / Custom GPT)
280
+ > **Security:** Never expose an authenticated instance on a public server. Always run locally when using API credentials.
73
281
 
74
- ChatGPT does not natively support the stdio MCP transport. To use this server with ChatGPT you need an HTTP bridge. The simplest option is [mcp-server-proxy](https://github.com/sparfenyuk/mcp-proxy):
282
+ ---
75
283
 
76
- ```bash
77
- pip install mcp-proxy
78
- mcp-proxy --port 8000 -- node /absolute/path/to/buda-mcp/dist/index.js
79
- ```
284
+ ## Markets covered
80
285
 
81
- Then register `http://localhost:8000` (or your deployed URL) as a GPT Action endpoint. Use the auto-generated OpenAPI schema that `mcp-proxy` exposes at `/openapi.json`.
286
+ | Quote | Country | Sample pairs |
287
+ |-------|---------|-------------|
288
+ | CLP | Chile | BTC-CLP, ETH-CLP, XRP-CLP |
289
+ | COP | Colombia | BTC-COP, ETH-COP, XRP-COP |
290
+ | PEN | Peru | BTC-PEN, ETH-PEN |
291
+ | USDC | USD-pegged | BTC-USDC, ETH-USDC |
292
+ | BTC | Cross | ETH-BTC, XRP-BTC, BCH-BTC |
82
293
 
83
- ## Project structure
294
+ ---
84
295
 
296
+ ## Build from source
297
+
298
+ ```bash
299
+ git clone https://github.com/gtorreal/buda-mcp.git
300
+ cd buda-mcp
301
+ npm install
302
+ npm run build
303
+ node dist/index.js # stdio (for MCP clients)
304
+ node dist/http.js # HTTP on port 3000 (for Railway / hosted)
85
305
  ```
86
- src/
87
- index.ts — MCP server entry point
88
- client.ts — BudaClient HTTP wrapper (extend here for auth)
89
- types.ts — TypeScript types for all API responses
90
- tools/
91
- markets.ts — get_markets
92
- ticker.ts — get_ticker
93
- orderbook.ts — get_orderbook
94
- trades.ts — get_trades
95
- volume.ts — get_market_volume
96
- test/
97
- run-all.ts — integration test script
306
+
307
+ Run tests (requires live internet access):
308
+
309
+ ```bash
310
+ npm test
98
311
  ```
99
312
 
100
- ## Adding private endpoints
313
+ ---
101
314
 
102
- `BudaClient` in `src/client.ts` is structured for easy extension. To add authenticated endpoints (balances, orders, withdrawals):
315
+ ## HTTP / Railway deployment
103
316
 
104
- 1. Add `apiKey` and `apiSecret` constructor parameters.
105
- 2. Implement HMAC-SHA2 signing in a `signedGet` / `signedPost` method (see [Buda auth docs](https://api.buda.com/en/#rest-api-private-endpoints-authentication)).
106
- 3. Drop new tool files under `src/tools/` and call `register(server, client)` in `src/index.ts`.
317
+ The `dist/http.js` entrypoint runs an Express server with:
318
+ - `POST /mcp` Streamable HTTP MCP transport
319
+ - `GET /mcp` SSE streaming transport
320
+ - `GET /health` — health check (`{ status, version, auth_mode }`)
321
+ - `GET /.well-known/mcp/server-card.json` — Smithery-compatible static tool manifest
107
322
 
108
- ## Markets available
323
+ Set `PORT` environment variable to override the default `3000`.
109
324
 
110
- Buda.com operates in Chile, Colombia, and Peru:
325
+ ---
111
326
 
112
- | Quote currency | Country |
113
- |---|---|
114
- | CLP | Chile |
115
- | COP | Colombia |
116
- | PEN | Peru |
327
+ ## Project structure
328
+
329
+ ```
330
+ src/
331
+ client.ts BudaClient (HTTP + HMAC auth)
332
+ cache.ts In-memory TTL cache
333
+ types.ts TypeScript types for Buda API responses
334
+ index.ts stdio MCP server entrypoint
335
+ http.ts HTTP/SSE MCP server entrypoint
336
+ tools/
337
+ markets.ts get_markets
338
+ ticker.ts get_ticker
339
+ orderbook.ts get_orderbook
340
+ trades.ts get_trades
341
+ volume.ts get_market_volume
342
+ spread.ts get_spread
343
+ compare_markets.ts compare_markets
344
+ price_history.ts get_price_history
345
+ balances.ts get_balances (auth)
346
+ orders.ts get_orders (auth)
347
+ place_order.ts place_order (auth)
348
+ cancel_order.ts cancel_order (auth)
349
+ marketplace/
350
+ cursor-mcp.json Cursor MCP config example
351
+ claude-listing.md Claude registry listing
352
+ openapi.yaml OpenAPI spec (GPT Actions / HTTP wrapper)
353
+ gemini-tools.json Gemini function declarations
354
+ ```
117
355
 
118
- Common markets: `BTC-CLP`, `ETH-CLP`, `BTC-COP`, `ETH-COP`, `BTC-PEN`, `ETH-PEN`, `ETH-BTC`, `XRP-BTC`, etc.
356
+ ---
119
357
 
120
358
  ## License
121
359
 
122
- MIT
360
+ MIT — [Buda.com API docs](https://api.buda.com/en/)
@@ -0,0 +1,13 @@
1
+ export declare class MemoryCache {
2
+ private store;
3
+ getOrFetch<T>(key: string, ttlMs: number, fetcher: () => Promise<T>): Promise<T>;
4
+ invalidate(key: string): void;
5
+ clear(): void;
6
+ }
7
+ export declare const CACHE_TTL: {
8
+ readonly MARKETS: 60000;
9
+ readonly TICKER: 5000;
10
+ readonly ORDERBOOK: 3000;
11
+ };
12
+ export declare const cache: MemoryCache;
13
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAKA,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAA0C;IAEjD,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAUtF,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B,KAAK,IAAI,IAAI;CAGd;AAED,eAAO,MAAM,SAAS;;;;CAIZ,CAAC;AAEX,eAAO,MAAM,KAAK,aAAoB,CAAC"}
package/dist/cache.js ADDED
@@ -0,0 +1,25 @@
1
+ export class MemoryCache {
2
+ store = new Map();
3
+ async getOrFetch(key, ttlMs, fetcher) {
4
+ const entry = this.store.get(key);
5
+ if (entry && Date.now() < entry.expiry) {
6
+ return entry.data;
7
+ }
8
+ const data = await fetcher();
9
+ this.store.set(key, { data, expiry: Date.now() + ttlMs });
10
+ return data;
11
+ }
12
+ invalidate(key) {
13
+ this.store.delete(key);
14
+ }
15
+ clear() {
16
+ this.store.clear();
17
+ }
18
+ }
19
+ export const CACHE_TTL = {
20
+ MARKETS: 60_000,
21
+ TICKER: 5_000,
22
+ ORDERBOOK: 3_000,
23
+ };
24
+ export const cache = new MemoryCache();
25
+ //# sourceMappingURL=cache.js.map
package/dist/client.d.ts CHANGED
@@ -5,14 +5,15 @@ export declare class BudaApiError extends Error {
5
5
  }
6
6
  export declare class BudaClient {
7
7
  private readonly baseUrl;
8
- constructor(baseUrl?: string);
9
- /**
10
- * Perform an authenticated GET request.
11
- *
12
- * Private endpoints (balances, orders, etc.) require HMAC-SHA2 signing.
13
- * To add auth later, extend this method with the `apiKey` + `apiSecret`
14
- * constructor params and sign the nonce/path headers here before fetching.
15
- */
8
+ private readonly apiKey;
9
+ private readonly apiSecret;
10
+ constructor(baseUrl?: string, apiKey?: string, apiSecret?: string);
11
+ hasAuth(): boolean;
12
+ private nonce;
13
+ private sign;
14
+ private authHeaders;
16
15
  get<T>(path: string, params?: Record<string, string | number>): Promise<T>;
16
+ post<T>(path: string, payload: unknown): Promise<T>;
17
+ put<T>(path: string, payload: unknown): Promise<T>;
17
18
  }
18
19
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,qBAAa,YAAa,SAAQ,KAAK;aAEnB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,MAAiB;IAItC;;;;;;OAMG;IACG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CA6BjF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAIA,qBAAa,YAAa,SAAQ,KAAK;aAEnB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;gBAG7C,OAAO,GAAE,MAAiB,EAC1B,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM;IAOpB,OAAO,IAAI,OAAO;IAIlB,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,WAAW;IAWb,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgC1E,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IA+BnD,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;CA8BzD"}
package/dist/client.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createHmac } from "crypto";
1
2
  const BASE_URL = "https://www.buda.com/api/v2";
2
3
  export class BudaApiError extends Error {
3
4
  status;
@@ -11,16 +12,39 @@ export class BudaApiError extends Error {
11
12
  }
12
13
  export class BudaClient {
13
14
  baseUrl;
14
- constructor(baseUrl = BASE_URL) {
15
+ apiKey;
16
+ apiSecret;
17
+ constructor(baseUrl = BASE_URL, apiKey, apiSecret) {
15
18
  this.baseUrl = baseUrl;
19
+ this.apiKey = apiKey;
20
+ this.apiSecret = apiSecret;
21
+ }
22
+ hasAuth() {
23
+ return Boolean(this.apiKey && this.apiSecret);
24
+ }
25
+ nonce() {
26
+ return String(Math.floor(Date.now() * 1000));
27
+ }
28
+ sign(method, pathWithQuery, body, nonce) {
29
+ const encodedBody = body ? Buffer.from(body).toString("base64") : "";
30
+ const parts = [method, pathWithQuery];
31
+ if (encodedBody)
32
+ parts.push(encodedBody);
33
+ parts.push(nonce);
34
+ const msg = parts.join(" ");
35
+ return createHmac("sha384", this.apiSecret).update(msg).digest("hex");
36
+ }
37
+ authHeaders(method, path, body) {
38
+ if (!this.hasAuth())
39
+ return {};
40
+ const nonce = this.nonce();
41
+ const signature = this.sign(method, path, body ?? "", nonce);
42
+ return {
43
+ "X-SBTC-APIKEY": this.apiKey,
44
+ "X-SBTC-NONCE": nonce,
45
+ "X-SBTC-SIGNATURE": signature,
46
+ };
16
47
  }
17
- /**
18
- * Perform an authenticated GET request.
19
- *
20
- * Private endpoints (balances, orders, etc.) require HMAC-SHA2 signing.
21
- * To add auth later, extend this method with the `apiKey` + `apiSecret`
22
- * constructor params and sign the nonce/path headers here before fetching.
23
- */
24
48
  async get(path, params) {
25
49
  const url = new URL(`${this.baseUrl}${path}.json`);
26
50
  if (params) {
@@ -28,11 +52,70 @@ export class BudaClient {
28
52
  url.searchParams.set(key, String(value));
29
53
  }
30
54
  }
55
+ const urlPath = url.pathname + url.search;
56
+ const headers = {
57
+ Accept: "application/json",
58
+ "User-Agent": "buda-mcp/1.1.0",
59
+ ...this.authHeaders("GET", urlPath),
60
+ };
61
+ const response = await fetch(url.toString(), { headers });
62
+ if (!response.ok) {
63
+ let detail = response.statusText;
64
+ try {
65
+ const body = (await response.json());
66
+ if (body.message)
67
+ detail = body.message;
68
+ }
69
+ catch {
70
+ // ignore parse error, use statusText
71
+ }
72
+ throw new BudaApiError(response.status, path, `Buda API ${response.status}: ${detail}`);
73
+ }
74
+ return response.json();
75
+ }
76
+ async post(path, payload) {
77
+ const url = new URL(`${this.baseUrl}${path}.json`);
78
+ const bodyStr = JSON.stringify(payload);
79
+ const urlPath = url.pathname + url.search;
80
+ const headers = {
81
+ Accept: "application/json",
82
+ "Content-Type": "application/json",
83
+ "User-Agent": "buda-mcp/1.1.0",
84
+ ...this.authHeaders("POST", urlPath, bodyStr),
85
+ };
86
+ const response = await fetch(url.toString(), {
87
+ method: "POST",
88
+ headers,
89
+ body: bodyStr,
90
+ });
91
+ if (!response.ok) {
92
+ let detail = response.statusText;
93
+ try {
94
+ const body = (await response.json());
95
+ if (body.message)
96
+ detail = body.message;
97
+ }
98
+ catch {
99
+ // ignore parse error, use statusText
100
+ }
101
+ throw new BudaApiError(response.status, path, `Buda API ${response.status}: ${detail}`);
102
+ }
103
+ return response.json();
104
+ }
105
+ async put(path, payload) {
106
+ const url = new URL(`${this.baseUrl}${path}.json`);
107
+ const bodyStr = JSON.stringify(payload);
108
+ const urlPath = url.pathname + url.search;
109
+ const headers = {
110
+ Accept: "application/json",
111
+ "Content-Type": "application/json",
112
+ "User-Agent": "buda-mcp/1.1.0",
113
+ ...this.authHeaders("PUT", urlPath, bodyStr),
114
+ };
31
115
  const response = await fetch(url.toString(), {
32
- headers: {
33
- Accept: "application/json",
34
- "User-Agent": "buda-mcp/1.0.0",
35
- },
116
+ method: "PUT",
117
+ headers,
118
+ body: bodyStr,
36
119
  });
37
120
  if (!response.ok) {
38
121
  let detail = response.statusText;
package/dist/http.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":""}