@0xinsider/mcp 1.3.1 → 2.0.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 (53) hide show
  1. package/README.md +91 -0
  2. package/dist/cli-lib.d.ts.map +1 -1
  3. package/dist/cli-lib.js +9 -5
  4. package/dist/cli-lib.js.map +1 -1
  5. package/dist/cli.js +6 -1
  6. package/dist/cli.js.map +1 -1
  7. package/dist/constants.d.ts +1 -1
  8. package/dist/constants.js +1 -1
  9. package/dist/product-cli/errors.d.ts +7 -0
  10. package/dist/product-cli/errors.d.ts.map +1 -0
  11. package/dist/product-cli/errors.js +13 -0
  12. package/dist/product-cli/errors.js.map +1 -0
  13. package/dist/product-cli/index.d.ts +4 -0
  14. package/dist/product-cli/index.d.ts.map +1 -0
  15. package/dist/product-cli/index.js +372 -0
  16. package/dist/product-cli/index.js.map +1 -0
  17. package/dist/product-cli/oauth.d.ts +10 -0
  18. package/dist/product-cli/oauth.d.ts.map +1 -0
  19. package/dist/product-cli/oauth.js +245 -0
  20. package/dist/product-cli/oauth.js.map +1 -0
  21. package/dist/product-cli/storage.d.ts +20 -0
  22. package/dist/product-cli/storage.d.ts.map +1 -0
  23. package/dist/product-cli/storage.js +149 -0
  24. package/dist/product-cli/storage.js.map +1 -0
  25. package/dist/sdk/client.d.ts +765 -0
  26. package/dist/sdk/client.d.ts.map +1 -0
  27. package/dist/sdk/client.js +974 -0
  28. package/dist/sdk/client.js.map +1 -0
  29. package/dist/sdk/errors.d.ts +313 -0
  30. package/dist/sdk/errors.d.ts.map +1 -0
  31. package/dist/sdk/errors.js +521 -0
  32. package/dist/sdk/errors.js.map +1 -0
  33. package/dist/sdk/index.d.ts +26 -0
  34. package/dist/sdk/index.d.ts.map +1 -0
  35. package/dist/sdk/index.js +25 -0
  36. package/dist/sdk/index.js.map +1 -0
  37. package/dist/sdk/pagination.d.ts +76 -0
  38. package/dist/sdk/pagination.d.ts.map +1 -0
  39. package/dist/sdk/pagination.js +106 -0
  40. package/dist/sdk/pagination.js.map +1 -0
  41. package/dist/sdk/schema.d.ts +2372 -0
  42. package/dist/sdk/schema.d.ts.map +1 -0
  43. package/dist/sdk/schema.js +7 -0
  44. package/dist/sdk/schema.js.map +1 -0
  45. package/dist/sdk/stream.d.ts +182 -0
  46. package/dist/sdk/stream.d.ts.map +1 -0
  47. package/dist/sdk/stream.js +391 -0
  48. package/dist/sdk/stream.js.map +1 -0
  49. package/dist/sdk/webhooks.d.ts +163 -0
  50. package/dist/sdk/webhooks.d.ts.map +1 -0
  51. package/dist/sdk/webhooks.js +122 -0
  52. package/dist/sdk/webhooks.js.map +1 -0
  53. package/package.json +6 -3
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Webhook signature verification and typed delivery payloads.
3
+ *
4
+ * The backend signs every webhook delivery exactly like this (source of truth:
5
+ * `backend/src/api_v1/handlers/webhooks/endpoint_security.rs::sign_webhook_payload`):
6
+ *
7
+ * signature = "v1=" + hex( HMAC_SHA256( signing_secret, `${timestamp}.${raw_body}` ) )
8
+ *
9
+ * It is sent on two headers:
10
+ * - `x-0xinsider-timestamp: <unix-seconds>`
11
+ * - `x-0xinsider-signature: v1=<hex>` (may be a comma-separated list)
12
+ *
13
+ * Verification, the receiver side. The backend only signs; the published
14
+ * recipe is the delivery-signing paragraph on POST /api/v1/webhooks in
15
+ * `web/public/api/v1/openapi.json`:
16
+ * 1. Reject if `|now - timestamp| > 300` seconds (replay tolerance).
17
+ * 2. Recompute the expected `v1=<hex>` over `${timestamp}.${rawBody}`.
18
+ * 3. Constant-time compare against each candidate in the header.
19
+ *
20
+ * `rawBody` MUST be the exact bytes received: verify before JSON parsing, since
21
+ * re-serializing changes whitespace/key order and breaks the HMAC.
22
+ *
23
+ * ENDPOINT ACTIVATION (`verifyWebhook`, `POST /api/v1/webhooks/{id}/verify`):
24
+ * the one-time `verification.token` is necessary but not sufficient. That call
25
+ * POSTs a challenge to your webhook url and activates the endpoint only if you
26
+ * answer 2xx within 10 seconds. The challenge body is
27
+ * `{ "type": "webhook.verification", "token": "<verification_token>",
28
+ * "webhook_id": <id> }`, it carries `x-0xinsider-event-type:
29
+ * webhook.verification`, and it is signed with the endpoint's `signing_secret`
30
+ * exactly like a delivery -- so `verifySignature` below validates it unchanged.
31
+ * The challenge follows no redirects and never reads your response body. A
32
+ * non-2xx answer, no answer inside 10 seconds, or a url that does not resolve to
33
+ * a publicly routable address returns 422 and leaves the endpoint
34
+ * `pending_verification`.
35
+ */
36
+ import { createHmac, timingSafeEqual } from "node:crypto";
37
+ /** Default replay tolerance; the published contract is 300 seconds. */
38
+ export const SIGNATURE_TOLERANCE_SECONDS = 300;
39
+ /** Header carrying the `v1=<hex>` signature. */
40
+ export const SIGNATURE_HEADER = "x-0xinsider-signature";
41
+ /** Header carrying the unix-seconds signing timestamp. */
42
+ export const TIMESTAMP_HEADER = "x-0xinsider-timestamp";
43
+ /**
44
+ * Recompute the canonical signature for a payload. Returns `v1=<hex>`.
45
+ * Exposed so callers can sign in tests; matches the backend byte-for-byte.
46
+ */
47
+ export function computeSignature(secret, timestamp, body) {
48
+ const hmac = createHmac("sha256", secret);
49
+ hmac.update(String(timestamp));
50
+ hmac.update(".");
51
+ hmac.update(typeof body === "string" ? Buffer.from(body, "utf-8") : body);
52
+ return `v1=${hmac.digest("hex")}`;
53
+ }
54
+ /**
55
+ * Verify a webhook signature. Returns `true` only when the timestamp is within
56
+ * tolerance AND a candidate signature constant-time-matches the recomputed one.
57
+ * Never throws on a bad signature; throws only on a missing/empty secret.
58
+ */
59
+ export function verifySignature(input) {
60
+ if (!input.secret) {
61
+ throw new Error("verifySignature requires a non-empty signing secret");
62
+ }
63
+ const tolerance = input.toleranceSeconds ?? SIGNATURE_TOLERANCE_SECONDS;
64
+ const now = input.nowSeconds ?? Math.floor(Date.now() / 1000);
65
+ // Guard a caller-injected non-finite `now` (e.g. NaN): a non-finite reference
66
+ // time would make `Math.abs(now - ts) > tolerance` false and silently skip the
67
+ // replay-window check, so reject outright rather than verify on the HMAC alone.
68
+ if (!Number.isFinite(now)) {
69
+ return false;
70
+ }
71
+ const ts = Number(input.timestamp);
72
+ if (!Number.isFinite(ts)) {
73
+ return false;
74
+ }
75
+ if (Math.abs(now - ts) > tolerance) {
76
+ return false;
77
+ }
78
+ const expected = computeSignature(input.secret, ts, input.body);
79
+ const expectedBuf = Buffer.from(expected, "utf-8");
80
+ // The header may carry multiple comma-separated candidate signatures.
81
+ return input.signature
82
+ .split(",")
83
+ .map((part) => part.trim())
84
+ .some((candidate) => constantTimeEqual(candidate, expectedBuf));
85
+ }
86
+ function constantTimeEqual(candidate, expected) {
87
+ const candidateBuf = Buffer.from(candidate, "utf-8");
88
+ // timingSafeEqual throws on length mismatch; the length check itself is not
89
+ // secret (signature length is public), so guard first.
90
+ if (candidateBuf.length !== expected.length) {
91
+ return false;
92
+ }
93
+ return timingSafeEqual(candidateBuf, expected);
94
+ }
95
+ // --- Typed webhook payloads ---
96
+ /**
97
+ * Webhook event types. Source of truth:
98
+ * `web/public/api/v1/openapi.json` -> components.schemas.WebhookEventType.enum.
99
+ * `whale_trades_inserted`, `wallet_grade_changed`, `insider_radar_flag_raised`,
100
+ * and `smart_money_flow_detected` are Pro-only: they deliver only to API keys
101
+ * on an active Pro subscription.
102
+ */
103
+ export const WEBHOOK_EVENT_TYPES = [
104
+ "whale_trades_inserted",
105
+ "live_sports_updated",
106
+ "whale_trader_synced",
107
+ "large_positions_updated",
108
+ "wallet_grade_changed",
109
+ "insider_radar_flag_raised",
110
+ // Pro-only; present in the OpenAPI WebhookEventType enum + backend
111
+ // allowlist but previously missing here (drift fix, #6915). The wire
112
+ // identifier stays `smart_money_flow_detected` (frozen event name).
113
+ "smart_money_flow_detected",
114
+ ];
115
+ /**
116
+ * Parse a verified raw body into the typed delivery envelope. Call only AFTER
117
+ * `verifySignature` passes (parsing first would let an unverified payload in).
118
+ */
119
+ export function parseWebhookEvent(body) {
120
+ return JSON.parse(body);
121
+ }
122
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../sdk/src/webhooks.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xinsider/mcp",
3
- "version": "1.3.1",
3
+ "version": "2.0.0",
4
4
  "mcpName": "io.github.0xinsider/mcp",
5
5
  "description": "Official 0xinsider CLI and MCP server: advanced tools for sports and esports markets, powered by Polymarket",
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "start": "node dist/index.js",
14
14
  "dev": "tsx watch src/index.ts",
15
15
  "prebuild": "node scripts/generate-version.mjs",
16
- "build": "tsc",
16
+ "build": "tsc -p tsconfig.sdk.json && tsc",
17
17
  "generate:catalog": "node ../scripts/generate-mcp-catalog.mjs",
18
18
  "catalog:parity": "node ../scripts/mcp-catalog-parity.mjs",
19
19
  "test": "tsx --test tests/**/*.test.ts",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "homepage": "https://0xinsider.com/developers",
49
49
  "engines": {
50
- "node": ">=18"
50
+ "node": ">=22"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public"
@@ -65,5 +65,8 @@
65
65
  "semver": "^7.8.5",
66
66
  "tsx": "^4.23.13",
67
67
  "typescript": "^7.0.2"
68
+ },
69
+ "imports": {
70
+ "#sdk": "./dist/sdk/index.js"
68
71
  }
69
72
  }