dritan-sdk 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/README.md +131 -0
- package/dist/index.cjs +255 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +154 -0
- package/dist/index.d.ts +154 -0
- package/dist/index.js +246 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# dritan-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for Dritan's data plane REST API and websocket streams.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i dritan-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { DritanClient } from "dritan-sdk";
|
|
15
|
+
|
|
16
|
+
const client = new DritanClient({
|
|
17
|
+
apiKey: process.env.DRITAN_API_KEY!,
|
|
18
|
+
baseUrl: "https://us-east.dritan.dev"
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const price = await client.getTokenPrice("So11111111111111111111111111111111111111112");
|
|
22
|
+
console.log(price);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## REST
|
|
26
|
+
|
|
27
|
+
### Token price
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
const price = await client.getTokenPrice("So11111111111111111111111111111111111111112");
|
|
31
|
+
console.log(price.priceUsd);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Token metadata
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const md = await client.getTokenMetadata("So11111111111111111111111111111111111111112");
|
|
38
|
+
console.log(md.name, md.symbol, md.decimals);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Token risk
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
const risk = await client.getTokenRisk("So11111111111111111111111111111111111111112");
|
|
45
|
+
console.log(risk.globalFeesPaid, risk.top10);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### First buyers (up to 100)
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
const res = await client.getFirstBuyers("So11111111111111111111111111111111111111112");
|
|
52
|
+
console.log(res.buyers);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Aggregated token data
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const agg = await client.getTokenAggregated("So11111111111111111111111111111111111111112");
|
|
59
|
+
console.log(agg.price.priceUsd, agg.metadata?.name, agg.risk?.top10, agg.bondingCurvePercent);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Swap
|
|
63
|
+
|
|
64
|
+
Dritan can build an unsigned swap transaction (base64) for you to sign, then you broadcast the signed transaction.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { Connection, VersionedTransaction } from "@solana/web3.js";
|
|
68
|
+
|
|
69
|
+
const build = await client.buildSwap({
|
|
70
|
+
userPublicKey: wallet.publicKey.toBase58(),
|
|
71
|
+
inputMint: "So11111111111111111111111111111111111111112",
|
|
72
|
+
outputMint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
73
|
+
amount: 100_000_000, // lamports
|
|
74
|
+
slippageBps: 500,
|
|
75
|
+
swapType: "buy",
|
|
76
|
+
// Optional: monetize swaps for your own users
|
|
77
|
+
feeWallet: "YourFeeWalletPubkeyHere",
|
|
78
|
+
feePercent: 0.5
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const tx = VersionedTransaction.deserialize(Buffer.from(build.transactionBase64, "base64"));
|
|
82
|
+
const signed = await wallet.signTransaction(tx);
|
|
83
|
+
const signedBase64 = Buffer.from(signed.serialize()).toString("base64");
|
|
84
|
+
|
|
85
|
+
const sent = await client.broadcastSwap(signedBase64);
|
|
86
|
+
console.log(sent.signature);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Websocket streams
|
|
90
|
+
|
|
91
|
+
Connect to a dex stream (for example `pumpamm`, `pumpfun`, `launchlab`, `dbc`, `dlmm`, `damm2`, `damm1`).
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
const stream = client.streamDex("pumpamm", {
|
|
95
|
+
onMessage: (event) => {
|
|
96
|
+
// `event` is parsed JSON when possible, otherwise raw string.
|
|
97
|
+
console.log(event);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
setTimeout(() => stream.close(), 10_000);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Note: browser websockets cannot send custom headers. If you use this SDK in the browser, pass `sendApiKeyInQuery: true` (this puts your API key in the websocket URL).
|
|
105
|
+
|
|
106
|
+
## Configuration
|
|
107
|
+
|
|
108
|
+
`DritanClient` options:
|
|
109
|
+
|
|
110
|
+
- `apiKey` (required): API key to send as `x-api-key`
|
|
111
|
+
- `baseUrl` (optional): REST base URL (default `https://us-east.dritan.dev`)
|
|
112
|
+
- `wsBaseUrl` (optional): WS base URL (default `wss://us-east.dritan.dev`)
|
|
113
|
+
|
|
114
|
+
## Meteora THS (No API Key)
|
|
115
|
+
|
|
116
|
+
Meteora THS is a public REST API hosted at `https://ths.dritan.dev`.
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { MeteoraThsClient } from "dritan-sdk";
|
|
120
|
+
|
|
121
|
+
const ths = new MeteoraThsClient();
|
|
122
|
+
|
|
123
|
+
const score = await ths.getThsScore("7Y...Wallet");
|
|
124
|
+
console.log(score.score, score.realizedPnLUsd);
|
|
125
|
+
|
|
126
|
+
const tokensOnly = await ths.getThsScoreForTokens("7Y...Wallet", [
|
|
127
|
+
"So11111111111111111111111111111111111111112",
|
|
128
|
+
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
|
|
129
|
+
]);
|
|
130
|
+
console.log(tokensOnly.score);
|
|
131
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var WebSocketImpl = require('isomorphic-ws');
|
|
4
|
+
|
|
5
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
+
|
|
7
|
+
var WebSocketImpl__default = /*#__PURE__*/_interopDefault(WebSocketImpl);
|
|
8
|
+
|
|
9
|
+
// src/index.ts
|
|
10
|
+
function buildUrl(baseUrl, path) {
|
|
11
|
+
return `${baseUrl.replace(/\/+$/, "")}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
12
|
+
}
|
|
13
|
+
function buildWsUrl(wsBaseUrl, path, query) {
|
|
14
|
+
const url = new URL(buildUrl(wsBaseUrl, path));
|
|
15
|
+
if (query) {
|
|
16
|
+
for (const [k, v] of Object.entries(query)) {
|
|
17
|
+
if (v === void 0 || v === null) continue;
|
|
18
|
+
url.searchParams.set(k, String(v));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return url.toString();
|
|
22
|
+
}
|
|
23
|
+
function safeJsonParse(payload) {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(payload);
|
|
26
|
+
} catch {
|
|
27
|
+
return payload;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function isNodeRuntime() {
|
|
31
|
+
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
32
|
+
}
|
|
33
|
+
function messageToString(data) {
|
|
34
|
+
if (typeof data === "string") return data;
|
|
35
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
36
|
+
return data.toString("utf8");
|
|
37
|
+
}
|
|
38
|
+
if (data instanceof ArrayBuffer) {
|
|
39
|
+
return new TextDecoder().decode(new Uint8Array(data));
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
var DritanClient = class {
|
|
44
|
+
apiKey;
|
|
45
|
+
baseUrl;
|
|
46
|
+
wsBaseUrl;
|
|
47
|
+
fetchImpl;
|
|
48
|
+
WebSocketCtor;
|
|
49
|
+
constructor(options) {
|
|
50
|
+
this.apiKey = options.apiKey;
|
|
51
|
+
this.baseUrl = options.baseUrl ?? "https://us-east.dritan.dev";
|
|
52
|
+
this.wsBaseUrl = options.wsBaseUrl ?? "wss://us-east.dritan.dev";
|
|
53
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
54
|
+
this.WebSocketCtor = options.WebSocket ?? WebSocketImpl__default.default;
|
|
55
|
+
}
|
|
56
|
+
async getTokenPrice(mint) {
|
|
57
|
+
const url = buildUrl(this.baseUrl, `/token/price/${encodeURIComponent(mint)}`);
|
|
58
|
+
const res = await this.fetchImpl(url, {
|
|
59
|
+
method: "GET",
|
|
60
|
+
headers: {
|
|
61
|
+
"x-api-key": this.apiKey
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
const text = await res.text().catch(() => "");
|
|
66
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
67
|
+
}
|
|
68
|
+
return await res.json();
|
|
69
|
+
}
|
|
70
|
+
async getTokenMetadata(mint) {
|
|
71
|
+
const url = buildUrl(this.baseUrl, `/token/metadata/${encodeURIComponent(mint)}`);
|
|
72
|
+
const res = await this.fetchImpl(url, {
|
|
73
|
+
method: "GET",
|
|
74
|
+
headers: {
|
|
75
|
+
"x-api-key": this.apiKey
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok) {
|
|
79
|
+
const text = await res.text().catch(() => "");
|
|
80
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
81
|
+
}
|
|
82
|
+
return await res.json();
|
|
83
|
+
}
|
|
84
|
+
async getTokenRisk(mint) {
|
|
85
|
+
const url = buildUrl(this.baseUrl, `/token/risk/${encodeURIComponent(mint)}`);
|
|
86
|
+
const res = await this.fetchImpl(url, {
|
|
87
|
+
method: "GET",
|
|
88
|
+
headers: {
|
|
89
|
+
"x-api-key": this.apiKey
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
if (!res.ok) {
|
|
93
|
+
const text = await res.text().catch(() => "");
|
|
94
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
95
|
+
}
|
|
96
|
+
return await res.json();
|
|
97
|
+
}
|
|
98
|
+
async getFirstBuyers(mint) {
|
|
99
|
+
const url = buildUrl(this.baseUrl, `/token/first-buyers/${encodeURIComponent(mint)}`);
|
|
100
|
+
const res = await this.fetchImpl(url, {
|
|
101
|
+
method: "GET",
|
|
102
|
+
headers: {
|
|
103
|
+
"x-api-key": this.apiKey
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
if (!res.ok) {
|
|
107
|
+
const text = await res.text().catch(() => "");
|
|
108
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
109
|
+
}
|
|
110
|
+
return await res.json();
|
|
111
|
+
}
|
|
112
|
+
async getTokenAggregated(mint) {
|
|
113
|
+
const url = buildUrl(this.baseUrl, `/token/aggregated/${encodeURIComponent(mint)}`);
|
|
114
|
+
const res = await this.fetchImpl(url, {
|
|
115
|
+
method: "GET",
|
|
116
|
+
headers: {
|
|
117
|
+
"x-api-key": this.apiKey
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
if (!res.ok) {
|
|
121
|
+
const text = await res.text().catch(() => "");
|
|
122
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
123
|
+
}
|
|
124
|
+
const raw = await res.json();
|
|
125
|
+
return {
|
|
126
|
+
mint: String(raw?.mint ?? mint),
|
|
127
|
+
price: raw?.price,
|
|
128
|
+
metadata: raw?.metadata ?? null,
|
|
129
|
+
risk: raw?.risk ?? null,
|
|
130
|
+
bondingCurvePercent: raw?.bondingCurvePercent === void 0 ? null : raw?.bondingCurvePercent ?? null
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
async buildSwap(body) {
|
|
134
|
+
const url = buildUrl(this.baseUrl, "/swap/build");
|
|
135
|
+
const res = await this.fetchImpl(url, {
|
|
136
|
+
method: "POST",
|
|
137
|
+
headers: {
|
|
138
|
+
"x-api-key": this.apiKey,
|
|
139
|
+
"content-type": "application/json"
|
|
140
|
+
},
|
|
141
|
+
body: JSON.stringify(body ?? {})
|
|
142
|
+
});
|
|
143
|
+
if (!res.ok) {
|
|
144
|
+
const text = await res.text().catch(() => "");
|
|
145
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
146
|
+
}
|
|
147
|
+
return await res.json();
|
|
148
|
+
}
|
|
149
|
+
async broadcastSwap(signedTransactionBase64) {
|
|
150
|
+
const url = buildUrl(this.baseUrl, "/swap/broadcast");
|
|
151
|
+
const res = await this.fetchImpl(url, {
|
|
152
|
+
method: "POST",
|
|
153
|
+
headers: {
|
|
154
|
+
"x-api-key": this.apiKey,
|
|
155
|
+
"content-type": "application/json"
|
|
156
|
+
},
|
|
157
|
+
body: JSON.stringify({ signedTransactionBase64 })
|
|
158
|
+
});
|
|
159
|
+
if (!res.ok) {
|
|
160
|
+
const text = await res.text().catch(() => "");
|
|
161
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
162
|
+
}
|
|
163
|
+
return await res.json();
|
|
164
|
+
}
|
|
165
|
+
streamDex(dex, options = {}) {
|
|
166
|
+
const shouldSendKeyInQuery = options.sendApiKeyInQuery ?? !isNodeRuntime();
|
|
167
|
+
const query = { ...options.query ?? {} };
|
|
168
|
+
if (shouldSendKeyInQuery && query.apiKey == null) {
|
|
169
|
+
query.apiKey = this.apiKey;
|
|
170
|
+
}
|
|
171
|
+
const url = buildWsUrl(this.wsBaseUrl, `/${dex}`, query);
|
|
172
|
+
const ws = shouldSendKeyInQuery ? new this.WebSocketCtor(url) : new this.WebSocketCtor(
|
|
173
|
+
url,
|
|
174
|
+
{
|
|
175
|
+
headers: {
|
|
176
|
+
"x-api-key": this.apiKey
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
ws.onopen = () => options.onOpen?.();
|
|
181
|
+
ws.onclose = (ev) => options.onClose?.(ev);
|
|
182
|
+
ws.onerror = (ev) => options.onError?.(ev);
|
|
183
|
+
ws.onmessage = (msg) => {
|
|
184
|
+
const raw = messageToString(msg.data);
|
|
185
|
+
const data = raw ? safeJsonParse(raw) : msg.data;
|
|
186
|
+
options.onMessage?.(data);
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
socket: ws,
|
|
190
|
+
close: () => ws.close()
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
var createClient = (options) => new DritanClient(options);
|
|
195
|
+
var MeteoraThsClient = class {
|
|
196
|
+
baseUrl;
|
|
197
|
+
fetchImpl;
|
|
198
|
+
constructor(options = {}) {
|
|
199
|
+
this.baseUrl = options.baseUrl ?? "https://ths.dritan.dev";
|
|
200
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
201
|
+
}
|
|
202
|
+
async health() {
|
|
203
|
+
const url = buildUrl(this.baseUrl, "/health");
|
|
204
|
+
const res = await this.fetchImpl(url, { method: "GET" });
|
|
205
|
+
return res.ok;
|
|
206
|
+
}
|
|
207
|
+
async getThsScore(wallet, options = {}) {
|
|
208
|
+
const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}`));
|
|
209
|
+
if (options.debug) url.searchParams.set("debug", "1");
|
|
210
|
+
if (options.breakdown) url.searchParams.set("breakdown", "1");
|
|
211
|
+
const res = await this.fetchImpl(url.toString(), { method: "GET" });
|
|
212
|
+
if (!res.ok) {
|
|
213
|
+
const text = await res.text().catch(() => "");
|
|
214
|
+
throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);
|
|
215
|
+
}
|
|
216
|
+
return await res.json();
|
|
217
|
+
}
|
|
218
|
+
async getThsScoreForTokens(wallet, tokenMints, options = {}) {
|
|
219
|
+
const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));
|
|
220
|
+
for (const mint of tokenMints ?? []) {
|
|
221
|
+
url.searchParams.append("tokenMints", mint);
|
|
222
|
+
}
|
|
223
|
+
if (options.debug) url.searchParams.set("debug", "1");
|
|
224
|
+
if (options.breakdown) url.searchParams.set("breakdown", "1");
|
|
225
|
+
const res = await this.fetchImpl(url.toString(), { method: "GET" });
|
|
226
|
+
if (!res.ok) {
|
|
227
|
+
const text = await res.text().catch(() => "");
|
|
228
|
+
throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);
|
|
229
|
+
}
|
|
230
|
+
return await res.json();
|
|
231
|
+
}
|
|
232
|
+
async postThsScoreForTokens(wallet, tokenMints, options = {}) {
|
|
233
|
+
const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));
|
|
234
|
+
if (options.debug) url.searchParams.set("debug", "1");
|
|
235
|
+
if (options.breakdown) url.searchParams.set("breakdown", "1");
|
|
236
|
+
const res = await this.fetchImpl(url.toString(), {
|
|
237
|
+
method: "POST",
|
|
238
|
+
headers: { "content-type": "application/json" },
|
|
239
|
+
body: JSON.stringify({ tokenMints: tokenMints ?? [] })
|
|
240
|
+
});
|
|
241
|
+
if (!res.ok) {
|
|
242
|
+
const text = await res.text().catch(() => "");
|
|
243
|
+
throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);
|
|
244
|
+
}
|
|
245
|
+
return await res.json();
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
var createMeteoraThsClient = (options) => new MeteoraThsClient(options);
|
|
249
|
+
|
|
250
|
+
exports.DritanClient = DritanClient;
|
|
251
|
+
exports.MeteoraThsClient = MeteoraThsClient;
|
|
252
|
+
exports.createClient = createClient;
|
|
253
|
+
exports.createMeteoraThsClient = createMeteoraThsClient;
|
|
254
|
+
//# sourceMappingURL=index.cjs.map
|
|
255
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["WebSocketImpl"],"mappings":"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","file":"index.cjs","sourcesContent":["import WebSocketImpl from \"isomorphic-ws\";\n\nexport type DritanClientOptions = {\n apiKey: string;\n baseUrl?: string;\n wsBaseUrl?: string;\n fetch?: typeof fetch;\n WebSocket?: typeof WebSocketImpl;\n};\n\nexport type KnownDexStream =\n | \"pumpamm\"\n | \"pumpfun\"\n | \"launchlab\"\n | \"dlmm\"\n | \"damm2\"\n | \"damm1\"\n | \"dbc\";\n\nexport type MeteoraThsClientOptions = {\n baseUrl?: string;\n fetch?: typeof fetch;\n};\n\nexport type TokenPriceResponse = {\n mint: string;\n dex: string;\n priceUsd: number;\n marketCap: number | null;\n liquiditySol: number | null;\n};\n\nexport type TokenMetadataResponse = {\n mint: string;\n programId: string;\n name: string;\n symbol: string;\n uri: string;\n decimals: number;\n supply: string;\n};\n\nexport type RiskGroup = {\n count: number;\n totalPercentage: number;\n};\n\nexport type TokenRiskResponse = {\n mint: string;\n globalFeesPaid: number;\n bundlers: RiskGroup;\n insiders: RiskGroup;\n snipers: RiskGroup;\n top10: number;\n devPercentage: number | null;\n};\n\nexport type TokenFirstBuyersResponse = {\n mint: string;\n buyers: unknown;\n};\n\nexport type TokenAggregatedResponse = {\n mint: string;\n price: TokenPriceResponse;\n metadata: TokenMetadataResponse | null;\n risk: TokenRiskResponse | null;\n bondingCurvePercent: number | null;\n};\n\nexport type DritanStreamOptions = {\n query?: Record<string, string | number | boolean | undefined | null>;\n /**\n * When true, includes the api key as `?apiKey=...` in the websocket URL.\n * This is required when using native browser websockets (custom headers are not supported).\n */\n sendApiKeyInQuery?: boolean;\n onOpen?: () => void;\n onClose?: (ev: CloseEvent) => void;\n onError?: (ev: Event) => void;\n onMessage?: (data: unknown) => void;\n};\n\nexport type DritanStreamHandle = {\n socket: WebSocket;\n close: () => void;\n};\n\nexport type SwapBuildRequest = {\n userPublicKey: string;\n inputMint: string;\n outputMint: string;\n amount: number | string;\n slippageBps?: number;\n swapType?: string;\n feeWallet?: string;\n feeBps?: number;\n feePercent?: number;\n};\n\nexport type SwapBuildFees = {\n platformFeeBps: number;\n platformFeeLamports: number;\n userFeeBps: number;\n userFeeLamports: number;\n tipLamports: number;\n};\n\nexport type SwapBuildResponse = {\n transactionBase64: string;\n fees: SwapBuildFees;\n quote: unknown;\n};\n\nexport type SwapBroadcastResponse = {\n signature: string;\n};\n\nexport type ThsTotals = {\n buys: number;\n sells: number;\n};\n\nexport type ThsResponse = {\n wallet: string;\n score: number;\n realizedPnLUsd: number;\n realizedPnLWeightedUsd: number;\n totals: ThsTotals;\n analyzedTxns: number;\n matchedTxCount: number;\n unmatchedTxCount: number;\n avgHoldTimeDays: number;\n avgHoldTimeHours: number;\n avgHoldTimeMinutes: number;\n avgHoldTimeSeconds: number;\n avgHoldTimePretty: string;\n};\n\nfunction buildUrl(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/+$/, \"\")}${path.startsWith(\"/\") ? \"\" : \"/\"}${path}`;\n}\n\nfunction buildWsUrl(\n wsBaseUrl: string,\n path: string,\n query?: Record<string, string | number | boolean | undefined | null>\n): string {\n const url = new URL(buildUrl(wsBaseUrl, path));\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined || v === null) continue;\n url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\nfunction safeJsonParse(payload: string): unknown {\n try {\n return JSON.parse(payload) as unknown;\n } catch {\n return payload;\n }\n}\n\nfunction isNodeRuntime(): boolean {\n return (\n typeof process !== \"undefined\" &&\n typeof (process as any).versions?.node === \"string\"\n );\n}\n\nfunction messageToString(data: unknown): string | null {\n if (typeof data === \"string\") return data;\n\n // ws (node) can emit Buffer\n if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(data)) {\n return data.toString(\"utf8\");\n }\n\n // browser ws can emit ArrayBuffer\n if (data instanceof ArrayBuffer) {\n return new TextDecoder().decode(new Uint8Array(data));\n }\n\n return null;\n}\n\nexport class DritanClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly wsBaseUrl: string;\n private readonly fetchImpl: typeof fetch;\n private readonly WebSocketCtor: typeof WebSocketImpl;\n\n constructor(options: DritanClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://us-east.dritan.dev\";\n this.wsBaseUrl = options.wsBaseUrl ?? \"wss://us-east.dritan.dev\";\n this.fetchImpl = options.fetch ?? fetch;\n this.WebSocketCtor = options.WebSocket ?? WebSocketImpl;\n }\n\n async getTokenPrice(mint: string): Promise<TokenPriceResponse> {\n const url = buildUrl(this.baseUrl, `/token/price/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenPriceResponse;\n }\n\n async getTokenMetadata(mint: string): Promise<TokenMetadataResponse> {\n const url = buildUrl(this.baseUrl, `/token/metadata/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenMetadataResponse;\n }\n\n async getTokenRisk(mint: string): Promise<TokenRiskResponse> {\n const url = buildUrl(this.baseUrl, `/token/risk/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenRiskResponse;\n }\n\n async getFirstBuyers(mint: string): Promise<TokenFirstBuyersResponse> {\n const url = buildUrl(this.baseUrl, `/token/first-buyers/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenFirstBuyersResponse;\n }\n\n async getTokenAggregated(mint: string): Promise<TokenAggregatedResponse> {\n const url = buildUrl(this.baseUrl, `/token/aggregated/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n const raw = (await res.json()) as any;\n return {\n mint: String(raw?.mint ?? mint),\n price: raw?.price as TokenPriceResponse,\n metadata: raw?.metadata ?? null,\n risk: raw?.risk ?? null,\n bondingCurvePercent:\n raw?.bondingCurvePercent === undefined ? null : (raw?.bondingCurvePercent ?? null)\n };\n }\n\n async buildSwap(body: SwapBuildRequest): Promise<SwapBuildResponse> {\n const url = buildUrl(this.baseUrl, \"/swap/build\");\n const res = await this.fetchImpl(url, {\n method: \"POST\",\n headers: {\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\"\n },\n body: JSON.stringify(body ?? {})\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as SwapBuildResponse;\n }\n\n async broadcastSwap(signedTransactionBase64: string): Promise<SwapBroadcastResponse> {\n const url = buildUrl(this.baseUrl, \"/swap/broadcast\");\n const res = await this.fetchImpl(url, {\n method: \"POST\",\n headers: {\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\"\n },\n body: JSON.stringify({ signedTransactionBase64 })\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as SwapBroadcastResponse;\n }\n\n streamDex(dex: KnownDexStream, options?: DritanStreamOptions): DritanStreamHandle;\n streamDex(dex: string, options?: DritanStreamOptions): DritanStreamHandle;\n streamDex(dex: string, options: DritanStreamOptions = {}): DritanStreamHandle {\n const shouldSendKeyInQuery = options.sendApiKeyInQuery ?? !isNodeRuntime();\n const query = { ...(options.query ?? {}) } as Record<\n string,\n string | number | boolean | undefined | null\n >;\n if (shouldSendKeyInQuery && query.apiKey == null) {\n query.apiKey = this.apiKey;\n }\n\n const url = buildWsUrl(this.wsBaseUrl, `/${dex}`, query);\n const ws = shouldSendKeyInQuery\n ? new this.WebSocketCtor(url)\n : new this.WebSocketCtor(\n url,\n {\n headers: {\n \"x-api-key\": this.apiKey\n }\n } as any\n );\n\n ws.onopen = () => options.onOpen?.();\n ws.onclose = (ev: any) => options.onClose?.(ev as CloseEvent);\n ws.onerror = (ev: any) => options.onError?.(ev as Event);\n ws.onmessage = (msg: any) => {\n const raw = messageToString(msg.data);\n const data = raw ? safeJsonParse(raw) : msg.data;\n options.onMessage?.(data);\n };\n\n return {\n socket: ws as unknown as WebSocket,\n close: () => ws.close()\n };\n }\n}\n\nexport const createClient = (options: DritanClientOptions) => new DritanClient(options);\n\nexport class MeteoraThsClient {\n readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: MeteoraThsClientOptions = {}) {\n this.baseUrl = options.baseUrl ?? \"https://ths.dritan.dev\";\n this.fetchImpl = options.fetch ?? fetch;\n }\n\n async health(): Promise<boolean> {\n const url = buildUrl(this.baseUrl, \"/health\");\n const res = await this.fetchImpl(url, { method: \"GET\" });\n return res.ok;\n }\n\n async getThsScore(\n wallet: string,\n options: { debug?: boolean; breakdown?: boolean } = {}\n ): Promise<ThsResponse> {\n const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}`));\n if (options.debug) url.searchParams.set(\"debug\", \"1\");\n if (options.breakdown) url.searchParams.set(\"breakdown\", \"1\");\n\n const res = await this.fetchImpl(url.toString(), { method: \"GET\" });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as ThsResponse;\n }\n\n async getThsScoreForTokens(\n wallet: string,\n tokenMints: string[],\n options: { debug?: boolean; breakdown?: boolean } = {}\n ): Promise<ThsResponse> {\n const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));\n for (const mint of tokenMints ?? []) {\n url.searchParams.append(\"tokenMints\", mint);\n }\n if (options.debug) url.searchParams.set(\"debug\", \"1\");\n if (options.breakdown) url.searchParams.set(\"breakdown\", \"1\");\n\n const res = await this.fetchImpl(url.toString(), { method: \"GET\" });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as ThsResponse;\n }\n\n async postThsScoreForTokens(\n wallet: string,\n tokenMints: string[],\n options: { debug?: boolean; breakdown?: boolean } = {}\n ): Promise<ThsResponse> {\n const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));\n if (options.debug) url.searchParams.set(\"debug\", \"1\");\n if (options.breakdown) url.searchParams.set(\"breakdown\", \"1\");\n\n const res = await this.fetchImpl(url.toString(), {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ tokenMints: tokenMints ?? [] })\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as ThsResponse;\n }\n}\n\nexport const createMeteoraThsClient = (options?: MeteoraThsClientOptions) =>\n new MeteoraThsClient(options);\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import WebSocketImpl from 'isomorphic-ws';
|
|
2
|
+
|
|
3
|
+
type DritanClientOptions = {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
wsBaseUrl?: string;
|
|
7
|
+
fetch?: typeof fetch;
|
|
8
|
+
WebSocket?: typeof WebSocketImpl;
|
|
9
|
+
};
|
|
10
|
+
type KnownDexStream = "pumpamm" | "pumpfun" | "launchlab" | "dlmm" | "damm2" | "damm1" | "dbc";
|
|
11
|
+
type MeteoraThsClientOptions = {
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
fetch?: typeof fetch;
|
|
14
|
+
};
|
|
15
|
+
type TokenPriceResponse = {
|
|
16
|
+
mint: string;
|
|
17
|
+
dex: string;
|
|
18
|
+
priceUsd: number;
|
|
19
|
+
marketCap: number | null;
|
|
20
|
+
liquiditySol: number | null;
|
|
21
|
+
};
|
|
22
|
+
type TokenMetadataResponse = {
|
|
23
|
+
mint: string;
|
|
24
|
+
programId: string;
|
|
25
|
+
name: string;
|
|
26
|
+
symbol: string;
|
|
27
|
+
uri: string;
|
|
28
|
+
decimals: number;
|
|
29
|
+
supply: string;
|
|
30
|
+
};
|
|
31
|
+
type RiskGroup = {
|
|
32
|
+
count: number;
|
|
33
|
+
totalPercentage: number;
|
|
34
|
+
};
|
|
35
|
+
type TokenRiskResponse = {
|
|
36
|
+
mint: string;
|
|
37
|
+
globalFeesPaid: number;
|
|
38
|
+
bundlers: RiskGroup;
|
|
39
|
+
insiders: RiskGroup;
|
|
40
|
+
snipers: RiskGroup;
|
|
41
|
+
top10: number;
|
|
42
|
+
devPercentage: number | null;
|
|
43
|
+
};
|
|
44
|
+
type TokenFirstBuyersResponse = {
|
|
45
|
+
mint: string;
|
|
46
|
+
buyers: unknown;
|
|
47
|
+
};
|
|
48
|
+
type TokenAggregatedResponse = {
|
|
49
|
+
mint: string;
|
|
50
|
+
price: TokenPriceResponse;
|
|
51
|
+
metadata: TokenMetadataResponse | null;
|
|
52
|
+
risk: TokenRiskResponse | null;
|
|
53
|
+
bondingCurvePercent: number | null;
|
|
54
|
+
};
|
|
55
|
+
type DritanStreamOptions = {
|
|
56
|
+
query?: Record<string, string | number | boolean | undefined | null>;
|
|
57
|
+
/**
|
|
58
|
+
* When true, includes the api key as `?apiKey=...` in the websocket URL.
|
|
59
|
+
* This is required when using native browser websockets (custom headers are not supported).
|
|
60
|
+
*/
|
|
61
|
+
sendApiKeyInQuery?: boolean;
|
|
62
|
+
onOpen?: () => void;
|
|
63
|
+
onClose?: (ev: CloseEvent) => void;
|
|
64
|
+
onError?: (ev: Event) => void;
|
|
65
|
+
onMessage?: (data: unknown) => void;
|
|
66
|
+
};
|
|
67
|
+
type DritanStreamHandle = {
|
|
68
|
+
socket: WebSocket;
|
|
69
|
+
close: () => void;
|
|
70
|
+
};
|
|
71
|
+
type SwapBuildRequest = {
|
|
72
|
+
userPublicKey: string;
|
|
73
|
+
inputMint: string;
|
|
74
|
+
outputMint: string;
|
|
75
|
+
amount: number | string;
|
|
76
|
+
slippageBps?: number;
|
|
77
|
+
swapType?: string;
|
|
78
|
+
feeWallet?: string;
|
|
79
|
+
feeBps?: number;
|
|
80
|
+
feePercent?: number;
|
|
81
|
+
};
|
|
82
|
+
type SwapBuildFees = {
|
|
83
|
+
platformFeeBps: number;
|
|
84
|
+
platformFeeLamports: number;
|
|
85
|
+
userFeeBps: number;
|
|
86
|
+
userFeeLamports: number;
|
|
87
|
+
tipLamports: number;
|
|
88
|
+
};
|
|
89
|
+
type SwapBuildResponse = {
|
|
90
|
+
transactionBase64: string;
|
|
91
|
+
fees: SwapBuildFees;
|
|
92
|
+
quote: unknown;
|
|
93
|
+
};
|
|
94
|
+
type SwapBroadcastResponse = {
|
|
95
|
+
signature: string;
|
|
96
|
+
};
|
|
97
|
+
type ThsTotals = {
|
|
98
|
+
buys: number;
|
|
99
|
+
sells: number;
|
|
100
|
+
};
|
|
101
|
+
type ThsResponse = {
|
|
102
|
+
wallet: string;
|
|
103
|
+
score: number;
|
|
104
|
+
realizedPnLUsd: number;
|
|
105
|
+
realizedPnLWeightedUsd: number;
|
|
106
|
+
totals: ThsTotals;
|
|
107
|
+
analyzedTxns: number;
|
|
108
|
+
matchedTxCount: number;
|
|
109
|
+
unmatchedTxCount: number;
|
|
110
|
+
avgHoldTimeDays: number;
|
|
111
|
+
avgHoldTimeHours: number;
|
|
112
|
+
avgHoldTimeMinutes: number;
|
|
113
|
+
avgHoldTimeSeconds: number;
|
|
114
|
+
avgHoldTimePretty: string;
|
|
115
|
+
};
|
|
116
|
+
declare class DritanClient {
|
|
117
|
+
readonly apiKey: string;
|
|
118
|
+
readonly baseUrl: string;
|
|
119
|
+
readonly wsBaseUrl: string;
|
|
120
|
+
private readonly fetchImpl;
|
|
121
|
+
private readonly WebSocketCtor;
|
|
122
|
+
constructor(options: DritanClientOptions);
|
|
123
|
+
getTokenPrice(mint: string): Promise<TokenPriceResponse>;
|
|
124
|
+
getTokenMetadata(mint: string): Promise<TokenMetadataResponse>;
|
|
125
|
+
getTokenRisk(mint: string): Promise<TokenRiskResponse>;
|
|
126
|
+
getFirstBuyers(mint: string): Promise<TokenFirstBuyersResponse>;
|
|
127
|
+
getTokenAggregated(mint: string): Promise<TokenAggregatedResponse>;
|
|
128
|
+
buildSwap(body: SwapBuildRequest): Promise<SwapBuildResponse>;
|
|
129
|
+
broadcastSwap(signedTransactionBase64: string): Promise<SwapBroadcastResponse>;
|
|
130
|
+
streamDex(dex: KnownDexStream, options?: DritanStreamOptions): DritanStreamHandle;
|
|
131
|
+
streamDex(dex: string, options?: DritanStreamOptions): DritanStreamHandle;
|
|
132
|
+
}
|
|
133
|
+
declare const createClient: (options: DritanClientOptions) => DritanClient;
|
|
134
|
+
declare class MeteoraThsClient {
|
|
135
|
+
readonly baseUrl: string;
|
|
136
|
+
private readonly fetchImpl;
|
|
137
|
+
constructor(options?: MeteoraThsClientOptions);
|
|
138
|
+
health(): Promise<boolean>;
|
|
139
|
+
getThsScore(wallet: string, options?: {
|
|
140
|
+
debug?: boolean;
|
|
141
|
+
breakdown?: boolean;
|
|
142
|
+
}): Promise<ThsResponse>;
|
|
143
|
+
getThsScoreForTokens(wallet: string, tokenMints: string[], options?: {
|
|
144
|
+
debug?: boolean;
|
|
145
|
+
breakdown?: boolean;
|
|
146
|
+
}): Promise<ThsResponse>;
|
|
147
|
+
postThsScoreForTokens(wallet: string, tokenMints: string[], options?: {
|
|
148
|
+
debug?: boolean;
|
|
149
|
+
breakdown?: boolean;
|
|
150
|
+
}): Promise<ThsResponse>;
|
|
151
|
+
}
|
|
152
|
+
declare const createMeteoraThsClient: (options?: MeteoraThsClientOptions) => MeteoraThsClient;
|
|
153
|
+
|
|
154
|
+
export { DritanClient, type DritanClientOptions, type DritanStreamHandle, type DritanStreamOptions, type KnownDexStream, MeteoraThsClient, type MeteoraThsClientOptions, type RiskGroup, type SwapBroadcastResponse, type SwapBuildFees, type SwapBuildRequest, type SwapBuildResponse, type ThsResponse, type ThsTotals, type TokenAggregatedResponse, type TokenFirstBuyersResponse, type TokenMetadataResponse, type TokenPriceResponse, type TokenRiskResponse, createClient, createMeteoraThsClient };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import WebSocketImpl from 'isomorphic-ws';
|
|
2
|
+
|
|
3
|
+
type DritanClientOptions = {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
wsBaseUrl?: string;
|
|
7
|
+
fetch?: typeof fetch;
|
|
8
|
+
WebSocket?: typeof WebSocketImpl;
|
|
9
|
+
};
|
|
10
|
+
type KnownDexStream = "pumpamm" | "pumpfun" | "launchlab" | "dlmm" | "damm2" | "damm1" | "dbc";
|
|
11
|
+
type MeteoraThsClientOptions = {
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
fetch?: typeof fetch;
|
|
14
|
+
};
|
|
15
|
+
type TokenPriceResponse = {
|
|
16
|
+
mint: string;
|
|
17
|
+
dex: string;
|
|
18
|
+
priceUsd: number;
|
|
19
|
+
marketCap: number | null;
|
|
20
|
+
liquiditySol: number | null;
|
|
21
|
+
};
|
|
22
|
+
type TokenMetadataResponse = {
|
|
23
|
+
mint: string;
|
|
24
|
+
programId: string;
|
|
25
|
+
name: string;
|
|
26
|
+
symbol: string;
|
|
27
|
+
uri: string;
|
|
28
|
+
decimals: number;
|
|
29
|
+
supply: string;
|
|
30
|
+
};
|
|
31
|
+
type RiskGroup = {
|
|
32
|
+
count: number;
|
|
33
|
+
totalPercentage: number;
|
|
34
|
+
};
|
|
35
|
+
type TokenRiskResponse = {
|
|
36
|
+
mint: string;
|
|
37
|
+
globalFeesPaid: number;
|
|
38
|
+
bundlers: RiskGroup;
|
|
39
|
+
insiders: RiskGroup;
|
|
40
|
+
snipers: RiskGroup;
|
|
41
|
+
top10: number;
|
|
42
|
+
devPercentage: number | null;
|
|
43
|
+
};
|
|
44
|
+
type TokenFirstBuyersResponse = {
|
|
45
|
+
mint: string;
|
|
46
|
+
buyers: unknown;
|
|
47
|
+
};
|
|
48
|
+
type TokenAggregatedResponse = {
|
|
49
|
+
mint: string;
|
|
50
|
+
price: TokenPriceResponse;
|
|
51
|
+
metadata: TokenMetadataResponse | null;
|
|
52
|
+
risk: TokenRiskResponse | null;
|
|
53
|
+
bondingCurvePercent: number | null;
|
|
54
|
+
};
|
|
55
|
+
type DritanStreamOptions = {
|
|
56
|
+
query?: Record<string, string | number | boolean | undefined | null>;
|
|
57
|
+
/**
|
|
58
|
+
* When true, includes the api key as `?apiKey=...` in the websocket URL.
|
|
59
|
+
* This is required when using native browser websockets (custom headers are not supported).
|
|
60
|
+
*/
|
|
61
|
+
sendApiKeyInQuery?: boolean;
|
|
62
|
+
onOpen?: () => void;
|
|
63
|
+
onClose?: (ev: CloseEvent) => void;
|
|
64
|
+
onError?: (ev: Event) => void;
|
|
65
|
+
onMessage?: (data: unknown) => void;
|
|
66
|
+
};
|
|
67
|
+
type DritanStreamHandle = {
|
|
68
|
+
socket: WebSocket;
|
|
69
|
+
close: () => void;
|
|
70
|
+
};
|
|
71
|
+
type SwapBuildRequest = {
|
|
72
|
+
userPublicKey: string;
|
|
73
|
+
inputMint: string;
|
|
74
|
+
outputMint: string;
|
|
75
|
+
amount: number | string;
|
|
76
|
+
slippageBps?: number;
|
|
77
|
+
swapType?: string;
|
|
78
|
+
feeWallet?: string;
|
|
79
|
+
feeBps?: number;
|
|
80
|
+
feePercent?: number;
|
|
81
|
+
};
|
|
82
|
+
type SwapBuildFees = {
|
|
83
|
+
platformFeeBps: number;
|
|
84
|
+
platformFeeLamports: number;
|
|
85
|
+
userFeeBps: number;
|
|
86
|
+
userFeeLamports: number;
|
|
87
|
+
tipLamports: number;
|
|
88
|
+
};
|
|
89
|
+
type SwapBuildResponse = {
|
|
90
|
+
transactionBase64: string;
|
|
91
|
+
fees: SwapBuildFees;
|
|
92
|
+
quote: unknown;
|
|
93
|
+
};
|
|
94
|
+
type SwapBroadcastResponse = {
|
|
95
|
+
signature: string;
|
|
96
|
+
};
|
|
97
|
+
type ThsTotals = {
|
|
98
|
+
buys: number;
|
|
99
|
+
sells: number;
|
|
100
|
+
};
|
|
101
|
+
type ThsResponse = {
|
|
102
|
+
wallet: string;
|
|
103
|
+
score: number;
|
|
104
|
+
realizedPnLUsd: number;
|
|
105
|
+
realizedPnLWeightedUsd: number;
|
|
106
|
+
totals: ThsTotals;
|
|
107
|
+
analyzedTxns: number;
|
|
108
|
+
matchedTxCount: number;
|
|
109
|
+
unmatchedTxCount: number;
|
|
110
|
+
avgHoldTimeDays: number;
|
|
111
|
+
avgHoldTimeHours: number;
|
|
112
|
+
avgHoldTimeMinutes: number;
|
|
113
|
+
avgHoldTimeSeconds: number;
|
|
114
|
+
avgHoldTimePretty: string;
|
|
115
|
+
};
|
|
116
|
+
declare class DritanClient {
|
|
117
|
+
readonly apiKey: string;
|
|
118
|
+
readonly baseUrl: string;
|
|
119
|
+
readonly wsBaseUrl: string;
|
|
120
|
+
private readonly fetchImpl;
|
|
121
|
+
private readonly WebSocketCtor;
|
|
122
|
+
constructor(options: DritanClientOptions);
|
|
123
|
+
getTokenPrice(mint: string): Promise<TokenPriceResponse>;
|
|
124
|
+
getTokenMetadata(mint: string): Promise<TokenMetadataResponse>;
|
|
125
|
+
getTokenRisk(mint: string): Promise<TokenRiskResponse>;
|
|
126
|
+
getFirstBuyers(mint: string): Promise<TokenFirstBuyersResponse>;
|
|
127
|
+
getTokenAggregated(mint: string): Promise<TokenAggregatedResponse>;
|
|
128
|
+
buildSwap(body: SwapBuildRequest): Promise<SwapBuildResponse>;
|
|
129
|
+
broadcastSwap(signedTransactionBase64: string): Promise<SwapBroadcastResponse>;
|
|
130
|
+
streamDex(dex: KnownDexStream, options?: DritanStreamOptions): DritanStreamHandle;
|
|
131
|
+
streamDex(dex: string, options?: DritanStreamOptions): DritanStreamHandle;
|
|
132
|
+
}
|
|
133
|
+
declare const createClient: (options: DritanClientOptions) => DritanClient;
|
|
134
|
+
declare class MeteoraThsClient {
|
|
135
|
+
readonly baseUrl: string;
|
|
136
|
+
private readonly fetchImpl;
|
|
137
|
+
constructor(options?: MeteoraThsClientOptions);
|
|
138
|
+
health(): Promise<boolean>;
|
|
139
|
+
getThsScore(wallet: string, options?: {
|
|
140
|
+
debug?: boolean;
|
|
141
|
+
breakdown?: boolean;
|
|
142
|
+
}): Promise<ThsResponse>;
|
|
143
|
+
getThsScoreForTokens(wallet: string, tokenMints: string[], options?: {
|
|
144
|
+
debug?: boolean;
|
|
145
|
+
breakdown?: boolean;
|
|
146
|
+
}): Promise<ThsResponse>;
|
|
147
|
+
postThsScoreForTokens(wallet: string, tokenMints: string[], options?: {
|
|
148
|
+
debug?: boolean;
|
|
149
|
+
breakdown?: boolean;
|
|
150
|
+
}): Promise<ThsResponse>;
|
|
151
|
+
}
|
|
152
|
+
declare const createMeteoraThsClient: (options?: MeteoraThsClientOptions) => MeteoraThsClient;
|
|
153
|
+
|
|
154
|
+
export { DritanClient, type DritanClientOptions, type DritanStreamHandle, type DritanStreamOptions, type KnownDexStream, MeteoraThsClient, type MeteoraThsClientOptions, type RiskGroup, type SwapBroadcastResponse, type SwapBuildFees, type SwapBuildRequest, type SwapBuildResponse, type ThsResponse, type ThsTotals, type TokenAggregatedResponse, type TokenFirstBuyersResponse, type TokenMetadataResponse, type TokenPriceResponse, type TokenRiskResponse, createClient, createMeteoraThsClient };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import WebSocketImpl from 'isomorphic-ws';
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
function buildUrl(baseUrl, path) {
|
|
5
|
+
return `${baseUrl.replace(/\/+$/, "")}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
6
|
+
}
|
|
7
|
+
function buildWsUrl(wsBaseUrl, path, query) {
|
|
8
|
+
const url = new URL(buildUrl(wsBaseUrl, path));
|
|
9
|
+
if (query) {
|
|
10
|
+
for (const [k, v] of Object.entries(query)) {
|
|
11
|
+
if (v === void 0 || v === null) continue;
|
|
12
|
+
url.searchParams.set(k, String(v));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return url.toString();
|
|
16
|
+
}
|
|
17
|
+
function safeJsonParse(payload) {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(payload);
|
|
20
|
+
} catch {
|
|
21
|
+
return payload;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isNodeRuntime() {
|
|
25
|
+
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
26
|
+
}
|
|
27
|
+
function messageToString(data) {
|
|
28
|
+
if (typeof data === "string") return data;
|
|
29
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
30
|
+
return data.toString("utf8");
|
|
31
|
+
}
|
|
32
|
+
if (data instanceof ArrayBuffer) {
|
|
33
|
+
return new TextDecoder().decode(new Uint8Array(data));
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
var DritanClient = class {
|
|
38
|
+
apiKey;
|
|
39
|
+
baseUrl;
|
|
40
|
+
wsBaseUrl;
|
|
41
|
+
fetchImpl;
|
|
42
|
+
WebSocketCtor;
|
|
43
|
+
constructor(options) {
|
|
44
|
+
this.apiKey = options.apiKey;
|
|
45
|
+
this.baseUrl = options.baseUrl ?? "https://us-east.dritan.dev";
|
|
46
|
+
this.wsBaseUrl = options.wsBaseUrl ?? "wss://us-east.dritan.dev";
|
|
47
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
48
|
+
this.WebSocketCtor = options.WebSocket ?? WebSocketImpl;
|
|
49
|
+
}
|
|
50
|
+
async getTokenPrice(mint) {
|
|
51
|
+
const url = buildUrl(this.baseUrl, `/token/price/${encodeURIComponent(mint)}`);
|
|
52
|
+
const res = await this.fetchImpl(url, {
|
|
53
|
+
method: "GET",
|
|
54
|
+
headers: {
|
|
55
|
+
"x-api-key": this.apiKey
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
if (!res.ok) {
|
|
59
|
+
const text = await res.text().catch(() => "");
|
|
60
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
61
|
+
}
|
|
62
|
+
return await res.json();
|
|
63
|
+
}
|
|
64
|
+
async getTokenMetadata(mint) {
|
|
65
|
+
const url = buildUrl(this.baseUrl, `/token/metadata/${encodeURIComponent(mint)}`);
|
|
66
|
+
const res = await this.fetchImpl(url, {
|
|
67
|
+
method: "GET",
|
|
68
|
+
headers: {
|
|
69
|
+
"x-api-key": this.apiKey
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
if (!res.ok) {
|
|
73
|
+
const text = await res.text().catch(() => "");
|
|
74
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
75
|
+
}
|
|
76
|
+
return await res.json();
|
|
77
|
+
}
|
|
78
|
+
async getTokenRisk(mint) {
|
|
79
|
+
const url = buildUrl(this.baseUrl, `/token/risk/${encodeURIComponent(mint)}`);
|
|
80
|
+
const res = await this.fetchImpl(url, {
|
|
81
|
+
method: "GET",
|
|
82
|
+
headers: {
|
|
83
|
+
"x-api-key": this.apiKey
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
const text = await res.text().catch(() => "");
|
|
88
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
89
|
+
}
|
|
90
|
+
return await res.json();
|
|
91
|
+
}
|
|
92
|
+
async getFirstBuyers(mint) {
|
|
93
|
+
const url = buildUrl(this.baseUrl, `/token/first-buyers/${encodeURIComponent(mint)}`);
|
|
94
|
+
const res = await this.fetchImpl(url, {
|
|
95
|
+
method: "GET",
|
|
96
|
+
headers: {
|
|
97
|
+
"x-api-key": this.apiKey
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
if (!res.ok) {
|
|
101
|
+
const text = await res.text().catch(() => "");
|
|
102
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
103
|
+
}
|
|
104
|
+
return await res.json();
|
|
105
|
+
}
|
|
106
|
+
async getTokenAggregated(mint) {
|
|
107
|
+
const url = buildUrl(this.baseUrl, `/token/aggregated/${encodeURIComponent(mint)}`);
|
|
108
|
+
const res = await this.fetchImpl(url, {
|
|
109
|
+
method: "GET",
|
|
110
|
+
headers: {
|
|
111
|
+
"x-api-key": this.apiKey
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
if (!res.ok) {
|
|
115
|
+
const text = await res.text().catch(() => "");
|
|
116
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
117
|
+
}
|
|
118
|
+
const raw = await res.json();
|
|
119
|
+
return {
|
|
120
|
+
mint: String(raw?.mint ?? mint),
|
|
121
|
+
price: raw?.price,
|
|
122
|
+
metadata: raw?.metadata ?? null,
|
|
123
|
+
risk: raw?.risk ?? null,
|
|
124
|
+
bondingCurvePercent: raw?.bondingCurvePercent === void 0 ? null : raw?.bondingCurvePercent ?? null
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async buildSwap(body) {
|
|
128
|
+
const url = buildUrl(this.baseUrl, "/swap/build");
|
|
129
|
+
const res = await this.fetchImpl(url, {
|
|
130
|
+
method: "POST",
|
|
131
|
+
headers: {
|
|
132
|
+
"x-api-key": this.apiKey,
|
|
133
|
+
"content-type": "application/json"
|
|
134
|
+
},
|
|
135
|
+
body: JSON.stringify(body ?? {})
|
|
136
|
+
});
|
|
137
|
+
if (!res.ok) {
|
|
138
|
+
const text = await res.text().catch(() => "");
|
|
139
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
140
|
+
}
|
|
141
|
+
return await res.json();
|
|
142
|
+
}
|
|
143
|
+
async broadcastSwap(signedTransactionBase64) {
|
|
144
|
+
const url = buildUrl(this.baseUrl, "/swap/broadcast");
|
|
145
|
+
const res = await this.fetchImpl(url, {
|
|
146
|
+
method: "POST",
|
|
147
|
+
headers: {
|
|
148
|
+
"x-api-key": this.apiKey,
|
|
149
|
+
"content-type": "application/json"
|
|
150
|
+
},
|
|
151
|
+
body: JSON.stringify({ signedTransactionBase64 })
|
|
152
|
+
});
|
|
153
|
+
if (!res.ok) {
|
|
154
|
+
const text = await res.text().catch(() => "");
|
|
155
|
+
throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);
|
|
156
|
+
}
|
|
157
|
+
return await res.json();
|
|
158
|
+
}
|
|
159
|
+
streamDex(dex, options = {}) {
|
|
160
|
+
const shouldSendKeyInQuery = options.sendApiKeyInQuery ?? !isNodeRuntime();
|
|
161
|
+
const query = { ...options.query ?? {} };
|
|
162
|
+
if (shouldSendKeyInQuery && query.apiKey == null) {
|
|
163
|
+
query.apiKey = this.apiKey;
|
|
164
|
+
}
|
|
165
|
+
const url = buildWsUrl(this.wsBaseUrl, `/${dex}`, query);
|
|
166
|
+
const ws = shouldSendKeyInQuery ? new this.WebSocketCtor(url) : new this.WebSocketCtor(
|
|
167
|
+
url,
|
|
168
|
+
{
|
|
169
|
+
headers: {
|
|
170
|
+
"x-api-key": this.apiKey
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
ws.onopen = () => options.onOpen?.();
|
|
175
|
+
ws.onclose = (ev) => options.onClose?.(ev);
|
|
176
|
+
ws.onerror = (ev) => options.onError?.(ev);
|
|
177
|
+
ws.onmessage = (msg) => {
|
|
178
|
+
const raw = messageToString(msg.data);
|
|
179
|
+
const data = raw ? safeJsonParse(raw) : msg.data;
|
|
180
|
+
options.onMessage?.(data);
|
|
181
|
+
};
|
|
182
|
+
return {
|
|
183
|
+
socket: ws,
|
|
184
|
+
close: () => ws.close()
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
var createClient = (options) => new DritanClient(options);
|
|
189
|
+
var MeteoraThsClient = class {
|
|
190
|
+
baseUrl;
|
|
191
|
+
fetchImpl;
|
|
192
|
+
constructor(options = {}) {
|
|
193
|
+
this.baseUrl = options.baseUrl ?? "https://ths.dritan.dev";
|
|
194
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
195
|
+
}
|
|
196
|
+
async health() {
|
|
197
|
+
const url = buildUrl(this.baseUrl, "/health");
|
|
198
|
+
const res = await this.fetchImpl(url, { method: "GET" });
|
|
199
|
+
return res.ok;
|
|
200
|
+
}
|
|
201
|
+
async getThsScore(wallet, options = {}) {
|
|
202
|
+
const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}`));
|
|
203
|
+
if (options.debug) url.searchParams.set("debug", "1");
|
|
204
|
+
if (options.breakdown) url.searchParams.set("breakdown", "1");
|
|
205
|
+
const res = await this.fetchImpl(url.toString(), { method: "GET" });
|
|
206
|
+
if (!res.ok) {
|
|
207
|
+
const text = await res.text().catch(() => "");
|
|
208
|
+
throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);
|
|
209
|
+
}
|
|
210
|
+
return await res.json();
|
|
211
|
+
}
|
|
212
|
+
async getThsScoreForTokens(wallet, tokenMints, options = {}) {
|
|
213
|
+
const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));
|
|
214
|
+
for (const mint of tokenMints ?? []) {
|
|
215
|
+
url.searchParams.append("tokenMints", mint);
|
|
216
|
+
}
|
|
217
|
+
if (options.debug) url.searchParams.set("debug", "1");
|
|
218
|
+
if (options.breakdown) url.searchParams.set("breakdown", "1");
|
|
219
|
+
const res = await this.fetchImpl(url.toString(), { method: "GET" });
|
|
220
|
+
if (!res.ok) {
|
|
221
|
+
const text = await res.text().catch(() => "");
|
|
222
|
+
throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);
|
|
223
|
+
}
|
|
224
|
+
return await res.json();
|
|
225
|
+
}
|
|
226
|
+
async postThsScoreForTokens(wallet, tokenMints, options = {}) {
|
|
227
|
+
const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));
|
|
228
|
+
if (options.debug) url.searchParams.set("debug", "1");
|
|
229
|
+
if (options.breakdown) url.searchParams.set("breakdown", "1");
|
|
230
|
+
const res = await this.fetchImpl(url.toString(), {
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: { "content-type": "application/json" },
|
|
233
|
+
body: JSON.stringify({ tokenMints: tokenMints ?? [] })
|
|
234
|
+
});
|
|
235
|
+
if (!res.ok) {
|
|
236
|
+
const text = await res.text().catch(() => "");
|
|
237
|
+
throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);
|
|
238
|
+
}
|
|
239
|
+
return await res.json();
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
var createMeteoraThsClient = (options) => new MeteoraThsClient(options);
|
|
243
|
+
|
|
244
|
+
export { DritanClient, MeteoraThsClient, createClient, createMeteoraThsClient };
|
|
245
|
+
//# sourceMappingURL=index.js.map
|
|
246
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import WebSocketImpl from \"isomorphic-ws\";\n\nexport type DritanClientOptions = {\n apiKey: string;\n baseUrl?: string;\n wsBaseUrl?: string;\n fetch?: typeof fetch;\n WebSocket?: typeof WebSocketImpl;\n};\n\nexport type KnownDexStream =\n | \"pumpamm\"\n | \"pumpfun\"\n | \"launchlab\"\n | \"dlmm\"\n | \"damm2\"\n | \"damm1\"\n | \"dbc\";\n\nexport type MeteoraThsClientOptions = {\n baseUrl?: string;\n fetch?: typeof fetch;\n};\n\nexport type TokenPriceResponse = {\n mint: string;\n dex: string;\n priceUsd: number;\n marketCap: number | null;\n liquiditySol: number | null;\n};\n\nexport type TokenMetadataResponse = {\n mint: string;\n programId: string;\n name: string;\n symbol: string;\n uri: string;\n decimals: number;\n supply: string;\n};\n\nexport type RiskGroup = {\n count: number;\n totalPercentage: number;\n};\n\nexport type TokenRiskResponse = {\n mint: string;\n globalFeesPaid: number;\n bundlers: RiskGroup;\n insiders: RiskGroup;\n snipers: RiskGroup;\n top10: number;\n devPercentage: number | null;\n};\n\nexport type TokenFirstBuyersResponse = {\n mint: string;\n buyers: unknown;\n};\n\nexport type TokenAggregatedResponse = {\n mint: string;\n price: TokenPriceResponse;\n metadata: TokenMetadataResponse | null;\n risk: TokenRiskResponse | null;\n bondingCurvePercent: number | null;\n};\n\nexport type DritanStreamOptions = {\n query?: Record<string, string | number | boolean | undefined | null>;\n /**\n * When true, includes the api key as `?apiKey=...` in the websocket URL.\n * This is required when using native browser websockets (custom headers are not supported).\n */\n sendApiKeyInQuery?: boolean;\n onOpen?: () => void;\n onClose?: (ev: CloseEvent) => void;\n onError?: (ev: Event) => void;\n onMessage?: (data: unknown) => void;\n};\n\nexport type DritanStreamHandle = {\n socket: WebSocket;\n close: () => void;\n};\n\nexport type SwapBuildRequest = {\n userPublicKey: string;\n inputMint: string;\n outputMint: string;\n amount: number | string;\n slippageBps?: number;\n swapType?: string;\n feeWallet?: string;\n feeBps?: number;\n feePercent?: number;\n};\n\nexport type SwapBuildFees = {\n platformFeeBps: number;\n platformFeeLamports: number;\n userFeeBps: number;\n userFeeLamports: number;\n tipLamports: number;\n};\n\nexport type SwapBuildResponse = {\n transactionBase64: string;\n fees: SwapBuildFees;\n quote: unknown;\n};\n\nexport type SwapBroadcastResponse = {\n signature: string;\n};\n\nexport type ThsTotals = {\n buys: number;\n sells: number;\n};\n\nexport type ThsResponse = {\n wallet: string;\n score: number;\n realizedPnLUsd: number;\n realizedPnLWeightedUsd: number;\n totals: ThsTotals;\n analyzedTxns: number;\n matchedTxCount: number;\n unmatchedTxCount: number;\n avgHoldTimeDays: number;\n avgHoldTimeHours: number;\n avgHoldTimeMinutes: number;\n avgHoldTimeSeconds: number;\n avgHoldTimePretty: string;\n};\n\nfunction buildUrl(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/+$/, \"\")}${path.startsWith(\"/\") ? \"\" : \"/\"}${path}`;\n}\n\nfunction buildWsUrl(\n wsBaseUrl: string,\n path: string,\n query?: Record<string, string | number | boolean | undefined | null>\n): string {\n const url = new URL(buildUrl(wsBaseUrl, path));\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined || v === null) continue;\n url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\nfunction safeJsonParse(payload: string): unknown {\n try {\n return JSON.parse(payload) as unknown;\n } catch {\n return payload;\n }\n}\n\nfunction isNodeRuntime(): boolean {\n return (\n typeof process !== \"undefined\" &&\n typeof (process as any).versions?.node === \"string\"\n );\n}\n\nfunction messageToString(data: unknown): string | null {\n if (typeof data === \"string\") return data;\n\n // ws (node) can emit Buffer\n if (typeof Buffer !== \"undefined\" && Buffer.isBuffer(data)) {\n return data.toString(\"utf8\");\n }\n\n // browser ws can emit ArrayBuffer\n if (data instanceof ArrayBuffer) {\n return new TextDecoder().decode(new Uint8Array(data));\n }\n\n return null;\n}\n\nexport class DritanClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly wsBaseUrl: string;\n private readonly fetchImpl: typeof fetch;\n private readonly WebSocketCtor: typeof WebSocketImpl;\n\n constructor(options: DritanClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://us-east.dritan.dev\";\n this.wsBaseUrl = options.wsBaseUrl ?? \"wss://us-east.dritan.dev\";\n this.fetchImpl = options.fetch ?? fetch;\n this.WebSocketCtor = options.WebSocket ?? WebSocketImpl;\n }\n\n async getTokenPrice(mint: string): Promise<TokenPriceResponse> {\n const url = buildUrl(this.baseUrl, `/token/price/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenPriceResponse;\n }\n\n async getTokenMetadata(mint: string): Promise<TokenMetadataResponse> {\n const url = buildUrl(this.baseUrl, `/token/metadata/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenMetadataResponse;\n }\n\n async getTokenRisk(mint: string): Promise<TokenRiskResponse> {\n const url = buildUrl(this.baseUrl, `/token/risk/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenRiskResponse;\n }\n\n async getFirstBuyers(mint: string): Promise<TokenFirstBuyersResponse> {\n const url = buildUrl(this.baseUrl, `/token/first-buyers/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as TokenFirstBuyersResponse;\n }\n\n async getTokenAggregated(mint: string): Promise<TokenAggregatedResponse> {\n const url = buildUrl(this.baseUrl, `/token/aggregated/${encodeURIComponent(mint)}`);\n const res = await this.fetchImpl(url, {\n method: \"GET\",\n headers: {\n \"x-api-key\": this.apiKey\n }\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n const raw = (await res.json()) as any;\n return {\n mint: String(raw?.mint ?? mint),\n price: raw?.price as TokenPriceResponse,\n metadata: raw?.metadata ?? null,\n risk: raw?.risk ?? null,\n bondingCurvePercent:\n raw?.bondingCurvePercent === undefined ? null : (raw?.bondingCurvePercent ?? null)\n };\n }\n\n async buildSwap(body: SwapBuildRequest): Promise<SwapBuildResponse> {\n const url = buildUrl(this.baseUrl, \"/swap/build\");\n const res = await this.fetchImpl(url, {\n method: \"POST\",\n headers: {\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\"\n },\n body: JSON.stringify(body ?? {})\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as SwapBuildResponse;\n }\n\n async broadcastSwap(signedTransactionBase64: string): Promise<SwapBroadcastResponse> {\n const url = buildUrl(this.baseUrl, \"/swap/broadcast\");\n const res = await this.fetchImpl(url, {\n method: \"POST\",\n headers: {\n \"x-api-key\": this.apiKey,\n \"content-type\": \"application/json\"\n },\n body: JSON.stringify({ signedTransactionBase64 })\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Dritan request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as SwapBroadcastResponse;\n }\n\n streamDex(dex: KnownDexStream, options?: DritanStreamOptions): DritanStreamHandle;\n streamDex(dex: string, options?: DritanStreamOptions): DritanStreamHandle;\n streamDex(dex: string, options: DritanStreamOptions = {}): DritanStreamHandle {\n const shouldSendKeyInQuery = options.sendApiKeyInQuery ?? !isNodeRuntime();\n const query = { ...(options.query ?? {}) } as Record<\n string,\n string | number | boolean | undefined | null\n >;\n if (shouldSendKeyInQuery && query.apiKey == null) {\n query.apiKey = this.apiKey;\n }\n\n const url = buildWsUrl(this.wsBaseUrl, `/${dex}`, query);\n const ws = shouldSendKeyInQuery\n ? new this.WebSocketCtor(url)\n : new this.WebSocketCtor(\n url,\n {\n headers: {\n \"x-api-key\": this.apiKey\n }\n } as any\n );\n\n ws.onopen = () => options.onOpen?.();\n ws.onclose = (ev: any) => options.onClose?.(ev as CloseEvent);\n ws.onerror = (ev: any) => options.onError?.(ev as Event);\n ws.onmessage = (msg: any) => {\n const raw = messageToString(msg.data);\n const data = raw ? safeJsonParse(raw) : msg.data;\n options.onMessage?.(data);\n };\n\n return {\n socket: ws as unknown as WebSocket,\n close: () => ws.close()\n };\n }\n}\n\nexport const createClient = (options: DritanClientOptions) => new DritanClient(options);\n\nexport class MeteoraThsClient {\n readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: MeteoraThsClientOptions = {}) {\n this.baseUrl = options.baseUrl ?? \"https://ths.dritan.dev\";\n this.fetchImpl = options.fetch ?? fetch;\n }\n\n async health(): Promise<boolean> {\n const url = buildUrl(this.baseUrl, \"/health\");\n const res = await this.fetchImpl(url, { method: \"GET\" });\n return res.ok;\n }\n\n async getThsScore(\n wallet: string,\n options: { debug?: boolean; breakdown?: boolean } = {}\n ): Promise<ThsResponse> {\n const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}`));\n if (options.debug) url.searchParams.set(\"debug\", \"1\");\n if (options.breakdown) url.searchParams.set(\"breakdown\", \"1\");\n\n const res = await this.fetchImpl(url.toString(), { method: \"GET\" });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as ThsResponse;\n }\n\n async getThsScoreForTokens(\n wallet: string,\n tokenMints: string[],\n options: { debug?: boolean; breakdown?: boolean } = {}\n ): Promise<ThsResponse> {\n const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));\n for (const mint of tokenMints ?? []) {\n url.searchParams.append(\"tokenMints\", mint);\n }\n if (options.debug) url.searchParams.set(\"debug\", \"1\");\n if (options.breakdown) url.searchParams.set(\"breakdown\", \"1\");\n\n const res = await this.fetchImpl(url.toString(), { method: \"GET\" });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as ThsResponse;\n }\n\n async postThsScoreForTokens(\n wallet: string,\n tokenMints: string[],\n options: { debug?: boolean; breakdown?: boolean } = {}\n ): Promise<ThsResponse> {\n const url = new URL(buildUrl(this.baseUrl, `/ths/${encodeURIComponent(wallet)}/tokens`));\n if (options.debug) url.searchParams.set(\"debug\", \"1\");\n if (options.breakdown) url.searchParams.set(\"breakdown\", \"1\");\n\n const res = await this.fetchImpl(url.toString(), {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ tokenMints: tokenMints ?? [] })\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(`Meteora THS request failed (${res.status}): ${text || res.statusText}`);\n }\n\n return (await res.json()) as ThsResponse;\n }\n}\n\nexport const createMeteoraThsClient = (options?: MeteoraThsClientOptions) =>\n new MeteoraThsClient(options);\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dritan-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript SDK for the Dritan data plane REST API and websocket streams.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/dritan/dritan"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://dritan.dev",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://dritan.dev"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "./dist/index.cjs",
|
|
16
|
+
"module": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js",
|
|
22
|
+
"require": "./dist/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"dev": "tsup --watch",
|
|
32
|
+
"lint": "tsc -p tsconfig.json --noEmit",
|
|
33
|
+
"prepublishOnly": "npm run build"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"isomorphic-ws": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^22.14.0",
|
|
40
|
+
"tsup": "^8.0.2",
|
|
41
|
+
"typescript": "^5.8.2"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
}
|
|
46
|
+
}
|