@cryptodetective/sdk 0.0.0-stage → 1.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.
package/README.md CHANGED
@@ -1,3 +1,371 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # Crypto Detective Node.js / TypeScript SDK
2
+
3
+ Official server-side Node.js and TypeScript SDK for the Crypto Detective Investigation API.
4
+
5
+
6
+
7
+
8
+
9
+
10
+ ## Overview
11
+
12
+ The Crypto Detective SDK provides a typed server-side interface to the Crypto Detective REST API.
13
+
14
+ It allows applications to submit blockchain addresses for investigation and receive the canonical Crypto Detective investigation response, including:
15
+
16
+ - Final Risk Score
17
+ - Risk level
18
+ - Address validity
19
+ - Classification
20
+ - Hard-stop status
21
+ - Final score source
22
+ - Extended intelligence returned by the Crypto Detective API
23
+
24
+ The SDK does not calculate or reconstruct Crypto Detective risk scores. The authoritative Final Risk Score is returned by the Crypto Detective API as `scan.score`.
25
+
26
+
27
+
28
+
29
+
30
+ ## Requirements
31
+
32
+ - Node.js 18 or later
33
+ - Active Crypto Detective API subscription
34
+ - Crypto Detective API key
35
+
36
+
37
+
38
+
39
+
40
+ ## Installation
41
+
42
+ Install the Crypto Detective SDK in your server-side Node.js application:
43
+
44
+ ```bash
45
+ npm install @cryptodetective/sdk
46
+ ```
47
+
48
+ The SDK requires Node.js 18 or later.
49
+
50
+ After installation, import the client:
51
+
52
+ ```ts
53
+ import { CryptoDetectiveClient } from "@cryptodetective/sdk";
54
+ ```
55
+
56
+ For CommonJS applications:
57
+
58
+ ```js
59
+ const {
60
+ CryptoDetectiveClient,
61
+ CryptoDetectiveError,
62
+ } = require("@cryptodetective/sdk");
63
+ ```
64
+
65
+
66
+
67
+
68
+ ## Security
69
+
70
+ The Crypto Detective API key is a server-side credential.
71
+
72
+ Do not expose the API key in:
73
+
74
+ - Browser JavaScript
75
+ - Client-side React or Next.js components
76
+ - Public repositories
77
+ - Mobile application bundles
78
+ - HTML source
79
+
80
+ Store the API key in a secure server-side environment variable or secrets-management system.
81
+
82
+
83
+
84
+
85
+
86
+ ## Configuration
87
+
88
+ Create the Crypto Detective client with your server-side API key:
89
+
90
+ ```ts
91
+ import { CryptoDetectiveClient } from "@cryptodetective/sdk";
92
+
93
+ const client = new CryptoDetectiveClient({
94
+ apiKey: process.env.CRYPTO_DETECTIVE_API_KEY!,
95
+ });
96
+ ```
97
+
98
+ The SDK connects to the production Crypto Detective API by default.
99
+
100
+ For specialized environments, the API base URL can be overridden:
101
+
102
+ ```ts
103
+ const client = new CryptoDetectiveClient({
104
+ apiKey: process.env.CRYPTO_DETECTIVE_API_KEY!,
105
+ baseUrl: "https://cryptodetective.app/api/v1",
106
+ });
107
+ ```
108
+
109
+ For normal production integrations, the default base URL should be used.
110
+
111
+ Store the API key in a server-side environment variable or secrets-management system. Never send the API key to the browser.
112
+
113
+
114
+
115
+
116
+ ## Investigation Request
117
+
118
+ Submit an investigation with `client.investigate()`:
119
+
120
+ ```ts
121
+ const result = await client.investigate({
122
+ address: "0x000000000000000000000000000000000000dEaD",
123
+ chainSelected: "eth",
124
+ scanMode: "full",
125
+ });
126
+ ```
127
+
128
+
129
+
130
+
131
+
132
+ ### Request Fields
133
+
134
+ | Field | Required | Description |
135
+ |---|---|---|
136
+ | `address` | Yes | Blockchain address to investigate. |
137
+ | `chainSelected` | Yes | Blockchain network to use for the investigation. |
138
+ | `scanMode` | No | `"quick"` or `"full"`. Defaults to `"full"`. |
139
+ | `assetSymbol` | No | Optional asset symbol. |
140
+ | `calldata` | No | Optional transaction calldata for applicable investigations. |
141
+ | `spender` | No | Optional spender address for applicable investigations. |
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+ ### Supported Chains
151
+
152
+ The SDK currently accepts:
153
+
154
+ `auto`, `btc`, `eth`, `bsc`, `base`, `polygon`, `arbitrum`, `optimism`, `avalanche`, `tron`, `sol`, `ada`, `ltc`, `doge`, `xrp`, `bch`, `bnb`, `atom`
155
+
156
+ Use the exact lowercase chain identifier shown above.
157
+
158
+
159
+
160
+
161
+ ## Investigation Response
162
+
163
+ A successful investigation returns the canonical Crypto Detective API response:
164
+
165
+ ```ts
166
+ const result = await client.investigate({
167
+ address: "0x000000000000000000000000000000000000dEaD",
168
+ chainSelected: "eth",
169
+ scanMode: "full",
170
+ });
171
+
172
+ console.log(result.scan.score);
173
+ console.log(result.scan.risk_level);
174
+ console.log(result.scan.hard_stop_triggered);
175
+ console.log(result.scan.score_breakdown.final_score_source);
176
+ ```
177
+
178
+
179
+
180
+ ## Error Handling
181
+
182
+ The SDK throws `CryptoDetectiveError` when the Crypto Detective API returns an error.
183
+
184
+ ```ts
185
+ import {
186
+ CryptoDetectiveClient,
187
+ CryptoDetectiveError,
188
+ } from "@cryptodetective/sdk";
189
+
190
+ try {
191
+ const result = await client.investigate({
192
+ address: "0x...",
193
+ chainSelected: "eth",
194
+ scanMode: "full",
195
+ });
196
+
197
+ console.log(result.scan.score);
198
+ } catch (error) {
199
+ if (error instanceof CryptoDetectiveError) {
200
+ console.error("HTTP Status:", error.status);
201
+ console.error("Error Code:", error.code);
202
+ console.error("Message:", error.message);
203
+ } else {
204
+ throw error;
205
+ }
206
+ }
207
+ ```
208
+
209
+ Applications should make programmatic decisions using the HTTP status and `error.code`. Do not depend on exact error-message wording.
210
+
211
+ Common HTTP statuses include:
212
+
213
+ | Status | Meaning |
214
+ |---:|---|
215
+ | `400` | Invalid request JSON or invalid idempotency key. |
216
+ | `401` | Missing or invalid API authentication. |
217
+ | `403` | API subscription or entitlement required. |
218
+ | `405` | HTTP method not allowed. |
219
+ | `409` | Idempotency conflict or request already in progress. |
220
+ | `422` | Request validation failed. |
221
+ | `429` | Rate limit or monthly quota reached. |
222
+ | `500` | Investigation or accounting failure. |
223
+ | `503` | Required API service or production dependency unavailable. |
224
+
225
+ A failed API request should not be interpreted as a successful low-risk investigation. The integrating application determines the appropriate failure policy for its own workflow.
226
+
227
+
228
+
229
+
230
+ ## Idempotency
231
+
232
+ Crypto Detective supports optional idempotency keys for investigation requests.
233
+
234
+ Use an idempotency key when your application may retry the same investigation and you want to prevent duplicate processing:
235
+
236
+ ```ts
237
+ const result = await client.investigate(
238
+ {
239
+ address: "0x000000000000000000000000000000000000dEaD",
240
+ chainSelected: "eth",
241
+ scanMode: "full",
242
+ },
243
+ {
244
+ idempotencyKey: "investigation-12345",
245
+ }
246
+ );
247
+ ```
248
+
249
+ Idempotency keys:
250
+
251
+ - Are optional.
252
+ - May contain a maximum of 128 characters.
253
+ - May contain letters, numbers, `.`, `_`, `:`, and `-`.
254
+ - Should identify one logical investigation request.
255
+
256
+ Reusing the same idempotency key with the same request allows the API to return the completed result without performing the investigation again.
257
+
258
+ Reusing the same idempotency key with different request data results in an idempotency conflict.
259
+
260
+ If an investigation using the same key is still being processed, the API may return a conflict indicating that the request is already in progress.
261
+
262
+
263
+
264
+ ## Production Security and Integration Model
265
+
266
+ The Crypto Detective SDK is designed for server-side use.
267
+
268
+ A typical production integration follows this pattern:
269
+
270
+ ```text
271
+ User / Browser / Application
272
+ ↓
273
+ Customer Backend
274
+ ↓
275
+ Crypto Detective SDK
276
+ ↓
277
+ Crypto Detective REST API
278
+ ↓
279
+ Canonical Investigation Response
280
+ ↓
281
+ Customer Application Policy
282
+ ```
283
+
284
+ The customer's backend should submit the public blockchain address and investigation parameters to Crypto Detective. The Crypto Detective API returns the investigation result, and the customer application determines how that intelligence is used within its own workflow.
285
+
286
+ ### Security Requirements
287
+
288
+ - Keep Crypto Detective API keys on the server.
289
+ - Never expose API keys in browser JavaScript or client-side application bundles.
290
+ - Never commit API keys to source control.
291
+ - Use environment variables or a secure secrets-management system.
292
+ - Crypto Detective investigations require public blockchain information only.
293
+ - Never send private keys, wallet seed phrases, recovery phrases, or signing credentials to Crypto Detective.
294
+ - Treat API authentication credentials as secrets and rotate them if exposure is suspected.
295
+
296
+ ### Application Responsibility
297
+
298
+ Crypto Detective provides investigation and risk intelligence. It does not control the integrating application's business rules.
299
+
300
+ Applications may use Crypto Detective results to support workflows such as transaction review, risk warnings, compliance processes, fraud prevention, or other application-specific decisions.
301
+
302
+ The authoritative investigation result comes from the Crypto Detective API. Applications should not recreate Crypto Detective scoring logic locally.
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+ ### Core Response Fields
312
+
313
+ | Field | Description |
314
+ |---|---|
315
+ | `scan.id` | Unique investigation identifier. |
316
+ | `scan.address` | Address that was investigated. |
317
+ | `scan.chain_selected` | Blockchain network used for the investigation. |
318
+ | `scan.asset_symbol` | Asset symbol associated with the investigation. |
319
+ | `scan.scan_type` | Investigation mode used. |
320
+ | `scan.scanned_at` | Investigation timestamp. |
321
+ | `scan.validity` | Address validity intelligence. |
322
+ | `scan.classification` | Address classification intelligence. |
323
+ | `scan.score` | Authoritative Crypto Detective Final Risk Score from 0–100. |
324
+ | `scan.risk_level` | `low`, `caution`, `high`, or `critical`. |
325
+ | `scan.hard_stop_triggered` | Indicates whether a Crypto Detective hard stop was triggered. |
326
+ | `scan.hard_stop_code` | Hard-stop code when applicable. |
327
+ | `scan.hard_stop_title` | Hard-stop title when applicable. |
328
+ | `scan.hard_stop_message` | Hard-stop explanation when applicable. |
329
+ | `scan.score_breakdown.final_score_source` | Identifies the source of the final score. |
330
+
331
+ Crypto Detective API v1 may return additional intelligence fields. Applications should tolerate additive response fields rather than rejecting an otherwise valid response.
332
+
333
+
334
+
335
+
336
+
337
+
338
+ ### Risk Levels
339
+
340
+ | Final Risk Score | Risk Level |
341
+ |---:|---|
342
+ | `0` to `<30` | `low` |
343
+ | `30` to `<60` | `caution` |
344
+ | `60` to `<80` | `high` |
345
+ | `80` to `100` | `critical` |
346
+
347
+ A `critical` result does not necessarily mean that a hard stop was triggered. Check `scan.hard_stop_triggered` when your application needs to distinguish a hard-stop result from another critical-risk result.
348
+
349
+
350
+
351
+
352
+
353
+
354
+ ## Basic Usage
355
+
356
+ ```ts
357
+ import { CryptoDetectiveClient } from "@cryptodetective/sdk";
358
+
359
+ const client = new CryptoDetectiveClient({
360
+ apiKey: process.env.CRYPTO_DETECTIVE_API_KEY!,
361
+ });
362
+
363
+ const result = await client.investigate({
364
+ address: "0x...",
365
+ chainSelected: "eth",
366
+ scanMode: "full",
367
+ });
368
+
369
+ console.log(result.scan.score);
370
+ console.log(result.scan.risk_level);
371
+ console.log(result.scan.hard_stop_triggered);
@@ -0,0 +1,23 @@
1
+ import { InvestigationRequest, InvestigationResponse } from "./types";
2
+ export interface CryptoDetectiveClientOptions {
3
+ apiKey: string;
4
+ /**
5
+ * Override only when necessary.
6
+ * Defaults to the production Crypto Detective API.
7
+ */
8
+ baseUrl?: string;
9
+ }
10
+ export interface InvestigationOptions {
11
+ /**
12
+ * Optional idempotency key.
13
+ * Maximum 128 characters.
14
+ */
15
+ idempotencyKey?: string;
16
+ }
17
+ export declare class CryptoDetectiveClient {
18
+ private readonly apiKey;
19
+ private readonly baseUrl;
20
+ constructor(options: CryptoDetectiveClientOptions);
21
+ investigate(request: InvestigationRequest, options?: InvestigationOptions): Promise<InvestigationResponse>;
22
+ }
23
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAIjB,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,4BAA4B;IAa3C,WAAW,CACf,OAAO,EAAE,oBAAoB,EAC7B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,qBAAqB,CAAC;CAgElC"}
package/dist/client.js ADDED
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CryptoDetectiveClient = void 0;
4
+ const errors_1 = require("./errors");
5
+ class CryptoDetectiveClient {
6
+ apiKey;
7
+ baseUrl;
8
+ constructor(options) {
9
+ if (!options.apiKey || !options.apiKey.trim()) {
10
+ throw new Error("Crypto Detective API key is required.");
11
+ }
12
+ this.apiKey = options.apiKey.trim();
13
+ this.baseUrl = (options.baseUrl ??
14
+ "https://cryptodetective.app/api/v1").replace(/\/+$/, "");
15
+ }
16
+ async investigate(request, options = {}) {
17
+ const headers = {
18
+ Authorization: `Bearer ${this.apiKey}`,
19
+ "Content-Type": "application/json",
20
+ Accept: "application/json",
21
+ };
22
+ if (options.idempotencyKey) {
23
+ headers["Idempotency-Key"] = options.idempotencyKey;
24
+ }
25
+ const response = await fetch(`${this.baseUrl}/investigations.php`, {
26
+ method: "POST",
27
+ headers,
28
+ body: JSON.stringify({
29
+ address: request.address,
30
+ chain_selected: request.chainSelected,
31
+ scan_mode: request.scanMode ?? "full",
32
+ asset_symbol: request.assetSymbol ?? "",
33
+ calldata: request.calldata ?? "",
34
+ spender: request.spender ?? "",
35
+ }),
36
+ });
37
+ let body;
38
+ try {
39
+ body = await response.json();
40
+ }
41
+ catch {
42
+ throw new errors_1.CryptoDetectiveError(response.status, "INVALID_API_RESPONSE", "Crypto Detective returned an invalid JSON response.");
43
+ }
44
+ if (!response.ok) {
45
+ const errorBody = body;
46
+ if (errorBody &&
47
+ errorBody.success === false &&
48
+ errorBody.error &&
49
+ typeof errorBody.error.code === "string" &&
50
+ typeof errorBody.error.message === "string") {
51
+ throw errors_1.CryptoDetectiveError.fromApiResponse(response.status, errorBody);
52
+ }
53
+ throw new errors_1.CryptoDetectiveError(response.status, "API_REQUEST_FAILED", "Crypto Detective API request failed.");
54
+ }
55
+ return body;
56
+ }
57
+ }
58
+ exports.CryptoDetectiveClient = CryptoDetectiveClient;
59
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAMA,qCAAgD;AAoBhD,MAAa,qBAAqB;IACf,MAAM,CAAS;IACf,OAAO,CAAS;IAEjC,YAAY,OAAqC;QAC/C,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAEpC,IAAI,CAAC,OAAO,GAAG,CACb,OAAO,CAAC,OAAO;YACf,oCAAoC,CACrC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,WAAW,CACf,OAA6B,EAC7B,UAAgC,EAAE;QAElC,MAAM,OAAO,GAA2B;YACtC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;YACtC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,kBAAkB;SAC3B,CAAC;QAEF,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3B,OAAO,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;QACtD,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,GAAG,IAAI,CAAC,OAAO,qBAAqB,EACpC;YACE,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,cAAc,EAAE,OAAO,CAAC,aAAa;gBACrC,SAAS,EAAE,OAAO,CAAC,QAAQ,IAAI,MAAM;gBACrC,YAAY,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;gBACvC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;gBAChC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;aAC/B,CAAC;SACH,CACF,CAAC;QAEF,IAAI,IAAa,CAAC;QAElB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,6BAAoB,CAC5B,QAAQ,CAAC,MAAM,EACf,sBAAsB,EACtB,qDAAqD,CACtD,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,IAAmC,CAAC;YAEtD,IACE,SAAS;gBACT,SAAS,CAAC,OAAO,KAAK,KAAK;gBAC3B,SAAS,CAAC,KAAK;gBACf,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ;gBACxC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ,EAC3C,CAAC;gBACD,MAAM,6BAAoB,CAAC,eAAe,CACxC,QAAQ,CAAC,MAAM,EACf,SAAS,CACV,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,6BAAoB,CAC5B,QAAQ,CAAC,MAAM,EACf,oBAAoB,EACpB,sCAAsC,CACvC,CAAC;QACJ,CAAC;QAED,OAAO,IAA6B,CAAC;IACvC,CAAC;CACF;AApFD,sDAoFC"}
@@ -0,0 +1,9 @@
1
+ import type { CryptoDetectiveApiErrorBody } from "./types";
2
+ export declare class CryptoDetectiveError extends Error {
3
+ readonly status: number;
4
+ readonly code: string;
5
+ readonly details?: Record<string, unknown>;
6
+ constructor(status: number, code: string, message: string, details?: Record<string, unknown>);
7
+ static fromApiResponse(status: number, body: CryptoDetectiveApiErrorBody): CryptoDetectiveError;
8
+ }
9
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAE3D,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGhD,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYnC,MAAM,CAAC,eAAe,CACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,2BAA2B,GAChC,oBAAoB;CAUxB"}
package/dist/errors.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CryptoDetectiveError = void 0;
4
+ class CryptoDetectiveError extends Error {
5
+ status;
6
+ code;
7
+ details;
8
+ constructor(status, code, message, details) {
9
+ super(message);
10
+ this.name = "CryptoDetectiveError";
11
+ this.status = status;
12
+ this.code = code;
13
+ this.details = details;
14
+ Object.setPrototypeOf(this, CryptoDetectiveError.prototype);
15
+ }
16
+ static fromApiResponse(status, body) {
17
+ const { code, message, ...details } = body.error;
18
+ return new CryptoDetectiveError(status, code, message, Object.keys(details).length > 0 ? details : undefined);
19
+ }
20
+ }
21
+ exports.CryptoDetectiveError = CryptoDetectiveError;
22
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAEA,MAAa,oBAAqB,SAAQ,KAAK;IAC7B,MAAM,CAAS;IACf,IAAI,CAAS;IACb,OAAO,CAA2B;IAElD,YACE,MAAc,EACd,IAAY,EACZ,OAAe,EACf,OAAiC;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,eAAe,CACpB,MAAc,EACd,IAAiC;QAEjC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAEjD,OAAO,IAAI,oBAAoB,CAC7B,MAAM,EACN,IAAI,EACJ,OAAO,EACP,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CACtD,CAAC;IACJ,CAAC;CACF;AAlCD,oDAkCC"}
@@ -0,0 +1,5 @@
1
+ export { CryptoDetectiveClient, } from "./client";
2
+ export type { CryptoDetectiveClientOptions, InvestigationOptions, } from "./client";
3
+ export { CryptoDetectiveError, } from "./errors";
4
+ export type { CryptoDetectiveChain, CryptoDetectiveScanMode, CryptoDetectiveRiskLevel, InvestigationRequest, InvestigationValidity, InvestigationClassification, ScoreBreakdown, InvestigationScan, InvestigationResponse, CryptoDetectiveApiErrorBody, } from "./types";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GACtB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,EAC3B,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CryptoDetectiveError = exports.CryptoDetectiveClient = void 0;
4
+ var client_1 = require("./client");
5
+ Object.defineProperty(exports, "CryptoDetectiveClient", { enumerable: true, get: function () { return client_1.CryptoDetectiveClient; } });
6
+ var errors_1 = require("./errors");
7
+ Object.defineProperty(exports, "CryptoDetectiveError", { enumerable: true, get: function () { return errors_1.CryptoDetectiveError; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAEkB;AADhB,+GAAA,qBAAqB,OAAA;AAQvB,mCAEkB;AADhB,8GAAA,oBAAoB,OAAA"}
@@ -0,0 +1,58 @@
1
+ export type CryptoDetectiveChain = "auto" | "btc" | "eth" | "bsc" | "base" | "polygon" | "arbitrum" | "optimism" | "avalanche" | "tron" | "sol" | "ada" | "ltc" | "doge" | "xrp" | "bch" | "bnb" | "atom";
2
+ export type CryptoDetectiveScanMode = "quick" | "full";
3
+ export type CryptoDetectiveRiskLevel = "low" | "caution" | "high" | "critical";
4
+ export interface InvestigationRequest {
5
+ address: string;
6
+ chainSelected: CryptoDetectiveChain;
7
+ scanMode?: CryptoDetectiveScanMode;
8
+ assetSymbol?: string;
9
+ calldata?: string;
10
+ spender?: string;
11
+ }
12
+ export interface InvestigationValidity {
13
+ [key: string]: unknown;
14
+ }
15
+ export interface InvestigationClassification {
16
+ [key: string]: unknown;
17
+ }
18
+ export interface ScoreBreakdown {
19
+ final_score_source: string;
20
+ [key: string]: unknown;
21
+ }
22
+ export interface InvestigationScan {
23
+ id: string | number;
24
+ address: string;
25
+ chain_selected: string;
26
+ asset_symbol: string;
27
+ scan_type: string;
28
+ scanned_at: string;
29
+ validity: InvestigationValidity;
30
+ classification: InvestigationClassification;
31
+ score: number;
32
+ risk_level: CryptoDetectiveRiskLevel;
33
+ hard_stop_triggered: boolean;
34
+ hard_stop_code: string | null;
35
+ hard_stop_title: string | null;
36
+ hard_stop_message: string | null;
37
+ score_breakdown: ScoreBreakdown;
38
+ [key: string]: unknown;
39
+ }
40
+ export interface InvestigationResponse {
41
+ success: true;
42
+ status: "completed";
43
+ scan: InvestigationScan;
44
+ api: {
45
+ version: "v1";
46
+ environment: string;
47
+ key_name: string;
48
+ };
49
+ }
50
+ export interface CryptoDetectiveApiErrorBody {
51
+ success: false;
52
+ error: {
53
+ code: string;
54
+ message: string;
55
+ [key: string]: unknown;
56
+ };
57
+ }
58
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,GACN,SAAS,GACT,UAAU,GACV,UAAU,GACV,WAAW,GACX,MAAM,GACN,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,GACN,KAAK,GACL,KAAK,GACL,KAAK,GACL,MAAM,CAAC;AAEX,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,wBAAwB,GAChC,KAAK,GACL,SAAS,GACT,MAAM,GACN,UAAU,CAAC;AAEf,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC1C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IAEnB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,cAAc,EAAE,2BAA2B,CAAC;IAE5C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,wBAAwB,CAAC;IAErC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC,eAAe,EAAE,cAAc,CAAC;IAMhC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IAEpB,IAAI,EAAE,iBAAiB,CAAC;IAExB,GAAG,EAAE;QACH,OAAO,EAAE,IAAI,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,KAAK,CAAC;IAEf,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,30 @@
1
- {
2
- "name": "@cryptodetective/sdk",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
1
+ {
2
+ "name": "@cryptodetective/sdk",
3
+ "version": "1.0.0",
4
+ "description": "Official Node.js and TypeScript SDK for the Crypto Detective Investigation API.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "clean": "rm -rf dist",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "crypto-detective",
18
+ "blockchain",
19
+ "risk-intelligence",
20
+ "wallet-intelligence",
21
+ "blockchain-investigation"
22
+ ],
23
+ "license": "UNLICENSED",
24
+ "engines": {
25
+ "node": ">=18"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^5.9.0"
29
+ }
6
30
  }