@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.
- package/.github/workflows/publish.yml +23 -0
- package/CLAUDE.md +69 -0
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/dist/__tests__/client.test.d.ts +2 -0
- package/dist/__tests__/client.test.d.ts.map +1 -0
- package/dist/__tests__/client.test.js +292 -0
- package/dist/__tests__/client.test.js.map +1 -0
- package/dist/__tests__/resources.test.d.ts +2 -0
- package/dist/__tests__/resources.test.d.ts.map +1 -0
- package/dist/__tests__/resources.test.js +176 -0
- package/dist/__tests__/resources.test.js.map +1 -0
- package/dist/__tests__/tools.test.d.ts +2 -0
- package/dist/__tests__/tools.test.d.ts.map +1 -0
- package/dist/__tests__/tools.test.js +317 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/client.d.ts +46 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +94 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/portfolio.d.ts +4 -0
- package/dist/resources/portfolio.d.ts.map +1 -0
- package/dist/resources/portfolio.js +19 -0
- package/dist/resources/portfolio.js.map +1 -0
- package/dist/resources/traders.d.ts +4 -0
- package/dist/resources/traders.d.ts.map +1 -0
- package/dist/resources/traders.js +19 -0
- package/dist/resources/traders.js.map +1 -0
- package/dist/tools/account.d.ts +4 -0
- package/dist/tools/account.d.ts.map +1 -0
- package/dist/tools/account.js +32 -0
- package/dist/tools/account.js.map +1 -0
- package/dist/tools/orders.d.ts +4 -0
- package/dist/tools/orders.d.ts.map +1 -0
- package/dist/tools/orders.js +57 -0
- package/dist/tools/orders.js.map +1 -0
- package/dist/tools/portfolio.d.ts +4 -0
- package/dist/tools/portfolio.d.ts.map +1 -0
- package/dist/tools/portfolio.js +84 -0
- package/dist/tools/portfolio.js.map +1 -0
- package/dist/tools/traders.d.ts +4 -0
- package/dist/tools/traders.d.ts.map +1 -0
- package/dist/tools/traders.js +163 -0
- package/dist/tools/traders.js.map +1 -0
- package/package.json +43 -0
- package/src/__tests__/client.test.ts +392 -0
- package/src/__tests__/resources.test.ts +263 -0
- package/src/__tests__/tools.test.ts +440 -0
- package/src/client.ts +161 -0
- package/src/index.ts +41 -0
- package/src/resources/portfolio.ts +30 -0
- package/src/resources/traders.ts +29 -0
- package/src/tools/account.ts +48 -0
- package/src/tools/orders.ts +74 -0
- package/src/tools/portfolio.ts +106 -0
- package/src/tools/traders.ts +207 -0
- package/tsconfig.json +17 -0
- 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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"resources.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/resources.test.ts"],"names":[],"mappings":""}
|