@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 +371 -3
- package/dist/client.d.ts +23 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +59 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +22 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +29 -5
package/README.md
CHANGED
|
@@ -1,3 +1,371 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
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);
|
package/dist/client.d.ts
ADDED
|
@@ -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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
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": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
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
|
}
|