@carbon-copy/mcp 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.
Files changed (62) hide show
  1. package/.github/workflows/publish.yml +23 -0
  2. package/CLAUDE.md +69 -0
  3. package/LICENSE +21 -0
  4. package/README.md +108 -0
  5. package/dist/__tests__/client.test.d.ts +2 -0
  6. package/dist/__tests__/client.test.d.ts.map +1 -0
  7. package/dist/__tests__/client.test.js +292 -0
  8. package/dist/__tests__/client.test.js.map +1 -0
  9. package/dist/__tests__/resources.test.d.ts +2 -0
  10. package/dist/__tests__/resources.test.d.ts.map +1 -0
  11. package/dist/__tests__/resources.test.js +176 -0
  12. package/dist/__tests__/resources.test.js.map +1 -0
  13. package/dist/__tests__/tools.test.d.ts +2 -0
  14. package/dist/__tests__/tools.test.d.ts.map +1 -0
  15. package/dist/__tests__/tools.test.js +317 -0
  16. package/dist/__tests__/tools.test.js.map +1 -0
  17. package/dist/client.d.ts +46 -0
  18. package/dist/client.d.ts.map +1 -0
  19. package/dist/client.js +94 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +33 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/resources/portfolio.d.ts +4 -0
  26. package/dist/resources/portfolio.d.ts.map +1 -0
  27. package/dist/resources/portfolio.js +19 -0
  28. package/dist/resources/portfolio.js.map +1 -0
  29. package/dist/resources/traders.d.ts +4 -0
  30. package/dist/resources/traders.d.ts.map +1 -0
  31. package/dist/resources/traders.js +19 -0
  32. package/dist/resources/traders.js.map +1 -0
  33. package/dist/tools/account.d.ts +4 -0
  34. package/dist/tools/account.d.ts.map +1 -0
  35. package/dist/tools/account.js +32 -0
  36. package/dist/tools/account.js.map +1 -0
  37. package/dist/tools/orders.d.ts +4 -0
  38. package/dist/tools/orders.d.ts.map +1 -0
  39. package/dist/tools/orders.js +57 -0
  40. package/dist/tools/orders.js.map +1 -0
  41. package/dist/tools/portfolio.d.ts +4 -0
  42. package/dist/tools/portfolio.d.ts.map +1 -0
  43. package/dist/tools/portfolio.js +84 -0
  44. package/dist/tools/portfolio.js.map +1 -0
  45. package/dist/tools/traders.d.ts +4 -0
  46. package/dist/tools/traders.d.ts.map +1 -0
  47. package/dist/tools/traders.js +163 -0
  48. package/dist/tools/traders.js.map +1 -0
  49. package/package.json +43 -0
  50. package/src/__tests__/client.test.ts +392 -0
  51. package/src/__tests__/resources.test.ts +263 -0
  52. package/src/__tests__/tools.test.ts +440 -0
  53. package/src/client.ts +161 -0
  54. package/src/index.ts +41 -0
  55. package/src/resources/portfolio.ts +30 -0
  56. package/src/resources/traders.ts +29 -0
  57. package/src/tools/account.ts +48 -0
  58. package/src/tools/orders.ts +74 -0
  59. package/src/tools/portfolio.ts +106 -0
  60. package/src/tools/traders.ts +207 -0
  61. package/tsconfig.json +17 -0
  62. package/vitest.config.ts +9 -0
@@ -0,0 +1,23 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: 22
17
+ registry-url: https://registry.npmjs.org
18
+ - run: npm ci
19
+ - run: npm run build
20
+ - run: npm test
21
+ - run: npm publish --access public
22
+ env:
23
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/CLAUDE.md ADDED
@@ -0,0 +1,69 @@
1
+ # Carbon Copy MCP Server
2
+
3
+ MCP (Model Context Protocol) server that wraps the Carbon Copy REST API, enabling AI agents to manage Polymarket copy-trading portfolios.
4
+
5
+ ## Build & Run
6
+
7
+ ```bash
8
+ npm install
9
+ npm run build # TypeScript → dist/
10
+ npm run dev # Dev mode with watch
11
+ npx @carbon-copy/mcp # Run via npx (after publish)
12
+ ```
13
+
14
+ ## Configuration
15
+
16
+ Set `CARBONCOPY_API_KEY` env var (format: `cc_<64 hex chars>`).
17
+
18
+ ```json
19
+ {
20
+ "mcpServers": {
21
+ "carboncopy": {
22
+ "command": "npx",
23
+ "args": ["@carbon-copy/mcp"],
24
+ "env": { "CARBONCOPY_API_KEY": "cc_..." }
25
+ }
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Structure
31
+
32
+ ```
33
+ src/
34
+ index.ts # McpServer setup + stdio transport
35
+ client.ts # HTTP client for CC REST API
36
+ tools/
37
+ portfolio.ts # get_portfolio, get_history, get_positions
38
+ traders.ts # list/follow/update/unfollow/pause/resume
39
+ orders.ts # list_orders, get_order
40
+ account.ts # get_account, health
41
+ resources/
42
+ portfolio.ts # carboncopy://portfolio
43
+ traders.ts # carboncopy://traders
44
+ ```
45
+
46
+ ## Public API Ecosystem
47
+
48
+ Carbon Copy has three repos that form the public API surface:
49
+
50
+ | Repo | Purpose | Deploys to |
51
+ |---|---|---|
52
+ | `CarbonCopyInc/habakkuk` | App + Convex backend + REST API (source of truth) | Vercel + Convex |
53
+ | `CarbonCopyInc/docs` | Mintlify API documentation | Mintlify |
54
+ | `CarbonCopyInc/carboncopy-mcp` (this repo) | MCP server | npm (`@carbon-copy/mcp`) |
55
+
56
+ ### Sync Rules
57
+
58
+ - **`habakkuk` is the source of truth** for API behavior. This server wraps it.
59
+ - This is a **thin fetch wrapper** — it does NOT parse or validate API response fields.
60
+ - Only needs updating when endpoints are added, removed, or renamed.
61
+ - Auth is handled via `CARBONCOPY_API_KEY` env var. No OAuth flows.
62
+
63
+ ## Conventions
64
+
65
+ - Use `@modelcontextprotocol/sdk` (spec version 2025-11-25)
66
+ - All tools must include `annotations` (readOnlyHint, destructiveHint, etc.)
67
+ - All tools must return `structuredContent` alongside text content
68
+ - Use `zod` for input/output schemas
69
+ - Tool names use snake_case (`get_portfolio`, not `getPortfolio`)
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CarbonCopyInc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Carbon Copy MCP Server
2
+
3
+ An [MCP](https://modelcontextprotocol.io) server that gives AI agents programmatic access to [Carbon Copy](https://carboncopy.news) — a Polymarket copy-trading platform.
4
+
5
+ ## Features
6
+
7
+ - **Portfolio Management** — View portfolio summary, positions, and trade history
8
+ - **Trader Operations** — Follow/unfollow traders, pause/resume copy trading, adjust settings
9
+ - **Order Tracking** — List and inspect copy trade orders with filtering
10
+ - **Account Info** — Access account details
11
+ - **Cursor Pagination** — Iterate through large datasets efficiently
12
+
13
+ ## Quick Start
14
+
15
+ ### Prerequisites
16
+
17
+ 1. A [Carbon Copy](https://carboncopy.news) account
18
+ 2. An API key (generate from the dashboard or via the [API](https://docs.carboncopy.news))
19
+
20
+ ### Usage with Claude Desktop
21
+
22
+ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
23
+
24
+ ```json
25
+ {
26
+ "mcpServers": {
27
+ "carboncopy": {
28
+ "command": "npx",
29
+ "args": ["-y", "@carbon-copy/mcp"],
30
+ "env": {
31
+ "CARBONCOPY_API_KEY": "cc_your_key_here"
32
+ }
33
+ }
34
+ }
35
+ }
36
+ ```
37
+
38
+ ### Usage with Cursor
39
+
40
+ Add to `.cursor/mcp.json` in your project:
41
+
42
+ ```json
43
+ {
44
+ "mcpServers": {
45
+ "carboncopy": {
46
+ "command": "npx",
47
+ "args": ["-y", "@carbon-copy/mcp"],
48
+ "env": {
49
+ "CARBONCOPY_API_KEY": "cc_your_key_here"
50
+ }
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ## Available Tools
57
+
58
+ | Tool | Description |
59
+ |---|---|
60
+ | `get_portfolio` | Portfolio summary (value, P&L, win rate) |
61
+ | `get_portfolio_history` | Paginated trade history with date filtering |
62
+ | `get_positions` | Open positions with pagination |
63
+ | `list_traders` | All followed traders with stats |
64
+ | `follow_trader` | Start following a trader |
65
+ | `get_trader` | Single trader details |
66
+ | `update_trader` | Update copy trading settings |
67
+ | `unfollow_trader` | Stop following a trader |
68
+ | `pause_trader` | Pause copy trading for a trader |
69
+ | `resume_trader` | Resume copy trading for a trader |
70
+ | `list_orders` | Paginated orders with status/date filters |
71
+ | `get_order` | Single order details |
72
+ | `get_account` | Account information |
73
+ | `health` | API health check |
74
+
75
+ ## Resources
76
+
77
+ | URI | Description |
78
+ |---|---|
79
+ | `carboncopy://portfolio` | Current portfolio snapshot |
80
+ | `carboncopy://traders` | List of followed traders |
81
+
82
+ ## Development
83
+
84
+ ```bash
85
+ npm install
86
+ npm run build
87
+ npm run dev # Watch mode
88
+ ```
89
+
90
+ ## Authentication
91
+
92
+ All tools use your `CARBONCOPY_API_KEY` (format: `cc_<64 hex chars>`). Generate one from the [Carbon Copy dashboard](https://carboncopy.news) or via the [Key Management API](https://docs.carboncopy.news/authentication).
93
+
94
+ API keys have scoped permissions (portfolio, traders, orders, markets, account). Tools will return permission errors if your key lacks the required scope.
95
+
96
+ ## Rate Limits
97
+
98
+ The underlying API enforces rate limits (60 reads/min, 20 writes/min). The MCP server surfaces rate limit errors transparently — retry after the indicated delay.
99
+
100
+ ## Links
101
+
102
+ - [Carbon Copy](https://carboncopy.news)
103
+ - [API Documentation](https://docs.carboncopy.news)
104
+ - [OpenAPI Spec](https://docs.carboncopy.news/api-reference/openapi.json)
105
+
106
+ ## License
107
+
108
+ MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,292 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { CarbonCopyClient } from "../client.js";
3
+ function createMockResponse(opts = {}) {
4
+ const { ok = true, status = 200, statusText = "OK", contentLength, body = null, bodyText = "", cloneJsonThrows = false, } = opts;
5
+ const headers = {};
6
+ if (contentLength !== undefined)
7
+ headers["content-length"] = contentLength;
8
+ const jsonFn = vi.fn().mockResolvedValue(body);
9
+ const textFn = vi.fn().mockResolvedValue(bodyText || (body !== null ? JSON.stringify(body) : ""));
10
+ // The clone is only used for error-path json parsing
11
+ const cloneJsonFn = cloneJsonThrows
12
+ ? vi.fn().mockRejectedValue(new Error("not json"))
13
+ : vi.fn().mockResolvedValue(body);
14
+ const clone = vi.fn().mockReturnValue({ json: cloneJsonFn });
15
+ return {
16
+ ok,
17
+ status,
18
+ statusText,
19
+ headers: { get: (name) => headers[name.toLowerCase()] ?? null },
20
+ json: jsonFn,
21
+ text: textFn,
22
+ clone,
23
+ };
24
+ }
25
+ const BASE = "https://carboncopy.news";
26
+ describe("CarbonCopyClient", () => {
27
+ let fetchMock;
28
+ let client;
29
+ beforeEach(() => {
30
+ fetchMock = vi.fn();
31
+ globalThis.fetch = fetchMock;
32
+ client = new CarbonCopyClient("cc_testkey");
33
+ });
34
+ afterEach(() => {
35
+ vi.restoreAllMocks();
36
+ });
37
+ // -------------------------------------------------------------------------
38
+ // Core request behaviour
39
+ // -------------------------------------------------------------------------
40
+ describe("request() — GET", () => {
41
+ it("sends correct URL and Authorization header, returns parsed JSON", async () => {
42
+ const data = { total: 42 };
43
+ fetchMock.mockResolvedValue(createMockResponse({ body: data }));
44
+ const result = await client.getPortfolio();
45
+ expect(fetchMock).toHaveBeenCalledOnce();
46
+ const [url, init] = fetchMock.mock.calls[0];
47
+ expect(url).toBe(`${BASE}/api/v1/portfolio`);
48
+ expect(init.headers["Authorization"]).toBe("Bearer cc_testkey");
49
+ expect(init.headers["Content-Type"]).toBe("application/json");
50
+ expect(init.method).toBe("GET");
51
+ expect(init.body).toBeUndefined();
52
+ expect(result).toEqual(data);
53
+ });
54
+ });
55
+ describe("request() — POST", () => {
56
+ it("serialises body to JSON and sends correct method", async () => {
57
+ const responseData = { id: "trader-1" };
58
+ fetchMock.mockResolvedValue(createMockResponse({ body: responseData }));
59
+ const payload = {
60
+ walletAddress: "0xabc",
61
+ copyPercentage: 50,
62
+ };
63
+ await client.followTrader(payload);
64
+ const [, init] = fetchMock.mock.calls[0];
65
+ expect(init.method).toBe("POST");
66
+ expect(init.body).toBe(JSON.stringify(payload));
67
+ });
68
+ });
69
+ describe("request() — error handling", () => {
70
+ it("throws an error including status and response body when response is not ok", async () => {
71
+ const errBody = { message: "Unauthorized" };
72
+ fetchMock.mockResolvedValue(createMockResponse({
73
+ ok: false,
74
+ status: 401,
75
+ statusText: "Unauthorized",
76
+ body: errBody,
77
+ }));
78
+ await expect(client.getPortfolio()).rejects.toThrow(/Carbon Copy API error 401 Unauthorized/);
79
+ await expect(client.getPortfolio()).rejects.toThrow(/Unauthorized/);
80
+ });
81
+ it("falls back to res.text() when cloned.json() fails on error response", async () => {
82
+ fetchMock.mockResolvedValue(createMockResponse({
83
+ ok: false,
84
+ status: 500,
85
+ statusText: "Internal Server Error",
86
+ bodyText: "raw error text",
87
+ cloneJsonThrows: true,
88
+ }));
89
+ await expect(client.getPortfolio()).rejects.toThrow(/raw error text/);
90
+ });
91
+ });
92
+ describe("request() — empty body handling", () => {
93
+ it("returns undefined for 204 No Content without calling res.json()", async () => {
94
+ const mock = createMockResponse({ status: 204 });
95
+ // ok defaults true but 204 has no body
96
+ fetchMock.mockResolvedValue({ ...mock, ok: true, status: 204 });
97
+ const result = await client.unfollowTrader("0xabc");
98
+ expect(result).toBeUndefined();
99
+ expect(mock.json).not.toHaveBeenCalled();
100
+ });
101
+ it("returns undefined when Content-Length is 0", async () => {
102
+ const mock = createMockResponse({ contentLength: "0" });
103
+ fetchMock.mockResolvedValue(mock);
104
+ const result = await client.pauseTrader("0xabc");
105
+ expect(result).toBeUndefined();
106
+ expect(mock.json).not.toHaveBeenCalled();
107
+ });
108
+ });
109
+ // -------------------------------------------------------------------------
110
+ // buildQuery (tested via endpoint methods)
111
+ // -------------------------------------------------------------------------
112
+ describe("buildQuery", () => {
113
+ it("appends query string for defined values", async () => {
114
+ fetchMock.mockResolvedValue(createMockResponse({ body: [] }));
115
+ await client.getPortfolioHistory({ limit: 10, cursor: "abc" });
116
+ const [url] = fetchMock.mock.calls[0];
117
+ expect(url).toContain("limit=10");
118
+ expect(url).toContain("cursor=abc");
119
+ });
120
+ it("omits undefined values from query string", async () => {
121
+ fetchMock.mockResolvedValue(createMockResponse({ body: [] }));
122
+ await client.getPortfolioHistory({ limit: 5 });
123
+ const [url] = fetchMock.mock.calls[0];
124
+ expect(url).toContain("limit=5");
125
+ expect(url).not.toContain("cursor");
126
+ expect(url).not.toContain("since");
127
+ expect(url).not.toContain("until");
128
+ });
129
+ it("omits query string entirely when params are all undefined", async () => {
130
+ fetchMock.mockResolvedValue(createMockResponse({ body: [] }));
131
+ await client.getPositions({});
132
+ const [url] = fetchMock.mock.calls[0];
133
+ expect(url).toBe(`${BASE}/api/v1/portfolio/positions`);
134
+ expect(url).not.toContain("?");
135
+ });
136
+ });
137
+ // -------------------------------------------------------------------------
138
+ // Endpoint methods — method + path
139
+ // -------------------------------------------------------------------------
140
+ describe("endpoint methods", () => {
141
+ beforeEach(() => {
142
+ fetchMock.mockResolvedValue(createMockResponse({ body: {} }));
143
+ });
144
+ it("getPortfolio() → GET /api/v1/portfolio", async () => {
145
+ await client.getPortfolio();
146
+ const [url, init] = fetchMock.mock.calls[0];
147
+ expect(url).toBe(`${BASE}/api/v1/portfolio`);
148
+ expect(init.method).toBe("GET");
149
+ });
150
+ it("getPortfolioHistory({limit:10, cursor:'abc'}) → GET /api/v1/portfolio/history?limit=10&cursor=abc", async () => {
151
+ await client.getPortfolioHistory({ limit: 10, cursor: "abc" });
152
+ const [url, init] = fetchMock.mock.calls[0];
153
+ expect(url).toBe(`${BASE}/api/v1/portfolio/history?limit=10&cursor=abc`);
154
+ expect(init.method).toBe("GET");
155
+ });
156
+ it("getPositions() → GET /api/v1/portfolio/positions", async () => {
157
+ await client.getPositions();
158
+ const [url, init] = fetchMock.mock.calls[0];
159
+ expect(url).toBe(`${BASE}/api/v1/portfolio/positions`);
160
+ expect(init.method).toBe("GET");
161
+ });
162
+ it("getTraders() → GET /api/v1/traders", async () => {
163
+ await client.getTraders();
164
+ const [url, init] = fetchMock.mock.calls[0];
165
+ expect(url).toBe(`${BASE}/api/v1/traders`);
166
+ expect(init.method).toBe("GET");
167
+ });
168
+ it("followTrader({...}) → POST /api/v1/traders with body", async () => {
169
+ const body = {
170
+ walletAddress: "0xabc",
171
+ copyPercentage: 50,
172
+ maxCopyAmount: 100,
173
+ notificationsEnabled: true,
174
+ };
175
+ await client.followTrader(body);
176
+ const [url, init] = fetchMock.mock.calls[0];
177
+ expect(url).toBe(`${BASE}/api/v1/traders`);
178
+ expect(init.method).toBe("POST");
179
+ expect(JSON.parse(init.body)).toEqual(body);
180
+ });
181
+ it("getTrader('0xabc') → GET /api/v1/traders/0xabc", async () => {
182
+ await client.getTrader("0xabc");
183
+ const [url, init] = fetchMock.mock.calls[0];
184
+ expect(url).toBe(`${BASE}/api/v1/traders/0xabc`);
185
+ expect(init.method).toBe("GET");
186
+ });
187
+ it("updateTrader('0xabc', {...}) → PATCH /api/v1/traders/0xabc with body", async () => {
188
+ const body = { copyPercentage: 75, copyTradingEnabled: false };
189
+ await client.updateTrader("0xabc", body);
190
+ const [url, init] = fetchMock.mock.calls[0];
191
+ expect(url).toBe(`${BASE}/api/v1/traders/0xabc`);
192
+ expect(init.method).toBe("PATCH");
193
+ expect(JSON.parse(init.body)).toEqual(body);
194
+ });
195
+ it("unfollowTrader('0xabc') → DELETE /api/v1/traders/0xabc", async () => {
196
+ fetchMock.mockResolvedValue(createMockResponse({ status: 204, ok: true }));
197
+ await client.unfollowTrader("0xabc");
198
+ const [url, init] = fetchMock.mock.calls[0];
199
+ expect(url).toBe(`${BASE}/api/v1/traders/0xabc`);
200
+ expect(init.method).toBe("DELETE");
201
+ });
202
+ it("pauseTrader('0xabc') → POST /api/v1/traders/0xabc/pause", async () => {
203
+ await client.pauseTrader("0xabc");
204
+ const [url, init] = fetchMock.mock.calls[0];
205
+ expect(url).toBe(`${BASE}/api/v1/traders/0xabc/pause`);
206
+ expect(init.method).toBe("POST");
207
+ });
208
+ it("resumeTrader('0xabc') → POST /api/v1/traders/0xabc/resume", async () => {
209
+ await client.resumeTrader("0xabc");
210
+ const [url, init] = fetchMock.mock.calls[0];
211
+ expect(url).toBe(`${BASE}/api/v1/traders/0xabc/resume`);
212
+ expect(init.method).toBe("POST");
213
+ });
214
+ it("getOrders({status:'filled'}) → GET /api/v1/orders?status=filled", async () => {
215
+ await client.getOrders({ status: "filled" });
216
+ const [url, init] = fetchMock.mock.calls[0];
217
+ expect(url).toBe(`${BASE}/api/v1/orders?status=filled`);
218
+ expect(init.method).toBe("GET");
219
+ });
220
+ it("getOrder('id123') → GET /api/v1/orders/id123", async () => {
221
+ await client.getOrder("id123");
222
+ const [url, init] = fetchMock.mock.calls[0];
223
+ expect(url).toBe(`${BASE}/api/v1/orders/id123`);
224
+ expect(init.method).toBe("GET");
225
+ });
226
+ it("getAccount() → GET /api/v1/account", async () => {
227
+ await client.getAccount();
228
+ const [url, init] = fetchMock.mock.calls[0];
229
+ expect(url).toBe(`${BASE}/api/v1/account`);
230
+ expect(init.method).toBe("GET");
231
+ });
232
+ it("health() → GET /api/v1/health", async () => {
233
+ await client.health();
234
+ const [url, init] = fetchMock.mock.calls[0];
235
+ expect(url).toBe(`${BASE}/api/v1/health`);
236
+ expect(init.method).toBe("GET");
237
+ });
238
+ });
239
+ // -------------------------------------------------------------------------
240
+ // URL encoding
241
+ // -------------------------------------------------------------------------
242
+ describe("URL encoding", () => {
243
+ beforeEach(() => {
244
+ fetchMock.mockResolvedValue(createMockResponse({ body: {} }));
245
+ });
246
+ it("encodes wallet addresses with special characters in path", async () => {
247
+ const wallet = "0xabc/def?foo=bar&baz=qux";
248
+ await client.getTrader(wallet);
249
+ const [url] = fetchMock.mock.calls[0];
250
+ expect(url).toContain(encodeURIComponent(wallet));
251
+ expect(url).not.toContain("?foo=bar");
252
+ });
253
+ it("encodes order IDs with special characters", async () => {
254
+ const id = "order/id?test=1";
255
+ await client.getOrder(id);
256
+ const [url] = fetchMock.mock.calls[0];
257
+ expect(url).toContain(encodeURIComponent(id));
258
+ });
259
+ it("encodes wallet addresses for updateTrader", async () => {
260
+ const wallet = "0xabc def";
261
+ await client.updateTrader(wallet, { copyPercentage: 10 });
262
+ const [url] = fetchMock.mock.calls[0];
263
+ expect(url).toContain(encodeURIComponent(wallet));
264
+ expect(url).toBe(`${BASE}/api/v1/traders/${encodeURIComponent(wallet)}`);
265
+ });
266
+ it("encodes wallet addresses for unfollowTrader", async () => {
267
+ const wallet = "0xabc def";
268
+ fetchMock.mockResolvedValue(createMockResponse({ status: 204, ok: true }));
269
+ await client.unfollowTrader(wallet);
270
+ const [url] = fetchMock.mock.calls[0];
271
+ expect(url).toBe(`${BASE}/api/v1/traders/${encodeURIComponent(wallet)}`);
272
+ });
273
+ it("encodes wallet addresses for pauseTrader", async () => {
274
+ const wallet = "0xabc def";
275
+ await client.pauseTrader(wallet);
276
+ const [url] = fetchMock.mock.calls[0];
277
+ expect(url).toBe(`${BASE}/api/v1/traders/${encodeURIComponent(wallet)}/pause`);
278
+ });
279
+ it("encodes wallet addresses for resumeTrader", async () => {
280
+ const wallet = "0xabc def";
281
+ await client.resumeTrader(wallet);
282
+ const [url] = fetchMock.mock.calls[0];
283
+ expect(url).toBe(`${BASE}/api/v1/traders/${encodeURIComponent(wallet)}/resume`);
284
+ });
285
+ it("encodes query string values correctly", async () => {
286
+ await client.getPortfolioHistory({ cursor: "abc=def&ghi" });
287
+ const [url] = fetchMock.mock.calls[0];
288
+ expect(url).toContain("cursor=abc%3Ddef%26ghi");
289
+ });
290
+ });
291
+ });
292
+ //# sourceMappingURL=client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=resources.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/resources.test.ts"],"names":[],"mappings":""}