@sereel/sdk 0.1.1 → 0.1.3
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 +214 -48
- package/dist/index.cjs +47 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -9
- package/dist/index.d.ts +39 -9
- package/dist/index.js +47 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# Sereel TypeScript SDK
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for the Sereel
|
|
3
|
+
TypeScript SDK for the Sereel marketplace REST endpoints. Use it to browse
|
|
4
|
+
security tokens listed on the Sereel marketplace, inspect their compliance
|
|
5
|
+
rule engines, and filter by issuer.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
npm install @sereel/sdk
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @sereel/sdk
|
|
9
13
|
```
|
|
10
14
|
|
|
11
15
|
## Quickstart
|
|
@@ -18,104 +22,266 @@ const client = createClient({
|
|
|
18
22
|
apiKey: process.env.SEREEL_SDK_API_KEY!,
|
|
19
23
|
});
|
|
20
24
|
|
|
25
|
+
// All listed assets
|
|
21
26
|
const assets = await client.getAssets();
|
|
22
|
-
|
|
27
|
+
|
|
28
|
+
// Single asset by token address
|
|
29
|
+
const asset = await client.getAssetByTokenAddress("0xabc…");
|
|
30
|
+
|
|
31
|
+
// All assets issued by a specific issuer
|
|
32
|
+
const issuerAssets = await client.getAssetsByIssuer("64f1a2b3c4d5e6f7a8b9c0d1");
|
|
23
33
|
```
|
|
24
34
|
|
|
25
35
|
## Authentication
|
|
26
36
|
|
|
27
|
-
The SDK sends your API key in the `x-api-key` header.
|
|
28
|
-
|
|
29
|
-
Only MATATA-issued API keys are supported right now.
|
|
37
|
+
The SDK sends your API key in the `x-api-key` header.
|
|
38
|
+
Only MATATA-issued API keys are supported.
|
|
30
39
|
|
|
31
40
|
```ts
|
|
32
|
-
import { createClient } from "@sereel/sdk";
|
|
33
|
-
|
|
34
41
|
const client = createClient({
|
|
35
42
|
environment: "testnet",
|
|
36
43
|
apiKey: process.env.SEREEL_SDK_API_KEY!,
|
|
37
44
|
});
|
|
38
|
-
|
|
39
|
-
const assets = await client.getAssets();
|
|
40
45
|
```
|
|
41
46
|
|
|
42
47
|
## Environments
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
| Key | Base URL |
|
|
50
|
+
|-----|----------|
|
|
51
|
+
| `devnet` | `https://api-lazer.sereel.com` |
|
|
52
|
+
| `testnet` | `https://api-lazer-v2.sereel.com` |
|
|
53
|
+
| `mainnet` | `https://cahokia.sereel.com` |
|
|
49
54
|
|
|
50
55
|
## Client API
|
|
51
56
|
|
|
52
|
-
### `createClient`
|
|
57
|
+
### `createClient(config)`
|
|
53
58
|
|
|
54
59
|
```ts
|
|
55
60
|
import { createClient } from "@sereel/sdk";
|
|
56
61
|
|
|
57
62
|
const client = createClient({
|
|
58
|
-
environment: "testnet",
|
|
59
|
-
apiKey:
|
|
60
|
-
timeoutMs: 10_000,
|
|
63
|
+
environment: "testnet", // required
|
|
64
|
+
apiKey: "sk_matata_…", // required
|
|
65
|
+
timeoutMs: 10_000, // optional, default: 30 000
|
|
66
|
+
baseUrl: "http://localhost:8080", // optional – overrides environment URL
|
|
61
67
|
});
|
|
62
68
|
```
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### `client.getAssets()`
|
|
65
73
|
|
|
66
|
-
`
|
|
74
|
+
`GET /sdk/assets` — returns all publicly listed security tokens.
|
|
67
75
|
|
|
68
76
|
```ts
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
77
|
+
const { data, count } = await client.getAssets();
|
|
78
|
+
|
|
79
|
+
for (const record of data) {
|
|
80
|
+
console.log(record.security.token_name, record.issuer.legal_name);
|
|
81
|
+
}
|
|
74
82
|
```
|
|
75
83
|
|
|
76
|
-
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### `client.getAssetByTokenAddress(tokenAddress)`
|
|
77
87
|
|
|
78
|
-
|
|
88
|
+
`GET /sdk/assets/{token_address}` — returns a single asset by its on-chain
|
|
89
|
+
token address.
|
|
79
90
|
|
|
80
91
|
```ts
|
|
81
|
-
const
|
|
92
|
+
const { data } = await client.getAssetByTokenAddress("0xabc…");
|
|
82
93
|
|
|
83
|
-
console.log(
|
|
84
|
-
console.log(
|
|
94
|
+
console.log(data.security.token_name);
|
|
95
|
+
console.log(data.security.rule_engine?.name); // present if token has compliance rules
|
|
96
|
+
console.log(data.books.length);
|
|
85
97
|
```
|
|
86
98
|
|
|
87
|
-
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### `client.getAssetsByIssuer(issuerId)`
|
|
88
102
|
|
|
89
|
-
|
|
103
|
+
`GET /sdk/assets/issuer/{issuer_id}` — returns all assets belonging to a
|
|
104
|
+
specific issuer. The `issuerId` is the `id` field from `SdkIssuerSummary`
|
|
105
|
+
(the issuer's hex-encoded MongoDB ObjectId).
|
|
90
106
|
|
|
91
107
|
```ts
|
|
92
|
-
const
|
|
108
|
+
const { data, count } = await client.getAssetsByIssuer("64f1a2b3c4d5e6f7a8b9c0d1");
|
|
93
109
|
|
|
94
|
-
console.log(
|
|
95
|
-
console.log(
|
|
110
|
+
console.log(`${count} tokens from this issuer`);
|
|
111
|
+
data.forEach(record => console.log(record.security.token_symbol));
|
|
96
112
|
```
|
|
97
113
|
|
|
114
|
+
---
|
|
115
|
+
|
|
98
116
|
## Response shape
|
|
99
117
|
|
|
100
|
-
|
|
118
|
+
Every API method returns one or more `SdkAssetRecord` objects.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
interface SdkAssetRecord {
|
|
122
|
+
security: SdkSecurityDetails;
|
|
123
|
+
issuer: SdkIssuerSummary;
|
|
124
|
+
books: SdkBookSummary[];
|
|
125
|
+
network: NetworkDetails;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### `SdkSecurityDetails`
|
|
130
|
+
|
|
131
|
+
Full token details. Internal and sensitive fields are intentionally excluded
|
|
132
|
+
(`id`, `org_id`, `deployment_txn_hash`, `token_program_id`, `engines` (raw),
|
|
133
|
+
`extra_information_attributes`, `allowlist_manager`, `iota_*` fields,
|
|
134
|
+
`individual_token_price`, `rule_engine_id`, `updated_at`).
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
interface SdkSecurityDetails {
|
|
138
|
+
token_address: string;
|
|
139
|
+
token_name: string;
|
|
140
|
+
token_symbol: string;
|
|
141
|
+
token_decimal: string;
|
|
142
|
+
network_id: string;
|
|
143
|
+
token_type: string; // e.g. "cmtat_standard" | "cmtat_debt" | …
|
|
144
|
+
admin: string; // token admin wallet address
|
|
145
|
+
icon_url: string | null;
|
|
146
|
+
prospectus: SdkTokenProspectus | null;
|
|
147
|
+
partners: SdkTokenPartner[] | null;
|
|
148
|
+
rule_engine: SdkRuleEngineSummary | null; // present when token has compliance rules
|
|
149
|
+
created_at: string | null;
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `SdkRuleEngineSummary`
|
|
101
154
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
155
|
+
When a token has an associated compliance rule engine, it is joined into the
|
|
156
|
+
security details. Only the name, address, and a slim view of each linked rule
|
|
157
|
+
are exposed.
|
|
105
158
|
|
|
106
|
-
|
|
159
|
+
```ts
|
|
160
|
+
interface SdkRuleEngineSummary {
|
|
161
|
+
name: string;
|
|
162
|
+
rule_engine_address: string;
|
|
163
|
+
rules: SdkRuleSummary[];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
interface SdkRuleSummary {
|
|
167
|
+
rule_address: string;
|
|
168
|
+
rule_type: string; // e.g. "whitelist" | "blacklist" | "sanctions_list" | …
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Rule types:
|
|
173
|
+
|
|
174
|
+
| Value | Description |
|
|
175
|
+
|-------|-------------|
|
|
176
|
+
| `whitelist` | Only allow-listed addresses can hold the token |
|
|
177
|
+
| `blacklist` | Blocked addresses cannot hold the token |
|
|
178
|
+
| `sanctions_list` | Integrates with an external sanctions oracle |
|
|
179
|
+
| `conditional_transfer_light` | Light conditional transfer checks |
|
|
180
|
+
| `erc2980` | ERC-2980 royalty enforcement |
|
|
181
|
+
| `identity_registry` | On-chain identity linking |
|
|
182
|
+
| `max_total_supply` | Total supply cap |
|
|
183
|
+
| `spender_whitelist` | Approved spenders only |
|
|
184
|
+
| `whitelist_wrapper` | Enhanced whitelist variant |
|
|
185
|
+
|
|
186
|
+
### `SdkIssuerSummary`
|
|
187
|
+
|
|
188
|
+
Public-facing details about the organisation that issued the token.
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
interface SdkIssuerSummary {
|
|
192
|
+
id: string;
|
|
193
|
+
legal_name: string;
|
|
194
|
+
display_name: string | null;
|
|
195
|
+
jurisdiction: string;
|
|
196
|
+
website: string | null;
|
|
197
|
+
logo_url: string | null;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `SdkBookSummary`
|
|
202
|
+
|
|
203
|
+
Order-book / issuance window attached to the token.
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
interface SdkBookSummary {
|
|
207
|
+
id: string;
|
|
208
|
+
order_book_address: string;
|
|
209
|
+
status: string;
|
|
210
|
+
network_id: string;
|
|
211
|
+
subscription_start: number; // unix timestamp
|
|
212
|
+
subscription_end: number; // unix timestamp
|
|
213
|
+
prospectus_file_url: string;
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### `NetworkDetails`
|
|
218
|
+
|
|
219
|
+
On-chain network the token is deployed on.
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
interface NetworkDetails {
|
|
223
|
+
network_id: string;
|
|
224
|
+
name: string;
|
|
225
|
+
family: string; // e.g. "ethereum" | "solana" | "iota"
|
|
226
|
+
chain_id: number | null;
|
|
227
|
+
native_currency: NativeCurrency;
|
|
228
|
+
rpc_endpoint: string;
|
|
229
|
+
explorer_urls: string[];
|
|
230
|
+
can_deploy_token: boolean;
|
|
231
|
+
is_testnet: boolean;
|
|
232
|
+
is_supported: boolean;
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
107
237
|
|
|
108
238
|
## Errors
|
|
109
239
|
|
|
110
|
-
|
|
240
|
+
All errors extend `SereelSdkError`.
|
|
241
|
+
|
|
242
|
+
| Class | When thrown |
|
|
243
|
+
|-------|-------------|
|
|
244
|
+
| `InvalidConfigurationError` | Bad `createClient` options or empty method arguments |
|
|
245
|
+
| `UnauthorizedError` | API key missing or invalid (HTTP 401) |
|
|
246
|
+
| `NotFoundError` | Token address or issuer ID not found (HTTP 404) |
|
|
247
|
+
| `ServerError` | Unexpected server error (HTTP 5xx) |
|
|
248
|
+
| `TimeoutError` | Request exceeded `timeoutMs` |
|
|
249
|
+
| `MalformedResponseError` | Response body doesn't match the expected shape |
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
import {
|
|
253
|
+
NotFoundError,
|
|
254
|
+
UnauthorizedError,
|
|
255
|
+
createClient,
|
|
256
|
+
} from "@sereel/sdk";
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
const asset = await client.getAssetByTokenAddress("0xmissing");
|
|
260
|
+
} catch (err) {
|
|
261
|
+
if (err instanceof NotFoundError) {
|
|
262
|
+
console.log("Token not found");
|
|
263
|
+
} else if (err instanceof UnauthorizedError) {
|
|
264
|
+
console.log("Check your API key");
|
|
265
|
+
} else {
|
|
266
|
+
throw err;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
111
270
|
|
|
112
|
-
|
|
113
|
-
- `UnauthorizedError`
|
|
114
|
-
- `NotFoundError`
|
|
115
|
-
- `ServerError`
|
|
116
|
-
- `TimeoutError`
|
|
117
|
-
- `MalformedResponseError`
|
|
271
|
+
---
|
|
118
272
|
|
|
119
273
|
## Runtime support
|
|
120
274
|
|
|
121
|
-
The SDK is framework-agnostic and
|
|
275
|
+
The SDK is framework-agnostic and relies on the platform `fetch` API
|
|
276
|
+
(Node ≥ 18, Deno, Bun, browsers). In older runtimes, pass a compatible
|
|
277
|
+
implementation:
|
|
278
|
+
|
|
279
|
+
```ts
|
|
280
|
+
import fetch from "node-fetch";
|
|
281
|
+
|
|
282
|
+
const client = createClient({
|
|
283
|
+
environment: "testnet",
|
|
284
|
+
apiKey: process.env.SEREEL_SDK_API_KEY!,
|
|
285
|
+
fetch: fetch as unknown as typeof globalThis.fetch,
|
|
286
|
+
});
|
|
287
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -212,26 +212,53 @@ function isNullableString(value) {
|
|
|
212
212
|
function isFiniteNumber(value) {
|
|
213
213
|
return typeof value === "number" && Number.isFinite(value);
|
|
214
214
|
}
|
|
215
|
-
function isSecuritySummary(value) {
|
|
216
|
-
return isRecord(value) && isString(value.id) && isString(value.token_address) && isString(value.token_name) && isString(value.token_symbol) && isString(value.network_id) && isString(value.token_type);
|
|
217
|
-
}
|
|
218
|
-
function isSellerOrganizationSummary(value) {
|
|
219
|
-
return isRecord(value) && isString(value.id) && isString(value.legal_name) && isNullableString(value.display_name) && isString(value.jurisdiction) && isNullableString(value.website);
|
|
220
|
-
}
|
|
221
215
|
function isBoolean(value) {
|
|
222
216
|
return typeof value === "boolean";
|
|
223
217
|
}
|
|
218
|
+
function isProspectus(value) {
|
|
219
|
+
return isRecord(value) && isString(value.name) && isString(value.url);
|
|
220
|
+
}
|
|
221
|
+
function isTokenPartner(value) {
|
|
222
|
+
return isRecord(value) && isString(value.partner_name) && isString(value.partner_logo) && isString(value.partner_role);
|
|
223
|
+
}
|
|
224
|
+
function isRuleSummary(value) {
|
|
225
|
+
return isRecord(value) && isString(value.rule_address) && isString(value.rule_type);
|
|
226
|
+
}
|
|
227
|
+
function isRuleEngineSummary(value) {
|
|
228
|
+
return isRecord(value) && isString(value.name) && isString(value.rule_engine_address) && Array.isArray(value.rules) && value.rules.every(isRuleSummary);
|
|
229
|
+
}
|
|
230
|
+
function isSecurityDetails(value) {
|
|
231
|
+
if (!isRecord(value)) return false;
|
|
232
|
+
const hasRequiredStrings = isString(value.token_address) && isString(value.token_name) && isString(value.token_symbol) && isString(value.token_decimal) && isString(value.network_id) && isString(value.token_type) && isString(value.admin);
|
|
233
|
+
if (!hasRequiredStrings) return false;
|
|
234
|
+
if (!isNullableString(value.icon_url)) return false;
|
|
235
|
+
if (!isNullableString(value.created_at)) return false;
|
|
236
|
+
if (value.prospectus !== null && value.prospectus !== void 0) {
|
|
237
|
+
if (!isProspectus(value.prospectus)) return false;
|
|
238
|
+
}
|
|
239
|
+
if (value.partners !== null && value.partners !== void 0) {
|
|
240
|
+
if (!Array.isArray(value.partners) || !value.partners.every(isTokenPartner))
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
if (value.rule_engine !== null && value.rule_engine !== void 0) {
|
|
244
|
+
if (!isRuleEngineSummary(value.rule_engine)) return false;
|
|
245
|
+
}
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
function isIssuerSummary(value) {
|
|
249
|
+
return isRecord(value) && isString(value.id) && isString(value.legal_name) && isNullableString(value.display_name) && isString(value.jurisdiction) && isNullableString(value.website) && isNullableString(value.logo_url);
|
|
250
|
+
}
|
|
224
251
|
function isNativeCurrency(value) {
|
|
225
252
|
return isRecord(value) && isString(value.symbol) && isString(value.name) && isFiniteNumber(value.decimals);
|
|
226
253
|
}
|
|
227
254
|
function isNetworkDetails(value) {
|
|
228
|
-
return isRecord(value) && isString(value.network_id) && isString(value.name) && isString(value.family) && (isFiniteNumber(value.chain_id) || value.chain_id === null) && isNativeCurrency(value.native_currency) && isString(value.rpc_endpoint) && Array.isArray(value.explorer_urls) && value.explorer_urls.every(isString) && isBoolean(value.
|
|
255
|
+
return isRecord(value) && isString(value.network_id) && isString(value.name) && isString(value.family) && (isFiniteNumber(value.chain_id) || value.chain_id === null) && isNativeCurrency(value.native_currency) && isString(value.rpc_endpoint) && Array.isArray(value.explorer_urls) && value.explorer_urls.every(isString) && isBoolean(value.can_deploy_cmtat_token) && isBoolean(value.can_deploy_trex_token) && isBoolean(value.is_testnet) && isBoolean(value.is_supported);
|
|
229
256
|
}
|
|
230
257
|
function isBookSummary(value) {
|
|
231
|
-
return isRecord(value) && isString(value.id) && isString(value.order_book_address) && isString(value.status) && isString(value.network_id) && isFiniteNumber(value.subscription_start) && isFiniteNumber(value.subscription_end)
|
|
258
|
+
return isRecord(value) && isString(value.id) && isString(value.order_book_address) && isString(value.status) && isString(value.network_id) && isFiniteNumber(value.subscription_start) && isFiniteNumber(value.subscription_end);
|
|
232
259
|
}
|
|
233
260
|
function isAssetRecord(value) {
|
|
234
|
-
return isRecord(value) &&
|
|
261
|
+
return isRecord(value) && isSecurityDetails(value.security) && isIssuerSummary(value.issuer) && Array.isArray(value.books) && value.books.every(isBookSummary) && isNetworkDetails(value.network);
|
|
235
262
|
}
|
|
236
263
|
function validateSdkAssetsResponse(value) {
|
|
237
264
|
if (!isRecord(value) || !Array.isArray(value.data) || !isFiniteNumber(value.count) || !value.data.every(isAssetRecord)) {
|
|
@@ -271,6 +298,17 @@ function createClient(config) {
|
|
|
271
298
|
`/sdk/assets/${encodeURIComponent(trimmedTokenAddress)}`,
|
|
272
299
|
validateSdkAssetResponse
|
|
273
300
|
);
|
|
301
|
+
},
|
|
302
|
+
getAssetsByIssuer(issuerId) {
|
|
303
|
+
const trimmedIssuerId = issuerId.trim();
|
|
304
|
+
if (!trimmedIssuerId) {
|
|
305
|
+
throw new InvalidConfigurationError("issuerId must not be empty.");
|
|
306
|
+
}
|
|
307
|
+
return requestJson(
|
|
308
|
+
resolved,
|
|
309
|
+
`/sdk/assets/issuer/${encodeURIComponent(trimmedIssuerId)}`,
|
|
310
|
+
validateSdkAssetsResponse
|
|
311
|
+
);
|
|
274
312
|
}
|
|
275
313
|
};
|
|
276
314
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/config.ts","../src/transport.ts","../src/validation.ts","../src/client.ts"],"sourcesContent":["export { createClient } from \"./client\";\nexport { ENVIRONMENT_BASE_URLS, resolveBaseUrl } from \"./config\";\nexport {\n HttpError,\n InvalidConfigurationError,\n MalformedResponseError,\n NotFoundError,\n ServerError,\n SereelSdkError,\n TimeoutError,\n UnauthorizedError,\n} from \"./errors\";\nexport type {\n ClientConfig,\n NativeCurrency,\n NetworkDetails,\n SdkAssetRecord,\n SdkAssetResponse,\n SdkAssetsResponse,\n SdkBookSummary,\n SdkSecuritySummary,\n SdkSellerOrganizationSummary,\n SereelEnvironment,\n SereelSdkClient,\n} from \"./types\";\n","export interface SereelSdkErrorOptions {\n status?: number;\n code?: string;\n cause?: unknown;\n details?: unknown;\n}\n\nexport class SereelSdkError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n readonly details?: unknown;\n\n constructor(message: string, options: SereelSdkErrorOptions = {}) {\n super(message, options.cause ? { cause: options.cause } : undefined);\n this.name = new.target.name;\n this.status = options.status;\n this.code = options.code;\n this.details = options.details;\n }\n}\n\nexport class InvalidConfigurationError extends SereelSdkError {}\n\nexport class HttpError extends SereelSdkError {}\n\nexport class UnauthorizedError extends HttpError {}\n\nexport class NotFoundError extends HttpError {}\n\nexport class ServerError extends HttpError {}\n\nexport class TimeoutError extends SereelSdkError {}\n\nexport class MalformedResponseError extends SereelSdkError {}\n","import { InvalidConfigurationError } from \"./errors\";\nimport type { ClientConfig, SereelEnvironment } from \"./types\";\n\nexport const ENVIRONMENT_BASE_URLS: Record<SereelEnvironment, string> = {\n devnet: \"https://api-lazer.sereel.com\",\n testnet: \"https://api-lazer-v2.sereel.com\",\n mainnet: \"https://cahokia.sereel.com\",\n};\n\nexport interface ResolvedClientConfig {\n environment: SereelEnvironment;\n apiKey: string;\n timeoutMs: number;\n baseUrl: string;\n fetch: typeof fetch;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction getFetchImplementation(\n providedFetch: ClientConfig[\"fetch\"],\n): typeof fetch {\n if (providedFetch) {\n return providedFetch;\n }\n\n if (typeof globalThis.fetch === \"function\") {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new InvalidConfigurationError(\n \"No fetch implementation is available. Provide config.fetch in this runtime.\",\n );\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const trimmed = baseUrl.trim();\n\n if (!trimmed) {\n throw new InvalidConfigurationError(\"baseUrl must not be empty when provided.\");\n }\n\n try {\n return new URL(trimmed).toString().replace(/\\/+$/, \"\");\n } catch (cause) {\n throw new InvalidConfigurationError(\"baseUrl must be a valid absolute URL.\", {\n cause,\n });\n }\n}\n\nexport function resolveBaseUrl(\n environment: SereelEnvironment,\n baseUrl?: string,\n): string {\n if (baseUrl) {\n return normalizeBaseUrl(baseUrl);\n }\n\n return ENVIRONMENT_BASE_URLS[environment];\n}\n\nexport function resolveClientConfig(config: ClientConfig): ResolvedClientConfig {\n const apiKey = config.apiKey.trim();\n\n if (!apiKey) {\n throw new InvalidConfigurationError(\"apiKey must not be empty.\");\n }\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new InvalidConfigurationError(\"timeoutMs must be a positive number.\");\n }\n\n return {\n environment: config.environment,\n apiKey,\n timeoutMs,\n baseUrl: resolveBaseUrl(config.environment, config.baseUrl),\n fetch: getFetchImplementation(config.fetch),\n };\n}\n","import {\n HttpError,\n MalformedResponseError,\n NotFoundError,\n ServerError,\n TimeoutError,\n UnauthorizedError,\n} from \"./errors\";\nimport type { ResolvedClientConfig } from \"./config\";\n\ninterface ApiErrorBody {\n error?: string;\n message?: string;\n}\n\nfunction createTimeoutSignal(timeoutMs: number): {\n signal: AbortSignal;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n return {\n signal: controller.signal,\n cleanup: () => clearTimeout(timeout),\n };\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const text = await response.text();\n if (!text) {\n return null;\n }\n\n try {\n return JSON.parse(text) as unknown;\n } catch (cause) {\n throw new MalformedResponseError(\"Received a non-JSON response body.\", {\n cause,\n status: response.status,\n details: text,\n });\n }\n}\n\nfunction getErrorMessage(status: number, body: unknown): string {\n if (body && typeof body === \"object\") {\n const apiError = body as ApiErrorBody;\n if (typeof apiError.error === \"string\" && apiError.error.trim()) {\n return apiError.error;\n }\n if (typeof apiError.message === \"string\" && apiError.message.trim()) {\n return apiError.message;\n }\n }\n\n return `Request failed with status ${status}.`;\n}\n\nfunction toHttpError(status: number, body: unknown): HttpError {\n const message = getErrorMessage(status, body);\n const options = { status, details: body };\n\n if (status === 401) {\n return new UnauthorizedError(message, options);\n }\n if (status === 404) {\n return new NotFoundError(message, options);\n }\n if (status >= 500) {\n return new ServerError(message, options);\n }\n\n return new HttpError(message, options);\n}\n\nexport async function requestJson<T>(\n config: ResolvedClientConfig,\n path: string,\n validate: (value: unknown) => T,\n): Promise<T> {\n const { signal, cleanup } = createTimeoutSignal(config.timeoutMs);\n\n try {\n const response = await config.fetch(`${config.baseUrl}${path}`, {\n method: \"GET\",\n signal,\n headers: {\n accept: \"application/json\",\n \"x-api-key\": config.apiKey,\n },\n });\n\n const body = await parseBody(response);\n if (!response.ok) {\n throw toHttpError(response.status, body);\n }\n\n return validate(body);\n } catch (error) {\n if (error instanceof HttpError || error instanceof MalformedResponseError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new TimeoutError(\n `Request timed out after ${config.timeoutMs}ms.`,\n { cause: error },\n );\n }\n\n throw error;\n } finally {\n cleanup();\n }\n}\n","import { MalformedResponseError } from \"./errors\";\nimport type {\n NativeCurrency,\n NetworkDetails,\n SdkAssetRecord,\n SdkAssetResponse,\n SdkAssetsResponse,\n SdkBookSummary,\n SdkSecuritySummary,\n SdkSellerOrganizationSummary,\n} from \"./types\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return typeof value === \"string\" || value === null;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isSecuritySummary(value: unknown): value is SdkSecuritySummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.token_address) &&\n isString(value.token_name) &&\n isString(value.token_symbol) &&\n isString(value.network_id) &&\n isString(value.token_type)\n );\n}\n\nfunction isSellerOrganizationSummary(\n value: unknown,\n): value is SdkSellerOrganizationSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.legal_name) &&\n isNullableString(value.display_name) &&\n isString(value.jurisdiction) &&\n isNullableString(value.website)\n );\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === \"boolean\";\n}\n\nfunction isNativeCurrency(value: unknown): value is NativeCurrency {\n return (\n isRecord(value) &&\n isString(value.symbol) &&\n isString(value.name) &&\n isFiniteNumber(value.decimals)\n );\n}\n\nfunction isNetworkDetails(value: unknown): value is NetworkDetails {\n return (\n isRecord(value) &&\n isString(value.network_id) &&\n isString(value.name) &&\n isString(value.family) &&\n (isFiniteNumber(value.chain_id) || value.chain_id === null) &&\n isNativeCurrency(value.native_currency) &&\n isString(value.rpc_endpoint) &&\n Array.isArray(value.explorer_urls) &&\n (value.explorer_urls as unknown[]).every(isString) &&\n isBoolean(value.can_deploy_token) &&\n isBoolean(value.is_testnet) &&\n isBoolean(value.is_supported)\n );\n}\n\nfunction isBookSummary(value: unknown): value is SdkBookSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.order_book_address) &&\n isString(value.status) &&\n isString(value.network_id) &&\n isFiniteNumber(value.subscription_start) &&\n isFiniteNumber(value.subscription_end) &&\n isString(value.prospectus_file_url)\n );\n}\n\nfunction isAssetRecord(value: unknown): value is SdkAssetRecord {\n return (\n isRecord(value) &&\n isSecuritySummary(value.security) &&\n isSellerOrganizationSummary(value.seller_organization) &&\n Array.isArray(value.books) &&\n value.books.every(isBookSummary) &&\n isNetworkDetails(value.network)\n );\n}\n\nexport function validateSdkAssetsResponse(value: unknown): SdkAssetsResponse {\n if (\n !isRecord(value) ||\n !Array.isArray(value.data) ||\n !isFiniteNumber(value.count) ||\n !value.data.every(isAssetRecord)\n ) {\n throw new MalformedResponseError(\n \"Received an invalid SDK assets response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetsResponse;\n}\n\nexport function validateSdkAssetResponse(value: unknown): SdkAssetResponse {\n if (!isRecord(value) || !isAssetRecord(value.data)) {\n throw new MalformedResponseError(\n \"Received an invalid SDK asset response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetResponse;\n}\n","import { resolveClientConfig } from \"./config\";\nimport { InvalidConfigurationError } from \"./errors\";\nimport { requestJson } from \"./transport\";\nimport type {\n ClientConfig,\n SdkAssetResponse,\n SdkAssetsResponse,\n SereelSdkClient,\n} from \"./types\";\nimport {\n validateSdkAssetResponse,\n validateSdkAssetsResponse,\n} from \"./validation\";\n\nexport function createClient(config: ClientConfig): SereelSdkClient {\n const resolved = resolveClientConfig(config);\n\n return {\n getAssets(): Promise<SdkAssetsResponse> {\n return requestJson(resolved, \"/sdk/assets\", validateSdkAssetsResponse);\n },\n\n getAssetByTokenAddress(tokenAddress: string): Promise<SdkAssetResponse> {\n const trimmedTokenAddress = tokenAddress.trim();\n if (!trimmedTokenAddress) {\n throw new InvalidConfigurationError(\n \"tokenAddress must not be empty.\",\n );\n }\n\n return requestJson(\n resolved,\n `/sdk/assets/${encodeURIComponent(trimmedTokenAddress)}`,\n validateSdkAssetResponse,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/config.ts","../src/transport.ts","../src/validation.ts","../src/client.ts"],"sourcesContent":["export { createClient } from \"./client\";\nexport { ENVIRONMENT_BASE_URLS, resolveBaseUrl } from \"./config\";\nexport {\n HttpError,\n InvalidConfigurationError,\n MalformedResponseError,\n NotFoundError,\n ServerError,\n SereelSdkError,\n TimeoutError,\n UnauthorizedError,\n} from \"./errors\";\nexport type {\n ClientConfig,\n NativeCurrency,\n NetworkDetails,\n SdkAssetRecord,\n SdkAssetResponse,\n SdkAssetsResponse,\n SdkBookSummary,\n SdkIssuerSummary,\n SdkRuleEngineSummary,\n SdkRuleSummary,\n SdkSecurityDetails,\n SdkTokenPartner,\n SdkTokenProspectus,\n SereelEnvironment,\n SereelSdkClient,\n} from \"./types\";\n","export interface SereelSdkErrorOptions {\n status?: number;\n code?: string;\n cause?: unknown;\n details?: unknown;\n}\n\nexport class SereelSdkError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n readonly details?: unknown;\n\n constructor(message: string, options: SereelSdkErrorOptions = {}) {\n super(message, options.cause ? { cause: options.cause } : undefined);\n this.name = new.target.name;\n this.status = options.status;\n this.code = options.code;\n this.details = options.details;\n }\n}\n\nexport class InvalidConfigurationError extends SereelSdkError {}\n\nexport class HttpError extends SereelSdkError {}\n\nexport class UnauthorizedError extends HttpError {}\n\nexport class NotFoundError extends HttpError {}\n\nexport class ServerError extends HttpError {}\n\nexport class TimeoutError extends SereelSdkError {}\n\nexport class MalformedResponseError extends SereelSdkError {}\n","import { InvalidConfigurationError } from \"./errors\";\nimport type { ClientConfig, SereelEnvironment } from \"./types\";\n\nexport const ENVIRONMENT_BASE_URLS: Record<SereelEnvironment, string> = {\n devnet: \"https://api-lazer.sereel.com\",\n testnet: \"https://api-lazer-v2.sereel.com\",\n mainnet: \"https://cahokia.sereel.com\",\n};\n\nexport interface ResolvedClientConfig {\n environment: SereelEnvironment;\n apiKey: string;\n timeoutMs: number;\n baseUrl: string;\n fetch: typeof fetch;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction getFetchImplementation(\n providedFetch: ClientConfig[\"fetch\"],\n): typeof fetch {\n if (providedFetch) {\n return providedFetch;\n }\n\n if (typeof globalThis.fetch === \"function\") {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new InvalidConfigurationError(\n \"No fetch implementation is available. Provide config.fetch in this runtime.\",\n );\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const trimmed = baseUrl.trim();\n\n if (!trimmed) {\n throw new InvalidConfigurationError(\"baseUrl must not be empty when provided.\");\n }\n\n try {\n return new URL(trimmed).toString().replace(/\\/+$/, \"\");\n } catch (cause) {\n throw new InvalidConfigurationError(\"baseUrl must be a valid absolute URL.\", {\n cause,\n });\n }\n}\n\nexport function resolveBaseUrl(\n environment: SereelEnvironment,\n baseUrl?: string,\n): string {\n if (baseUrl) {\n return normalizeBaseUrl(baseUrl);\n }\n\n return ENVIRONMENT_BASE_URLS[environment];\n}\n\nexport function resolveClientConfig(config: ClientConfig): ResolvedClientConfig {\n const apiKey = config.apiKey.trim();\n\n if (!apiKey) {\n throw new InvalidConfigurationError(\"apiKey must not be empty.\");\n }\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new InvalidConfigurationError(\"timeoutMs must be a positive number.\");\n }\n\n return {\n environment: config.environment,\n apiKey,\n timeoutMs,\n baseUrl: resolveBaseUrl(config.environment, config.baseUrl),\n fetch: getFetchImplementation(config.fetch),\n };\n}\n","import {\n HttpError,\n MalformedResponseError,\n NotFoundError,\n ServerError,\n TimeoutError,\n UnauthorizedError,\n} from \"./errors\";\nimport type { ResolvedClientConfig } from \"./config\";\n\ninterface ApiErrorBody {\n error?: string;\n message?: string;\n}\n\nfunction createTimeoutSignal(timeoutMs: number): {\n signal: AbortSignal;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n return {\n signal: controller.signal,\n cleanup: () => clearTimeout(timeout),\n };\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const text = await response.text();\n if (!text) {\n return null;\n }\n\n try {\n return JSON.parse(text) as unknown;\n } catch (cause) {\n throw new MalformedResponseError(\"Received a non-JSON response body.\", {\n cause,\n status: response.status,\n details: text,\n });\n }\n}\n\nfunction getErrorMessage(status: number, body: unknown): string {\n if (body && typeof body === \"object\") {\n const apiError = body as ApiErrorBody;\n if (typeof apiError.error === \"string\" && apiError.error.trim()) {\n return apiError.error;\n }\n if (typeof apiError.message === \"string\" && apiError.message.trim()) {\n return apiError.message;\n }\n }\n\n return `Request failed with status ${status}.`;\n}\n\nfunction toHttpError(status: number, body: unknown): HttpError {\n const message = getErrorMessage(status, body);\n const options = { status, details: body };\n\n if (status === 401) {\n return new UnauthorizedError(message, options);\n }\n if (status === 404) {\n return new NotFoundError(message, options);\n }\n if (status >= 500) {\n return new ServerError(message, options);\n }\n\n return new HttpError(message, options);\n}\n\nexport async function requestJson<T>(\n config: ResolvedClientConfig,\n path: string,\n validate: (value: unknown) => T,\n): Promise<T> {\n const { signal, cleanup } = createTimeoutSignal(config.timeoutMs);\n\n try {\n const response = await config.fetch(`${config.baseUrl}${path}`, {\n method: \"GET\",\n signal,\n headers: {\n accept: \"application/json\",\n \"x-api-key\": config.apiKey,\n },\n });\n\n const body = await parseBody(response);\n if (!response.ok) {\n throw toHttpError(response.status, body);\n }\n\n return validate(body);\n } catch (error) {\n if (error instanceof HttpError || error instanceof MalformedResponseError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new TimeoutError(\n `Request timed out after ${config.timeoutMs}ms.`,\n { cause: error },\n );\n }\n\n throw error;\n } finally {\n cleanup();\n }\n}\n","import { MalformedResponseError } from \"./errors\";\nimport type {\n NativeCurrency,\n NetworkDetails,\n SdkAssetRecord,\n SdkAssetResponse,\n SdkAssetsResponse,\n SdkBookSummary,\n SdkIssuerSummary,\n SdkRuleEngineSummary,\n SdkRuleSummary,\n SdkSecurityDetails,\n SdkTokenPartner,\n SdkTokenProspectus,\n} from \"./types\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return typeof value === \"string\" || value === null;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === \"boolean\";\n}\n\nfunction isProspectus(value: unknown): value is SdkTokenProspectus {\n return isRecord(value) && isString(value.name) && isString(value.url);\n}\n\nfunction isTokenPartner(value: unknown): value is SdkTokenPartner {\n return (\n isRecord(value) &&\n isString(value.partner_name) &&\n isString(value.partner_logo) &&\n isString(value.partner_role)\n );\n}\n\nfunction isRuleSummary(value: unknown): value is SdkRuleSummary {\n return (\n isRecord(value) &&\n isString(value.rule_address) &&\n isString(value.rule_type)\n );\n}\n\nfunction isRuleEngineSummary(value: unknown): value is SdkRuleEngineSummary {\n return (\n isRecord(value) &&\n isString(value.name) &&\n isString(value.rule_engine_address) &&\n Array.isArray(value.rules) &&\n (value.rules as unknown[]).every(isRuleSummary)\n );\n}\n\nfunction isSecurityDetails(value: unknown): value is SdkSecurityDetails {\n if (!isRecord(value)) return false;\n\n const hasRequiredStrings =\n isString(value.token_address) &&\n isString(value.token_name) &&\n isString(value.token_symbol) &&\n isString(value.token_decimal) &&\n isString(value.network_id) &&\n isString(value.token_type) &&\n isString(value.admin);\n\n if (!hasRequiredStrings) return false;\n\n if (!isNullableString(value.icon_url)) return false;\n if (!isNullableString(value.created_at)) return false;\n\n if (value.prospectus !== null && value.prospectus !== undefined) {\n if (!isProspectus(value.prospectus)) return false;\n }\n\n if (value.partners !== null && value.partners !== undefined) {\n if (\n !Array.isArray(value.partners) ||\n !(value.partners as unknown[]).every(isTokenPartner)\n )\n return false;\n }\n\n if (value.rule_engine !== null && value.rule_engine !== undefined) {\n if (!isRuleEngineSummary(value.rule_engine)) return false;\n }\n\n return true;\n}\n\nfunction isIssuerSummary(value: unknown): value is SdkIssuerSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.legal_name) &&\n isNullableString(value.display_name) &&\n isString(value.jurisdiction) &&\n isNullableString(value.website) &&\n isNullableString(value.logo_url)\n );\n}\n\nfunction isNativeCurrency(value: unknown): value is NativeCurrency {\n return (\n isRecord(value) &&\n isString(value.symbol) &&\n isString(value.name) &&\n isFiniteNumber(value.decimals)\n );\n}\n\nfunction isNetworkDetails(value: unknown): value is NetworkDetails {\n return (\n isRecord(value) &&\n isString(value.network_id) &&\n isString(value.name) &&\n isString(value.family) &&\n (isFiniteNumber(value.chain_id) || value.chain_id === null) &&\n isNativeCurrency(value.native_currency) &&\n isString(value.rpc_endpoint) &&\n Array.isArray(value.explorer_urls) &&\n (value.explorer_urls as unknown[]).every(isString) &&\n isBoolean(value.can_deploy_cmtat_token) &&\n isBoolean(value.can_deploy_trex_token) &&\n isBoolean(value.is_testnet) &&\n isBoolean(value.is_supported)\n );\n}\n\nfunction isBookSummary(value: unknown): value is SdkBookSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.order_book_address) &&\n isString(value.status) &&\n isString(value.network_id) &&\n isFiniteNumber(value.subscription_start) &&\n isFiniteNumber(value.subscription_end)\n );\n}\n\nfunction isAssetRecord(value: unknown): value is SdkAssetRecord {\n return (\n isRecord(value) &&\n isSecurityDetails(value.security) &&\n isIssuerSummary(value.issuer) &&\n Array.isArray(value.books) &&\n value.books.every(isBookSummary) &&\n isNetworkDetails(value.network)\n );\n}\n\nexport function validateSdkAssetsResponse(value: unknown): SdkAssetsResponse {\n if (\n !isRecord(value) ||\n !Array.isArray(value.data) ||\n !isFiniteNumber(value.count) ||\n !value.data.every(isAssetRecord)\n ) {\n throw new MalformedResponseError(\n \"Received an invalid SDK assets response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetsResponse;\n}\n\nexport function validateSdkAssetResponse(value: unknown): SdkAssetResponse {\n if (!isRecord(value) || !isAssetRecord(value.data)) {\n throw new MalformedResponseError(\n \"Received an invalid SDK asset response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetResponse;\n}\n","import { resolveClientConfig } from \"./config\";\nimport { InvalidConfigurationError } from \"./errors\";\nimport { requestJson } from \"./transport\";\nimport type {\n ClientConfig,\n SdkAssetResponse,\n SdkAssetsResponse,\n SereelSdkClient,\n} from \"./types\";\nimport {\n validateSdkAssetResponse,\n validateSdkAssetsResponse,\n} from \"./validation\";\n\nexport function createClient(config: ClientConfig): SereelSdkClient {\n const resolved = resolveClientConfig(config);\n\n return {\n getAssets(): Promise<SdkAssetsResponse> {\n return requestJson(resolved, \"/sdk/assets\", validateSdkAssetsResponse);\n },\n\n getAssetByTokenAddress(tokenAddress: string): Promise<SdkAssetResponse> {\n const trimmedTokenAddress = tokenAddress.trim();\n if (!trimmedTokenAddress) {\n throw new InvalidConfigurationError(\n \"tokenAddress must not be empty.\",\n );\n }\n\n return requestJson(\n resolved,\n `/sdk/assets/${encodeURIComponent(trimmedTokenAddress)}`,\n validateSdkAssetResponse,\n );\n },\n\n getAssetsByIssuer(issuerId: string): Promise<SdkAssetsResponse> {\n const trimmedIssuerId = issuerId.trim();\n if (!trimmedIssuerId) {\n throw new InvalidConfigurationError(\"issuerId must not be empty.\");\n }\n\n return requestJson(\n resolved,\n `/sdk/assets/issuer/${encodeURIComponent(trimmedIssuerId)}`,\n validateSdkAssetsResponse,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -19,37 +19,66 @@ interface NetworkDetails {
|
|
|
19
19
|
native_currency: NativeCurrency;
|
|
20
20
|
rpc_endpoint: string;
|
|
21
21
|
explorer_urls: string[];
|
|
22
|
-
|
|
22
|
+
can_deploy_cmtat_token: boolean;
|
|
23
|
+
can_deploy_trex_token: boolean;
|
|
23
24
|
is_testnet: boolean;
|
|
24
25
|
is_supported: boolean;
|
|
25
26
|
}
|
|
26
|
-
interface
|
|
27
|
-
|
|
27
|
+
interface SdkTokenProspectus {
|
|
28
|
+
name: string;
|
|
29
|
+
url: string;
|
|
30
|
+
}
|
|
31
|
+
interface SdkTokenPartner {
|
|
32
|
+
partner_name: string;
|
|
33
|
+
partner_logo: string;
|
|
34
|
+
partner_role: string;
|
|
35
|
+
}
|
|
36
|
+
interface SdkRuleSummary {
|
|
37
|
+
rule_address: string;
|
|
38
|
+
rule_type: string;
|
|
39
|
+
}
|
|
40
|
+
interface SdkRuleEngineSummary {
|
|
41
|
+
name: string;
|
|
42
|
+
rule_engine_address: string;
|
|
43
|
+
rules: SdkRuleSummary[];
|
|
44
|
+
}
|
|
45
|
+
/** Full security token details. Sensitive/internal fields are excluded. */
|
|
46
|
+
interface SdkSecurityDetails {
|
|
28
47
|
token_address: string;
|
|
29
48
|
token_name: string;
|
|
30
49
|
token_symbol: string;
|
|
50
|
+
token_decimal: string;
|
|
31
51
|
network_id: string;
|
|
32
52
|
token_type: string;
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
admin: string;
|
|
54
|
+
icon_url: string | null;
|
|
55
|
+
prospectus: SdkTokenProspectus | null;
|
|
56
|
+
partners: SdkTokenPartner[] | null;
|
|
57
|
+
rule_engine: SdkRuleEngineSummary | null;
|
|
58
|
+
created_at: string | null;
|
|
59
|
+
trex_claim_topics: number[] | null;
|
|
60
|
+
trex_issuers: string[] | null;
|
|
61
|
+
}
|
|
62
|
+
interface SdkIssuerSummary {
|
|
35
63
|
id: string;
|
|
36
64
|
legal_name: string;
|
|
37
65
|
display_name: string | null;
|
|
38
66
|
jurisdiction: string;
|
|
39
67
|
website: string | null;
|
|
68
|
+
logo_url: string | null;
|
|
40
69
|
}
|
|
41
70
|
interface SdkBookSummary {
|
|
42
71
|
id: string;
|
|
43
72
|
order_book_address: string;
|
|
44
73
|
status: string;
|
|
74
|
+
book_type: string | null;
|
|
45
75
|
network_id: string;
|
|
46
76
|
subscription_start: number;
|
|
47
77
|
subscription_end: number;
|
|
48
|
-
prospectus_file_url: string;
|
|
49
78
|
}
|
|
50
79
|
interface SdkAssetRecord {
|
|
51
|
-
security:
|
|
52
|
-
|
|
80
|
+
security: SdkSecurityDetails;
|
|
81
|
+
issuer: SdkIssuerSummary;
|
|
53
82
|
books: SdkBookSummary[];
|
|
54
83
|
network: NetworkDetails;
|
|
55
84
|
}
|
|
@@ -63,6 +92,7 @@ interface SdkAssetResponse {
|
|
|
63
92
|
interface SereelSdkClient {
|
|
64
93
|
getAssets(): Promise<SdkAssetsResponse>;
|
|
65
94
|
getAssetByTokenAddress(tokenAddress: string): Promise<SdkAssetResponse>;
|
|
95
|
+
getAssetsByIssuer(issuerId: string): Promise<SdkAssetsResponse>;
|
|
66
96
|
}
|
|
67
97
|
|
|
68
98
|
declare function createClient(config: ClientConfig): SereelSdkClient;
|
|
@@ -97,4 +127,4 @@ declare class TimeoutError extends SereelSdkError {
|
|
|
97
127
|
declare class MalformedResponseError extends SereelSdkError {
|
|
98
128
|
}
|
|
99
129
|
|
|
100
|
-
export { type ClientConfig, ENVIRONMENT_BASE_URLS, HttpError, InvalidConfigurationError, MalformedResponseError, type NativeCurrency, type NetworkDetails, NotFoundError, type SdkAssetRecord, type SdkAssetResponse, type SdkAssetsResponse, type SdkBookSummary, type
|
|
130
|
+
export { type ClientConfig, ENVIRONMENT_BASE_URLS, HttpError, InvalidConfigurationError, MalformedResponseError, type NativeCurrency, type NetworkDetails, NotFoundError, type SdkAssetRecord, type SdkAssetResponse, type SdkAssetsResponse, type SdkBookSummary, type SdkIssuerSummary, type SdkRuleEngineSummary, type SdkRuleSummary, type SdkSecurityDetails, type SdkTokenPartner, type SdkTokenProspectus, type SereelEnvironment, type SereelSdkClient, SereelSdkError, ServerError, TimeoutError, UnauthorizedError, createClient, resolveBaseUrl };
|
package/dist/index.d.ts
CHANGED
|
@@ -19,37 +19,66 @@ interface NetworkDetails {
|
|
|
19
19
|
native_currency: NativeCurrency;
|
|
20
20
|
rpc_endpoint: string;
|
|
21
21
|
explorer_urls: string[];
|
|
22
|
-
|
|
22
|
+
can_deploy_cmtat_token: boolean;
|
|
23
|
+
can_deploy_trex_token: boolean;
|
|
23
24
|
is_testnet: boolean;
|
|
24
25
|
is_supported: boolean;
|
|
25
26
|
}
|
|
26
|
-
interface
|
|
27
|
-
|
|
27
|
+
interface SdkTokenProspectus {
|
|
28
|
+
name: string;
|
|
29
|
+
url: string;
|
|
30
|
+
}
|
|
31
|
+
interface SdkTokenPartner {
|
|
32
|
+
partner_name: string;
|
|
33
|
+
partner_logo: string;
|
|
34
|
+
partner_role: string;
|
|
35
|
+
}
|
|
36
|
+
interface SdkRuleSummary {
|
|
37
|
+
rule_address: string;
|
|
38
|
+
rule_type: string;
|
|
39
|
+
}
|
|
40
|
+
interface SdkRuleEngineSummary {
|
|
41
|
+
name: string;
|
|
42
|
+
rule_engine_address: string;
|
|
43
|
+
rules: SdkRuleSummary[];
|
|
44
|
+
}
|
|
45
|
+
/** Full security token details. Sensitive/internal fields are excluded. */
|
|
46
|
+
interface SdkSecurityDetails {
|
|
28
47
|
token_address: string;
|
|
29
48
|
token_name: string;
|
|
30
49
|
token_symbol: string;
|
|
50
|
+
token_decimal: string;
|
|
31
51
|
network_id: string;
|
|
32
52
|
token_type: string;
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
admin: string;
|
|
54
|
+
icon_url: string | null;
|
|
55
|
+
prospectus: SdkTokenProspectus | null;
|
|
56
|
+
partners: SdkTokenPartner[] | null;
|
|
57
|
+
rule_engine: SdkRuleEngineSummary | null;
|
|
58
|
+
created_at: string | null;
|
|
59
|
+
trex_claim_topics: number[] | null;
|
|
60
|
+
trex_issuers: string[] | null;
|
|
61
|
+
}
|
|
62
|
+
interface SdkIssuerSummary {
|
|
35
63
|
id: string;
|
|
36
64
|
legal_name: string;
|
|
37
65
|
display_name: string | null;
|
|
38
66
|
jurisdiction: string;
|
|
39
67
|
website: string | null;
|
|
68
|
+
logo_url: string | null;
|
|
40
69
|
}
|
|
41
70
|
interface SdkBookSummary {
|
|
42
71
|
id: string;
|
|
43
72
|
order_book_address: string;
|
|
44
73
|
status: string;
|
|
74
|
+
book_type: string | null;
|
|
45
75
|
network_id: string;
|
|
46
76
|
subscription_start: number;
|
|
47
77
|
subscription_end: number;
|
|
48
|
-
prospectus_file_url: string;
|
|
49
78
|
}
|
|
50
79
|
interface SdkAssetRecord {
|
|
51
|
-
security:
|
|
52
|
-
|
|
80
|
+
security: SdkSecurityDetails;
|
|
81
|
+
issuer: SdkIssuerSummary;
|
|
53
82
|
books: SdkBookSummary[];
|
|
54
83
|
network: NetworkDetails;
|
|
55
84
|
}
|
|
@@ -63,6 +92,7 @@ interface SdkAssetResponse {
|
|
|
63
92
|
interface SereelSdkClient {
|
|
64
93
|
getAssets(): Promise<SdkAssetsResponse>;
|
|
65
94
|
getAssetByTokenAddress(tokenAddress: string): Promise<SdkAssetResponse>;
|
|
95
|
+
getAssetsByIssuer(issuerId: string): Promise<SdkAssetsResponse>;
|
|
66
96
|
}
|
|
67
97
|
|
|
68
98
|
declare function createClient(config: ClientConfig): SereelSdkClient;
|
|
@@ -97,4 +127,4 @@ declare class TimeoutError extends SereelSdkError {
|
|
|
97
127
|
declare class MalformedResponseError extends SereelSdkError {
|
|
98
128
|
}
|
|
99
129
|
|
|
100
|
-
export { type ClientConfig, ENVIRONMENT_BASE_URLS, HttpError, InvalidConfigurationError, MalformedResponseError, type NativeCurrency, type NetworkDetails, NotFoundError, type SdkAssetRecord, type SdkAssetResponse, type SdkAssetsResponse, type SdkBookSummary, type
|
|
130
|
+
export { type ClientConfig, ENVIRONMENT_BASE_URLS, HttpError, InvalidConfigurationError, MalformedResponseError, type NativeCurrency, type NetworkDetails, NotFoundError, type SdkAssetRecord, type SdkAssetResponse, type SdkAssetsResponse, type SdkBookSummary, type SdkIssuerSummary, type SdkRuleEngineSummary, type SdkRuleSummary, type SdkSecurityDetails, type SdkTokenPartner, type SdkTokenProspectus, type SereelEnvironment, type SereelSdkClient, SereelSdkError, ServerError, TimeoutError, UnauthorizedError, createClient, resolveBaseUrl };
|
package/dist/index.js
CHANGED
|
@@ -176,26 +176,53 @@ function isNullableString(value) {
|
|
|
176
176
|
function isFiniteNumber(value) {
|
|
177
177
|
return typeof value === "number" && Number.isFinite(value);
|
|
178
178
|
}
|
|
179
|
-
function isSecuritySummary(value) {
|
|
180
|
-
return isRecord(value) && isString(value.id) && isString(value.token_address) && isString(value.token_name) && isString(value.token_symbol) && isString(value.network_id) && isString(value.token_type);
|
|
181
|
-
}
|
|
182
|
-
function isSellerOrganizationSummary(value) {
|
|
183
|
-
return isRecord(value) && isString(value.id) && isString(value.legal_name) && isNullableString(value.display_name) && isString(value.jurisdiction) && isNullableString(value.website);
|
|
184
|
-
}
|
|
185
179
|
function isBoolean(value) {
|
|
186
180
|
return typeof value === "boolean";
|
|
187
181
|
}
|
|
182
|
+
function isProspectus(value) {
|
|
183
|
+
return isRecord(value) && isString(value.name) && isString(value.url);
|
|
184
|
+
}
|
|
185
|
+
function isTokenPartner(value) {
|
|
186
|
+
return isRecord(value) && isString(value.partner_name) && isString(value.partner_logo) && isString(value.partner_role);
|
|
187
|
+
}
|
|
188
|
+
function isRuleSummary(value) {
|
|
189
|
+
return isRecord(value) && isString(value.rule_address) && isString(value.rule_type);
|
|
190
|
+
}
|
|
191
|
+
function isRuleEngineSummary(value) {
|
|
192
|
+
return isRecord(value) && isString(value.name) && isString(value.rule_engine_address) && Array.isArray(value.rules) && value.rules.every(isRuleSummary);
|
|
193
|
+
}
|
|
194
|
+
function isSecurityDetails(value) {
|
|
195
|
+
if (!isRecord(value)) return false;
|
|
196
|
+
const hasRequiredStrings = isString(value.token_address) && isString(value.token_name) && isString(value.token_symbol) && isString(value.token_decimal) && isString(value.network_id) && isString(value.token_type) && isString(value.admin);
|
|
197
|
+
if (!hasRequiredStrings) return false;
|
|
198
|
+
if (!isNullableString(value.icon_url)) return false;
|
|
199
|
+
if (!isNullableString(value.created_at)) return false;
|
|
200
|
+
if (value.prospectus !== null && value.prospectus !== void 0) {
|
|
201
|
+
if (!isProspectus(value.prospectus)) return false;
|
|
202
|
+
}
|
|
203
|
+
if (value.partners !== null && value.partners !== void 0) {
|
|
204
|
+
if (!Array.isArray(value.partners) || !value.partners.every(isTokenPartner))
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
if (value.rule_engine !== null && value.rule_engine !== void 0) {
|
|
208
|
+
if (!isRuleEngineSummary(value.rule_engine)) return false;
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
function isIssuerSummary(value) {
|
|
213
|
+
return isRecord(value) && isString(value.id) && isString(value.legal_name) && isNullableString(value.display_name) && isString(value.jurisdiction) && isNullableString(value.website) && isNullableString(value.logo_url);
|
|
214
|
+
}
|
|
188
215
|
function isNativeCurrency(value) {
|
|
189
216
|
return isRecord(value) && isString(value.symbol) && isString(value.name) && isFiniteNumber(value.decimals);
|
|
190
217
|
}
|
|
191
218
|
function isNetworkDetails(value) {
|
|
192
|
-
return isRecord(value) && isString(value.network_id) && isString(value.name) && isString(value.family) && (isFiniteNumber(value.chain_id) || value.chain_id === null) && isNativeCurrency(value.native_currency) && isString(value.rpc_endpoint) && Array.isArray(value.explorer_urls) && value.explorer_urls.every(isString) && isBoolean(value.
|
|
219
|
+
return isRecord(value) && isString(value.network_id) && isString(value.name) && isString(value.family) && (isFiniteNumber(value.chain_id) || value.chain_id === null) && isNativeCurrency(value.native_currency) && isString(value.rpc_endpoint) && Array.isArray(value.explorer_urls) && value.explorer_urls.every(isString) && isBoolean(value.can_deploy_cmtat_token) && isBoolean(value.can_deploy_trex_token) && isBoolean(value.is_testnet) && isBoolean(value.is_supported);
|
|
193
220
|
}
|
|
194
221
|
function isBookSummary(value) {
|
|
195
|
-
return isRecord(value) && isString(value.id) && isString(value.order_book_address) && isString(value.status) && isString(value.network_id) && isFiniteNumber(value.subscription_start) && isFiniteNumber(value.subscription_end)
|
|
222
|
+
return isRecord(value) && isString(value.id) && isString(value.order_book_address) && isString(value.status) && isString(value.network_id) && isFiniteNumber(value.subscription_start) && isFiniteNumber(value.subscription_end);
|
|
196
223
|
}
|
|
197
224
|
function isAssetRecord(value) {
|
|
198
|
-
return isRecord(value) &&
|
|
225
|
+
return isRecord(value) && isSecurityDetails(value.security) && isIssuerSummary(value.issuer) && Array.isArray(value.books) && value.books.every(isBookSummary) && isNetworkDetails(value.network);
|
|
199
226
|
}
|
|
200
227
|
function validateSdkAssetsResponse(value) {
|
|
201
228
|
if (!isRecord(value) || !Array.isArray(value.data) || !isFiniteNumber(value.count) || !value.data.every(isAssetRecord)) {
|
|
@@ -235,6 +262,17 @@ function createClient(config) {
|
|
|
235
262
|
`/sdk/assets/${encodeURIComponent(trimmedTokenAddress)}`,
|
|
236
263
|
validateSdkAssetResponse
|
|
237
264
|
);
|
|
265
|
+
},
|
|
266
|
+
getAssetsByIssuer(issuerId) {
|
|
267
|
+
const trimmedIssuerId = issuerId.trim();
|
|
268
|
+
if (!trimmedIssuerId) {
|
|
269
|
+
throw new InvalidConfigurationError("issuerId must not be empty.");
|
|
270
|
+
}
|
|
271
|
+
return requestJson(
|
|
272
|
+
resolved,
|
|
273
|
+
`/sdk/assets/issuer/${encodeURIComponent(trimmedIssuerId)}`,
|
|
274
|
+
validateSdkAssetsResponse
|
|
275
|
+
);
|
|
238
276
|
}
|
|
239
277
|
};
|
|
240
278
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/config.ts","../src/transport.ts","../src/validation.ts","../src/client.ts"],"sourcesContent":["export interface SereelSdkErrorOptions {\n status?: number;\n code?: string;\n cause?: unknown;\n details?: unknown;\n}\n\nexport class SereelSdkError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n readonly details?: unknown;\n\n constructor(message: string, options: SereelSdkErrorOptions = {}) {\n super(message, options.cause ? { cause: options.cause } : undefined);\n this.name = new.target.name;\n this.status = options.status;\n this.code = options.code;\n this.details = options.details;\n }\n}\n\nexport class InvalidConfigurationError extends SereelSdkError {}\n\nexport class HttpError extends SereelSdkError {}\n\nexport class UnauthorizedError extends HttpError {}\n\nexport class NotFoundError extends HttpError {}\n\nexport class ServerError extends HttpError {}\n\nexport class TimeoutError extends SereelSdkError {}\n\nexport class MalformedResponseError extends SereelSdkError {}\n","import { InvalidConfigurationError } from \"./errors\";\nimport type { ClientConfig, SereelEnvironment } from \"./types\";\n\nexport const ENVIRONMENT_BASE_URLS: Record<SereelEnvironment, string> = {\n devnet: \"https://api-lazer.sereel.com\",\n testnet: \"https://api-lazer-v2.sereel.com\",\n mainnet: \"https://cahokia.sereel.com\",\n};\n\nexport interface ResolvedClientConfig {\n environment: SereelEnvironment;\n apiKey: string;\n timeoutMs: number;\n baseUrl: string;\n fetch: typeof fetch;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction getFetchImplementation(\n providedFetch: ClientConfig[\"fetch\"],\n): typeof fetch {\n if (providedFetch) {\n return providedFetch;\n }\n\n if (typeof globalThis.fetch === \"function\") {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new InvalidConfigurationError(\n \"No fetch implementation is available. Provide config.fetch in this runtime.\",\n );\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const trimmed = baseUrl.trim();\n\n if (!trimmed) {\n throw new InvalidConfigurationError(\"baseUrl must not be empty when provided.\");\n }\n\n try {\n return new URL(trimmed).toString().replace(/\\/+$/, \"\");\n } catch (cause) {\n throw new InvalidConfigurationError(\"baseUrl must be a valid absolute URL.\", {\n cause,\n });\n }\n}\n\nexport function resolveBaseUrl(\n environment: SereelEnvironment,\n baseUrl?: string,\n): string {\n if (baseUrl) {\n return normalizeBaseUrl(baseUrl);\n }\n\n return ENVIRONMENT_BASE_URLS[environment];\n}\n\nexport function resolveClientConfig(config: ClientConfig): ResolvedClientConfig {\n const apiKey = config.apiKey.trim();\n\n if (!apiKey) {\n throw new InvalidConfigurationError(\"apiKey must not be empty.\");\n }\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new InvalidConfigurationError(\"timeoutMs must be a positive number.\");\n }\n\n return {\n environment: config.environment,\n apiKey,\n timeoutMs,\n baseUrl: resolveBaseUrl(config.environment, config.baseUrl),\n fetch: getFetchImplementation(config.fetch),\n };\n}\n","import {\n HttpError,\n MalformedResponseError,\n NotFoundError,\n ServerError,\n TimeoutError,\n UnauthorizedError,\n} from \"./errors\";\nimport type { ResolvedClientConfig } from \"./config\";\n\ninterface ApiErrorBody {\n error?: string;\n message?: string;\n}\n\nfunction createTimeoutSignal(timeoutMs: number): {\n signal: AbortSignal;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n return {\n signal: controller.signal,\n cleanup: () => clearTimeout(timeout),\n };\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const text = await response.text();\n if (!text) {\n return null;\n }\n\n try {\n return JSON.parse(text) as unknown;\n } catch (cause) {\n throw new MalformedResponseError(\"Received a non-JSON response body.\", {\n cause,\n status: response.status,\n details: text,\n });\n }\n}\n\nfunction getErrorMessage(status: number, body: unknown): string {\n if (body && typeof body === \"object\") {\n const apiError = body as ApiErrorBody;\n if (typeof apiError.error === \"string\" && apiError.error.trim()) {\n return apiError.error;\n }\n if (typeof apiError.message === \"string\" && apiError.message.trim()) {\n return apiError.message;\n }\n }\n\n return `Request failed with status ${status}.`;\n}\n\nfunction toHttpError(status: number, body: unknown): HttpError {\n const message = getErrorMessage(status, body);\n const options = { status, details: body };\n\n if (status === 401) {\n return new UnauthorizedError(message, options);\n }\n if (status === 404) {\n return new NotFoundError(message, options);\n }\n if (status >= 500) {\n return new ServerError(message, options);\n }\n\n return new HttpError(message, options);\n}\n\nexport async function requestJson<T>(\n config: ResolvedClientConfig,\n path: string,\n validate: (value: unknown) => T,\n): Promise<T> {\n const { signal, cleanup } = createTimeoutSignal(config.timeoutMs);\n\n try {\n const response = await config.fetch(`${config.baseUrl}${path}`, {\n method: \"GET\",\n signal,\n headers: {\n accept: \"application/json\",\n \"x-api-key\": config.apiKey,\n },\n });\n\n const body = await parseBody(response);\n if (!response.ok) {\n throw toHttpError(response.status, body);\n }\n\n return validate(body);\n } catch (error) {\n if (error instanceof HttpError || error instanceof MalformedResponseError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new TimeoutError(\n `Request timed out after ${config.timeoutMs}ms.`,\n { cause: error },\n );\n }\n\n throw error;\n } finally {\n cleanup();\n }\n}\n","import { MalformedResponseError } from \"./errors\";\nimport type {\n NativeCurrency,\n NetworkDetails,\n SdkAssetRecord,\n SdkAssetResponse,\n SdkAssetsResponse,\n SdkBookSummary,\n SdkSecuritySummary,\n SdkSellerOrganizationSummary,\n} from \"./types\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return typeof value === \"string\" || value === null;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isSecuritySummary(value: unknown): value is SdkSecuritySummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.token_address) &&\n isString(value.token_name) &&\n isString(value.token_symbol) &&\n isString(value.network_id) &&\n isString(value.token_type)\n );\n}\n\nfunction isSellerOrganizationSummary(\n value: unknown,\n): value is SdkSellerOrganizationSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.legal_name) &&\n isNullableString(value.display_name) &&\n isString(value.jurisdiction) &&\n isNullableString(value.website)\n );\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === \"boolean\";\n}\n\nfunction isNativeCurrency(value: unknown): value is NativeCurrency {\n return (\n isRecord(value) &&\n isString(value.symbol) &&\n isString(value.name) &&\n isFiniteNumber(value.decimals)\n );\n}\n\nfunction isNetworkDetails(value: unknown): value is NetworkDetails {\n return (\n isRecord(value) &&\n isString(value.network_id) &&\n isString(value.name) &&\n isString(value.family) &&\n (isFiniteNumber(value.chain_id) || value.chain_id === null) &&\n isNativeCurrency(value.native_currency) &&\n isString(value.rpc_endpoint) &&\n Array.isArray(value.explorer_urls) &&\n (value.explorer_urls as unknown[]).every(isString) &&\n isBoolean(value.can_deploy_token) &&\n isBoolean(value.is_testnet) &&\n isBoolean(value.is_supported)\n );\n}\n\nfunction isBookSummary(value: unknown): value is SdkBookSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.order_book_address) &&\n isString(value.status) &&\n isString(value.network_id) &&\n isFiniteNumber(value.subscription_start) &&\n isFiniteNumber(value.subscription_end) &&\n isString(value.prospectus_file_url)\n );\n}\n\nfunction isAssetRecord(value: unknown): value is SdkAssetRecord {\n return (\n isRecord(value) &&\n isSecuritySummary(value.security) &&\n isSellerOrganizationSummary(value.seller_organization) &&\n Array.isArray(value.books) &&\n value.books.every(isBookSummary) &&\n isNetworkDetails(value.network)\n );\n}\n\nexport function validateSdkAssetsResponse(value: unknown): SdkAssetsResponse {\n if (\n !isRecord(value) ||\n !Array.isArray(value.data) ||\n !isFiniteNumber(value.count) ||\n !value.data.every(isAssetRecord)\n ) {\n throw new MalformedResponseError(\n \"Received an invalid SDK assets response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetsResponse;\n}\n\nexport function validateSdkAssetResponse(value: unknown): SdkAssetResponse {\n if (!isRecord(value) || !isAssetRecord(value.data)) {\n throw new MalformedResponseError(\n \"Received an invalid SDK asset response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetResponse;\n}\n","import { resolveClientConfig } from \"./config\";\nimport { InvalidConfigurationError } from \"./errors\";\nimport { requestJson } from \"./transport\";\nimport type {\n ClientConfig,\n SdkAssetResponse,\n SdkAssetsResponse,\n SereelSdkClient,\n} from \"./types\";\nimport {\n validateSdkAssetResponse,\n validateSdkAssetsResponse,\n} from \"./validation\";\n\nexport function createClient(config: ClientConfig): SereelSdkClient {\n const resolved = resolveClientConfig(config);\n\n return {\n getAssets(): Promise<SdkAssetsResponse> {\n return requestJson(resolved, \"/sdk/assets\", validateSdkAssetsResponse);\n },\n\n getAssetByTokenAddress(tokenAddress: string): Promise<SdkAssetResponse> {\n const trimmedTokenAddress = tokenAddress.trim();\n if (!trimmedTokenAddress) {\n throw new InvalidConfigurationError(\n \"tokenAddress must not be empty.\",\n );\n }\n\n return requestJson(\n resolved,\n `/sdk/assets/${encodeURIComponent(trimmedTokenAddress)}`,\n validateSdkAssetResponse,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/config.ts","../src/transport.ts","../src/validation.ts","../src/client.ts"],"sourcesContent":["export interface SereelSdkErrorOptions {\n status?: number;\n code?: string;\n cause?: unknown;\n details?: unknown;\n}\n\nexport class SereelSdkError extends Error {\n readonly status: number | undefined;\n readonly code: string | undefined;\n readonly details?: unknown;\n\n constructor(message: string, options: SereelSdkErrorOptions = {}) {\n super(message, options.cause ? { cause: options.cause } : undefined);\n this.name = new.target.name;\n this.status = options.status;\n this.code = options.code;\n this.details = options.details;\n }\n}\n\nexport class InvalidConfigurationError extends SereelSdkError {}\n\nexport class HttpError extends SereelSdkError {}\n\nexport class UnauthorizedError extends HttpError {}\n\nexport class NotFoundError extends HttpError {}\n\nexport class ServerError extends HttpError {}\n\nexport class TimeoutError extends SereelSdkError {}\n\nexport class MalformedResponseError extends SereelSdkError {}\n","import { InvalidConfigurationError } from \"./errors\";\nimport type { ClientConfig, SereelEnvironment } from \"./types\";\n\nexport const ENVIRONMENT_BASE_URLS: Record<SereelEnvironment, string> = {\n devnet: \"https://api-lazer.sereel.com\",\n testnet: \"https://api-lazer-v2.sereel.com\",\n mainnet: \"https://cahokia.sereel.com\",\n};\n\nexport interface ResolvedClientConfig {\n environment: SereelEnvironment;\n apiKey: string;\n timeoutMs: number;\n baseUrl: string;\n fetch: typeof fetch;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nfunction getFetchImplementation(\n providedFetch: ClientConfig[\"fetch\"],\n): typeof fetch {\n if (providedFetch) {\n return providedFetch;\n }\n\n if (typeof globalThis.fetch === \"function\") {\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new InvalidConfigurationError(\n \"No fetch implementation is available. Provide config.fetch in this runtime.\",\n );\n}\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n const trimmed = baseUrl.trim();\n\n if (!trimmed) {\n throw new InvalidConfigurationError(\"baseUrl must not be empty when provided.\");\n }\n\n try {\n return new URL(trimmed).toString().replace(/\\/+$/, \"\");\n } catch (cause) {\n throw new InvalidConfigurationError(\"baseUrl must be a valid absolute URL.\", {\n cause,\n });\n }\n}\n\nexport function resolveBaseUrl(\n environment: SereelEnvironment,\n baseUrl?: string,\n): string {\n if (baseUrl) {\n return normalizeBaseUrl(baseUrl);\n }\n\n return ENVIRONMENT_BASE_URLS[environment];\n}\n\nexport function resolveClientConfig(config: ClientConfig): ResolvedClientConfig {\n const apiKey = config.apiKey.trim();\n\n if (!apiKey) {\n throw new InvalidConfigurationError(\"apiKey must not be empty.\");\n }\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new InvalidConfigurationError(\"timeoutMs must be a positive number.\");\n }\n\n return {\n environment: config.environment,\n apiKey,\n timeoutMs,\n baseUrl: resolveBaseUrl(config.environment, config.baseUrl),\n fetch: getFetchImplementation(config.fetch),\n };\n}\n","import {\n HttpError,\n MalformedResponseError,\n NotFoundError,\n ServerError,\n TimeoutError,\n UnauthorizedError,\n} from \"./errors\";\nimport type { ResolvedClientConfig } from \"./config\";\n\ninterface ApiErrorBody {\n error?: string;\n message?: string;\n}\n\nfunction createTimeoutSignal(timeoutMs: number): {\n signal: AbortSignal;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n return {\n signal: controller.signal,\n cleanup: () => clearTimeout(timeout),\n };\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const text = await response.text();\n if (!text) {\n return null;\n }\n\n try {\n return JSON.parse(text) as unknown;\n } catch (cause) {\n throw new MalformedResponseError(\"Received a non-JSON response body.\", {\n cause,\n status: response.status,\n details: text,\n });\n }\n}\n\nfunction getErrorMessage(status: number, body: unknown): string {\n if (body && typeof body === \"object\") {\n const apiError = body as ApiErrorBody;\n if (typeof apiError.error === \"string\" && apiError.error.trim()) {\n return apiError.error;\n }\n if (typeof apiError.message === \"string\" && apiError.message.trim()) {\n return apiError.message;\n }\n }\n\n return `Request failed with status ${status}.`;\n}\n\nfunction toHttpError(status: number, body: unknown): HttpError {\n const message = getErrorMessage(status, body);\n const options = { status, details: body };\n\n if (status === 401) {\n return new UnauthorizedError(message, options);\n }\n if (status === 404) {\n return new NotFoundError(message, options);\n }\n if (status >= 500) {\n return new ServerError(message, options);\n }\n\n return new HttpError(message, options);\n}\n\nexport async function requestJson<T>(\n config: ResolvedClientConfig,\n path: string,\n validate: (value: unknown) => T,\n): Promise<T> {\n const { signal, cleanup } = createTimeoutSignal(config.timeoutMs);\n\n try {\n const response = await config.fetch(`${config.baseUrl}${path}`, {\n method: \"GET\",\n signal,\n headers: {\n accept: \"application/json\",\n \"x-api-key\": config.apiKey,\n },\n });\n\n const body = await parseBody(response);\n if (!response.ok) {\n throw toHttpError(response.status, body);\n }\n\n return validate(body);\n } catch (error) {\n if (error instanceof HttpError || error instanceof MalformedResponseError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new TimeoutError(\n `Request timed out after ${config.timeoutMs}ms.`,\n { cause: error },\n );\n }\n\n throw error;\n } finally {\n cleanup();\n }\n}\n","import { MalformedResponseError } from \"./errors\";\nimport type {\n NativeCurrency,\n NetworkDetails,\n SdkAssetRecord,\n SdkAssetResponse,\n SdkAssetsResponse,\n SdkBookSummary,\n SdkIssuerSummary,\n SdkRuleEngineSummary,\n SdkRuleSummary,\n SdkSecurityDetails,\n SdkTokenPartner,\n SdkTokenProspectus,\n} from \"./types\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\nfunction isNullableString(value: unknown): value is string | null {\n return typeof value === \"string\" || value === null;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isBoolean(value: unknown): value is boolean {\n return typeof value === \"boolean\";\n}\n\nfunction isProspectus(value: unknown): value is SdkTokenProspectus {\n return isRecord(value) && isString(value.name) && isString(value.url);\n}\n\nfunction isTokenPartner(value: unknown): value is SdkTokenPartner {\n return (\n isRecord(value) &&\n isString(value.partner_name) &&\n isString(value.partner_logo) &&\n isString(value.partner_role)\n );\n}\n\nfunction isRuleSummary(value: unknown): value is SdkRuleSummary {\n return (\n isRecord(value) &&\n isString(value.rule_address) &&\n isString(value.rule_type)\n );\n}\n\nfunction isRuleEngineSummary(value: unknown): value is SdkRuleEngineSummary {\n return (\n isRecord(value) &&\n isString(value.name) &&\n isString(value.rule_engine_address) &&\n Array.isArray(value.rules) &&\n (value.rules as unknown[]).every(isRuleSummary)\n );\n}\n\nfunction isSecurityDetails(value: unknown): value is SdkSecurityDetails {\n if (!isRecord(value)) return false;\n\n const hasRequiredStrings =\n isString(value.token_address) &&\n isString(value.token_name) &&\n isString(value.token_symbol) &&\n isString(value.token_decimal) &&\n isString(value.network_id) &&\n isString(value.token_type) &&\n isString(value.admin);\n\n if (!hasRequiredStrings) return false;\n\n if (!isNullableString(value.icon_url)) return false;\n if (!isNullableString(value.created_at)) return false;\n\n if (value.prospectus !== null && value.prospectus !== undefined) {\n if (!isProspectus(value.prospectus)) return false;\n }\n\n if (value.partners !== null && value.partners !== undefined) {\n if (\n !Array.isArray(value.partners) ||\n !(value.partners as unknown[]).every(isTokenPartner)\n )\n return false;\n }\n\n if (value.rule_engine !== null && value.rule_engine !== undefined) {\n if (!isRuleEngineSummary(value.rule_engine)) return false;\n }\n\n return true;\n}\n\nfunction isIssuerSummary(value: unknown): value is SdkIssuerSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.legal_name) &&\n isNullableString(value.display_name) &&\n isString(value.jurisdiction) &&\n isNullableString(value.website) &&\n isNullableString(value.logo_url)\n );\n}\n\nfunction isNativeCurrency(value: unknown): value is NativeCurrency {\n return (\n isRecord(value) &&\n isString(value.symbol) &&\n isString(value.name) &&\n isFiniteNumber(value.decimals)\n );\n}\n\nfunction isNetworkDetails(value: unknown): value is NetworkDetails {\n return (\n isRecord(value) &&\n isString(value.network_id) &&\n isString(value.name) &&\n isString(value.family) &&\n (isFiniteNumber(value.chain_id) || value.chain_id === null) &&\n isNativeCurrency(value.native_currency) &&\n isString(value.rpc_endpoint) &&\n Array.isArray(value.explorer_urls) &&\n (value.explorer_urls as unknown[]).every(isString) &&\n isBoolean(value.can_deploy_cmtat_token) &&\n isBoolean(value.can_deploy_trex_token) &&\n isBoolean(value.is_testnet) &&\n isBoolean(value.is_supported)\n );\n}\n\nfunction isBookSummary(value: unknown): value is SdkBookSummary {\n return (\n isRecord(value) &&\n isString(value.id) &&\n isString(value.order_book_address) &&\n isString(value.status) &&\n isString(value.network_id) &&\n isFiniteNumber(value.subscription_start) &&\n isFiniteNumber(value.subscription_end)\n );\n}\n\nfunction isAssetRecord(value: unknown): value is SdkAssetRecord {\n return (\n isRecord(value) &&\n isSecurityDetails(value.security) &&\n isIssuerSummary(value.issuer) &&\n Array.isArray(value.books) &&\n value.books.every(isBookSummary) &&\n isNetworkDetails(value.network)\n );\n}\n\nexport function validateSdkAssetsResponse(value: unknown): SdkAssetsResponse {\n if (\n !isRecord(value) ||\n !Array.isArray(value.data) ||\n !isFiniteNumber(value.count) ||\n !value.data.every(isAssetRecord)\n ) {\n throw new MalformedResponseError(\n \"Received an invalid SDK assets response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetsResponse;\n}\n\nexport function validateSdkAssetResponse(value: unknown): SdkAssetResponse {\n if (!isRecord(value) || !isAssetRecord(value.data)) {\n throw new MalformedResponseError(\n \"Received an invalid SDK asset response shape.\",\n { details: value },\n );\n }\n\n return value as unknown as SdkAssetResponse;\n}\n","import { resolveClientConfig } from \"./config\";\nimport { InvalidConfigurationError } from \"./errors\";\nimport { requestJson } from \"./transport\";\nimport type {\n ClientConfig,\n SdkAssetResponse,\n SdkAssetsResponse,\n SereelSdkClient,\n} from \"./types\";\nimport {\n validateSdkAssetResponse,\n validateSdkAssetsResponse,\n} from \"./validation\";\n\nexport function createClient(config: ClientConfig): SereelSdkClient {\n const resolved = resolveClientConfig(config);\n\n return {\n getAssets(): Promise<SdkAssetsResponse> {\n return requestJson(resolved, \"/sdk/assets\", validateSdkAssetsResponse);\n },\n\n getAssetByTokenAddress(tokenAddress: string): Promise<SdkAssetResponse> {\n const trimmedTokenAddress = tokenAddress.trim();\n if (!trimmedTokenAddress) {\n throw new InvalidConfigurationError(\n \"tokenAddress must not be empty.\",\n );\n }\n\n return requestJson(\n resolved,\n `/sdk/assets/${encodeURIComponent(trimmedTokenAddress)}`,\n validateSdkAssetResponse,\n );\n },\n\n getAssetsByIssuer(issuerId: string): Promise<SdkAssetsResponse> {\n const trimmedIssuerId = issuerId.trim();\n if (!trimmedIssuerId) {\n throw new InvalidConfigurationError(\"issuerId must not be empty.\");\n }\n\n return requestJson(\n resolved,\n `/sdk/assets/issuer/${encodeURIComponent(trimmedIssuerId)}`,\n validateSdkAssetsResponse,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
|