@cesto/sdk 0.0.1
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/LICENSE +21 -0
- package/README.md +184 -0
- package/dist/index.cjs +394 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +573 -0
- package/dist/index.d.ts +573 -0
- package/dist/index.js +377 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
// src/core/errors.ts
|
|
2
|
+
var CestoError = class extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = new.target.name;
|
|
6
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
var APIError = class extends CestoError {
|
|
10
|
+
/** HTTP status code. */
|
|
11
|
+
status;
|
|
12
|
+
/** Machine-readable error code from the API envelope (e.g. `RESOURCE_NOT_FOUND`). */
|
|
13
|
+
code;
|
|
14
|
+
/** Correlation id from the API envelope, useful when reporting issues. */
|
|
15
|
+
requestId;
|
|
16
|
+
/** Structured error details from the API envelope. */
|
|
17
|
+
details;
|
|
18
|
+
/** Response headers. */
|
|
19
|
+
headers;
|
|
20
|
+
constructor(status, message, opts = {}) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.status = status;
|
|
23
|
+
this.code = opts.code;
|
|
24
|
+
this.requestId = opts.requestId;
|
|
25
|
+
this.details = opts.details;
|
|
26
|
+
this.headers = opts.headers;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var BadRequestError = class extends APIError {
|
|
30
|
+
};
|
|
31
|
+
var AuthenticationError = class extends APIError {
|
|
32
|
+
};
|
|
33
|
+
var PermissionDeniedError = class extends APIError {
|
|
34
|
+
};
|
|
35
|
+
var NotFoundError = class extends APIError {
|
|
36
|
+
};
|
|
37
|
+
var ConflictError = class extends APIError {
|
|
38
|
+
};
|
|
39
|
+
var UnprocessableEntityError = class extends APIError {
|
|
40
|
+
};
|
|
41
|
+
var RateLimitError = class extends APIError {
|
|
42
|
+
/** Milliseconds to wait before retrying, derived from `Retry-After`. */
|
|
43
|
+
retryAfter;
|
|
44
|
+
constructor(status, message, opts = {}) {
|
|
45
|
+
super(status, message, opts);
|
|
46
|
+
this.retryAfter = opts.retryAfter;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var InternalServerError = class extends APIError {
|
|
50
|
+
};
|
|
51
|
+
var APIConnectionError = class extends CestoError {
|
|
52
|
+
cause;
|
|
53
|
+
constructor(message = "Connection error", opts = {}) {
|
|
54
|
+
super(message);
|
|
55
|
+
this.cause = opts.cause;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var APIConnectionTimeoutError = class extends APIConnectionError {
|
|
59
|
+
constructor(message = "Request timed out") {
|
|
60
|
+
super(message);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var APIUserAbortError = class extends CestoError {
|
|
64
|
+
constructor(message = "Request was aborted") {
|
|
65
|
+
super(message);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
function makeAPIError(status, envelope, headers, retryAfter) {
|
|
69
|
+
const message = envelope.message || `HTTP ${status}`;
|
|
70
|
+
const opts = {
|
|
71
|
+
code: envelope.code,
|
|
72
|
+
requestId: envelope.requestId,
|
|
73
|
+
details: envelope.details,
|
|
74
|
+
headers
|
|
75
|
+
};
|
|
76
|
+
switch (status) {
|
|
77
|
+
case 400:
|
|
78
|
+
return new BadRequestError(status, message, opts);
|
|
79
|
+
case 401:
|
|
80
|
+
return new AuthenticationError(status, message, opts);
|
|
81
|
+
case 403:
|
|
82
|
+
return new PermissionDeniedError(status, message, opts);
|
|
83
|
+
case 404:
|
|
84
|
+
return new NotFoundError(status, message, opts);
|
|
85
|
+
case 409:
|
|
86
|
+
return new ConflictError(status, message, opts);
|
|
87
|
+
case 422:
|
|
88
|
+
return new UnprocessableEntityError(status, message, opts);
|
|
89
|
+
case 429:
|
|
90
|
+
return new RateLimitError(status, message, { ...opts, retryAfter });
|
|
91
|
+
default:
|
|
92
|
+
if (status >= 500) return new InternalServerError(status, message, opts);
|
|
93
|
+
return new APIError(status, message, opts);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/core/options.ts
|
|
98
|
+
var PROD_BASE_URL = "https://backend.cesto.co";
|
|
99
|
+
var BETA_BASE_URL = "https://dev.backend.cesto.co";
|
|
100
|
+
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
101
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
102
|
+
function isBrowser() {
|
|
103
|
+
return typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
104
|
+
}
|
|
105
|
+
function resolveBaseURL(environment) {
|
|
106
|
+
return environment === "BETA" ? BETA_BASE_URL : PROD_BASE_URL;
|
|
107
|
+
}
|
|
108
|
+
function resolveOptions(options) {
|
|
109
|
+
if (isBrowser()) {
|
|
110
|
+
throw new CestoError(
|
|
111
|
+
"The Cesto SDK is server-side only. It must not run in a browser \u2014 a secret key (cesto_sk_\u2026) would be exposed to end users."
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const apiKey = options.apiKey;
|
|
115
|
+
if (!apiKey) {
|
|
116
|
+
throw new CestoError("Missing API key. Pass { apiKey } when constructing the client.");
|
|
117
|
+
}
|
|
118
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
119
|
+
if (typeof fetchImpl !== "function") {
|
|
120
|
+
throw new CestoError(
|
|
121
|
+
"No fetch implementation found. Use Node 18+ or pass a custom { fetch } in ClientOptions."
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
const timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
125
|
+
if (!Number.isFinite(timeout) || timeout < 0) {
|
|
126
|
+
throw new CestoError("`timeout` must be a finite number >= 0.");
|
|
127
|
+
}
|
|
128
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
129
|
+
if (!Number.isInteger(maxRetries) || maxRetries < 0) {
|
|
130
|
+
throw new CestoError("`maxRetries` must be an integer >= 0.");
|
|
131
|
+
}
|
|
132
|
+
const environment = options.environment ?? "PRODUCTION";
|
|
133
|
+
if (environment !== "PRODUCTION" && environment !== "BETA") {
|
|
134
|
+
throw new CestoError(`Invalid environment: ${environment}. Use 'PRODUCTION' or 'BETA'.`);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
apiKey,
|
|
138
|
+
baseURL: resolveBaseURL(environment),
|
|
139
|
+
timeout,
|
|
140
|
+
maxRetries,
|
|
141
|
+
fetch: options.fetch ?? fetchImpl.bind(globalThis)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/core/version.ts
|
|
146
|
+
var VERSION = "0.0.1";
|
|
147
|
+
|
|
148
|
+
// src/core/request.ts
|
|
149
|
+
var RETRY_BASE_MS = 500;
|
|
150
|
+
var RETRY_CAP_MS = 8e3;
|
|
151
|
+
var APIClientCore = class {
|
|
152
|
+
constructor(opts) {
|
|
153
|
+
this.opts = opts;
|
|
154
|
+
}
|
|
155
|
+
get(path, options = {}) {
|
|
156
|
+
return this.request("GET", path, options);
|
|
157
|
+
}
|
|
158
|
+
async request(method, path, options) {
|
|
159
|
+
const url = this.buildURL(path, options.query);
|
|
160
|
+
const timeout = options.timeout ?? this.opts.timeout;
|
|
161
|
+
const maxRetries = options.maxRetries ?? this.opts.maxRetries;
|
|
162
|
+
let attempt = 0;
|
|
163
|
+
for (; ; ) {
|
|
164
|
+
const timer = withTimeout(options.signal, timeout);
|
|
165
|
+
let response;
|
|
166
|
+
try {
|
|
167
|
+
response = await this.opts.fetch(url, {
|
|
168
|
+
method,
|
|
169
|
+
headers: buildHeaders(this.opts.apiKey, attempt),
|
|
170
|
+
signal: timer.signal
|
|
171
|
+
});
|
|
172
|
+
} catch (err) {
|
|
173
|
+
timer.cleanup();
|
|
174
|
+
const mapped = mapFetchError(err, timer, options.signal);
|
|
175
|
+
if (mapped instanceof APIUserAbortError) throw mapped;
|
|
176
|
+
if (attempt < maxRetries) {
|
|
177
|
+
attempt += 1;
|
|
178
|
+
await sleep(backoff(attempt));
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
throw mapped;
|
|
182
|
+
}
|
|
183
|
+
timer.cleanup();
|
|
184
|
+
if (response.ok) {
|
|
185
|
+
return parseJSON(response);
|
|
186
|
+
}
|
|
187
|
+
if (shouldRetryStatus(response.status) && attempt < maxRetries) {
|
|
188
|
+
attempt += 1;
|
|
189
|
+
await sleep(parseRetryAfter(response.headers) ?? backoff(attempt));
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
throw await errorFromResponse(response);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
buildURL(path, query) {
|
|
196
|
+
const url = new URL(`${this.opts.baseURL}${path}`);
|
|
197
|
+
if (query) {
|
|
198
|
+
for (const [key, value] of Object.entries(query)) {
|
|
199
|
+
if (value !== void 0 && value !== null) url.searchParams.set(key, String(value));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return url.toString();
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
function buildHeaders(apiKey, attempt) {
|
|
206
|
+
const headers = {
|
|
207
|
+
"X-API-Key": apiKey,
|
|
208
|
+
Accept: "application/json"
|
|
209
|
+
};
|
|
210
|
+
const ua = userAgent();
|
|
211
|
+
if (ua) headers["User-Agent"] = ua;
|
|
212
|
+
if (attempt > 0) headers["x-cesto-retry-count"] = String(attempt);
|
|
213
|
+
return headers;
|
|
214
|
+
}
|
|
215
|
+
function userAgent() {
|
|
216
|
+
if (typeof process !== "undefined" && process.versions?.node) {
|
|
217
|
+
return `cesto-sdk/${VERSION} (node/${process.versions.node})`;
|
|
218
|
+
}
|
|
219
|
+
return `cesto-sdk/${VERSION}`;
|
|
220
|
+
}
|
|
221
|
+
function withTimeout(userSignal, timeoutMs) {
|
|
222
|
+
const controller = new AbortController();
|
|
223
|
+
let timedOut = false;
|
|
224
|
+
const timer = setTimeout(() => {
|
|
225
|
+
timedOut = true;
|
|
226
|
+
controller.abort(new Error("timeout"));
|
|
227
|
+
}, timeoutMs);
|
|
228
|
+
const onUserAbort = () => controller.abort(userSignal?.reason);
|
|
229
|
+
if (userSignal) {
|
|
230
|
+
if (userSignal.aborted) controller.abort(userSignal.reason);
|
|
231
|
+
else userSignal.addEventListener("abort", onUserAbort, { once: true });
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
signal: controller.signal,
|
|
235
|
+
didTimeout: () => timedOut,
|
|
236
|
+
cleanup: () => {
|
|
237
|
+
clearTimeout(timer);
|
|
238
|
+
userSignal?.removeEventListener("abort", onUserAbort);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function mapFetchError(err, timer, userSignal) {
|
|
243
|
+
if (userSignal?.aborted) return new APIUserAbortError();
|
|
244
|
+
if (timer.didTimeout()) return new APIConnectionTimeoutError();
|
|
245
|
+
return new APIConnectionError("Connection error", { cause: err });
|
|
246
|
+
}
|
|
247
|
+
function shouldRetryStatus(status) {
|
|
248
|
+
return status === 408 || status === 409 || status === 429 || status >= 500;
|
|
249
|
+
}
|
|
250
|
+
async function parseJSON(response) {
|
|
251
|
+
const text = await response.text();
|
|
252
|
+
if (!text) return void 0;
|
|
253
|
+
try {
|
|
254
|
+
return JSON.parse(text);
|
|
255
|
+
} catch {
|
|
256
|
+
throw new CestoError("Failed to parse response body as JSON.");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function errorFromResponse(response) {
|
|
260
|
+
let envelope = {};
|
|
261
|
+
try {
|
|
262
|
+
const text = await response.text();
|
|
263
|
+
if (text) {
|
|
264
|
+
const parsed = JSON.parse(text);
|
|
265
|
+
if (parsed && typeof parsed === "object") envelope = parsed;
|
|
266
|
+
}
|
|
267
|
+
} catch {
|
|
268
|
+
}
|
|
269
|
+
return makeAPIError(
|
|
270
|
+
response.status,
|
|
271
|
+
envelope,
|
|
272
|
+
response.headers,
|
|
273
|
+
parseRetryAfter(response.headers)
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
function parseRetryAfter(headers) {
|
|
277
|
+
const value = headers.get("retry-after");
|
|
278
|
+
if (!value) return void 0;
|
|
279
|
+
const seconds = Number(value);
|
|
280
|
+
if (!Number.isNaN(seconds)) return Math.max(0, seconds * 1e3);
|
|
281
|
+
const dateMs = Date.parse(value);
|
|
282
|
+
if (!Number.isNaN(dateMs)) return Math.max(0, dateMs - Date.now());
|
|
283
|
+
return void 0;
|
|
284
|
+
}
|
|
285
|
+
function backoff(attempt) {
|
|
286
|
+
const ceiling = Math.min(RETRY_CAP_MS, RETRY_BASE_MS * 2 ** (attempt - 1));
|
|
287
|
+
return Math.random() * ceiling;
|
|
288
|
+
}
|
|
289
|
+
function sleep(ms) {
|
|
290
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/resources/resource.ts
|
|
294
|
+
var APIResource = class {
|
|
295
|
+
constructor(client) {
|
|
296
|
+
this.client = client;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// src/resources/positions.ts
|
|
301
|
+
var Positions = class extends APIResource {
|
|
302
|
+
/**
|
|
303
|
+
* List a user's open/closing positions, resolved from their external Solana
|
|
304
|
+
* wallet. A wallet with no Cesto account returns an empty result (not an error).
|
|
305
|
+
*/
|
|
306
|
+
list(params, options) {
|
|
307
|
+
if (!params?.wallet) throw new CestoError("wallet is required");
|
|
308
|
+
return this.client.get("/positions/by-wallet", {
|
|
309
|
+
query: { wallet: params.wallet },
|
|
310
|
+
...options
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
// src/resources/products.ts
|
|
316
|
+
var DEFAULT_CHART_TIME_RANGE = "1y";
|
|
317
|
+
var Products = class extends APIResource {
|
|
318
|
+
async list(params = {}, options) {
|
|
319
|
+
const query = params.category ? { category: params.category } : void 0;
|
|
320
|
+
if (!params.includeBacktest) {
|
|
321
|
+
return this.client.get("/products", { query, ...options });
|
|
322
|
+
}
|
|
323
|
+
const [items, backtests] = await Promise.all([
|
|
324
|
+
this.client.get("/products", { query, ...options }),
|
|
325
|
+
this.client.get("/products/analytics", { query, ...options }).catch(() => ({}))
|
|
326
|
+
]);
|
|
327
|
+
return items.map((item) => ({ ...item, backtest: backtests[item.id] ?? null }));
|
|
328
|
+
}
|
|
329
|
+
async get(slug, params = {}, options) {
|
|
330
|
+
const product = await this.client.get(
|
|
331
|
+
`/products/${encodeURIComponent(slug)}`,
|
|
332
|
+
options
|
|
333
|
+
);
|
|
334
|
+
if (!params.includeBacktestChart) return product;
|
|
335
|
+
const backtestChart = await this.client.get(`/products/${encodeURIComponent(product.id)}/graph`, {
|
|
336
|
+
query: { timeRange: params.chartTimeRange ?? DEFAULT_CHART_TIME_RANGE },
|
|
337
|
+
...options
|
|
338
|
+
}).catch(() => null);
|
|
339
|
+
return { ...product, backtestChart };
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// src/client.ts
|
|
344
|
+
var Cesto = class {
|
|
345
|
+
products;
|
|
346
|
+
positions;
|
|
347
|
+
core;
|
|
348
|
+
constructor(options = {}) {
|
|
349
|
+
this.core = new APIClientCore(resolveOptions(options));
|
|
350
|
+
this.products = new Products(this.core);
|
|
351
|
+
this.positions = new Positions(this.core);
|
|
352
|
+
}
|
|
353
|
+
// Error classes re-exposed for ergonomic `instanceof` checks:
|
|
354
|
+
// catch (e) { if (e instanceof Cesto.NotFoundError) … }
|
|
355
|
+
static CestoError = CestoError;
|
|
356
|
+
static APIError = APIError;
|
|
357
|
+
static BadRequestError = BadRequestError;
|
|
358
|
+
static AuthenticationError = AuthenticationError;
|
|
359
|
+
static PermissionDeniedError = PermissionDeniedError;
|
|
360
|
+
static NotFoundError = NotFoundError;
|
|
361
|
+
static ConflictError = ConflictError;
|
|
362
|
+
static UnprocessableEntityError = UnprocessableEntityError;
|
|
363
|
+
static RateLimitError = RateLimitError;
|
|
364
|
+
static InternalServerError = InternalServerError;
|
|
365
|
+
static APIConnectionError = APIConnectionError;
|
|
366
|
+
static APIConnectionTimeoutError = APIConnectionTimeoutError;
|
|
367
|
+
static APIUserAbortError = APIUserAbortError;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
// src/types/products.ts
|
|
371
|
+
function isPredictionMarketChart(chart) {
|
|
372
|
+
return chart.predictionMarket === true;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export { APIConnectionError, APIConnectionTimeoutError, APIError, APIUserAbortError, AuthenticationError, BadRequestError, Cesto, CestoError, ConflictError, InternalServerError, NotFoundError, PermissionDeniedError, RateLimitError, UnprocessableEntityError, VERSION, isPredictionMarketChart };
|
|
376
|
+
//# sourceMappingURL=index.js.map
|
|
377
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts","../src/core/options.ts","../src/core/version.ts","../src/core/request.ts","../src/resources/resource.ts","../src/resources/positions.ts","../src/resources/products.ts","../src/client.ts","../src/types/products.ts"],"names":[],"mappings":";AAUO,IAAM,UAAA,GAAN,cAAyB,KAAA,CAAM;AAAA,EACpC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,OAAO,GAAA,CAAA,MAAA,CAAW,IAAA;AAEvB,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AACF;AAWO,IAAM,QAAA,GAAN,cAAuB,UAAA,CAAW;AAAA;AAAA,EAE9B,MAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA,EAEA,SAAA;AAAA;AAAA,EAEA,OAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EAET,WAAA,CACE,MAAA,EACA,OAAA,EACA,IAAA,GAAoF,EAAC,EACrF;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA;AACtB,IAAA,IAAA,CAAK,UAAU,IAAA,CAAK,OAAA;AACpB,IAAA,IAAA,CAAK,UAAU,IAAA,CAAK,OAAA;AAAA,EACtB;AACF;AAEO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAC;AACxC,IAAM,mBAAA,GAAN,cAAkC,QAAA,CAAS;AAAC;AAC5C,IAAM,qBAAA,GAAN,cAAoC,QAAA,CAAS;AAAC;AAC9C,IAAM,aAAA,GAAN,cAA4B,QAAA,CAAS;AAAC;AACtC,IAAM,aAAA,GAAN,cAA4B,QAAA,CAAS;AAAC;AACtC,IAAM,wBAAA,GAAN,cAAuC,QAAA,CAAS;AAAC;AAGjD,IAAM,cAAA,GAAN,cAA6B,QAAA,CAAS;AAAA;AAAA,EAElC,UAAA;AAAA,EAET,WAAA,CACE,MAAA,EACA,OAAA,EACA,IAAA,GAMI,EAAC,EACL;AACA,IAAA,KAAA,CAAM,MAAA,EAAQ,SAAS,IAAI,CAAA;AAC3B,IAAA,IAAA,CAAK,aAAa,IAAA,CAAK,UAAA;AAAA,EACzB;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,QAAA,CAAS;AAAC;AAG5C,IAAM,kBAAA,GAAN,cAAiC,UAAA,CAAW;AAAA,EACxC,KAAA;AAAA,EACT,WAAA,CAAY,OAAA,GAAU,kBAAA,EAAoB,IAAA,GAA4B,EAAC,EAAG;AACxE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,KAAA;AAAA,EACpB;AACF;AAGO,IAAM,yBAAA,GAAN,cAAwC,kBAAA,CAAmB;AAAA,EAChE,WAAA,CAAY,UAAU,mBAAA,EAAqB;AACzC,IAAA,KAAA,CAAM,OAAO,CAAA;AAAA,EACf;AACF;AAGO,IAAM,iBAAA,GAAN,cAAgC,UAAA,CAAW;AAAA,EAChD,WAAA,CAAY,UAAU,qBAAA,EAAuB;AAC3C,IAAA,KAAA,CAAM,OAAO,CAAA;AAAA,EACf;AACF;AAGO,SAAS,YAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACA,UAAA,EACU;AACV,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,OAAA,IAAW,CAAA,KAAA,EAAQ,MAAM,CAAA,CAAA;AAClD,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,MAAM,QAAA,CAAS,IAAA;AAAA,IACf,WAAW,QAAA,CAAS,SAAA;AAAA,IACpB,SAAS,QAAA,CAAS,OAAA;AAAA,IAClB;AAAA,GACF;AAEA,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,GAAA;AACH,MAAA,OAAO,IAAI,eAAA,CAAgB,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,IAClD,KAAK,GAAA;AACH,MAAA,OAAO,IAAI,mBAAA,CAAoB,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,IACtD,KAAK,GAAA;AACH,MAAA,OAAO,IAAI,qBAAA,CAAsB,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,IACxD,KAAK,GAAA;AACH,MAAA,OAAO,IAAI,aAAA,CAAc,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,IAChD,KAAK,GAAA;AACH,MAAA,OAAO,IAAI,aAAA,CAAc,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,IAChD,KAAK,GAAA;AACH,MAAA,OAAO,IAAI,wBAAA,CAAyB,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,IAC3D,KAAK,GAAA;AACH,MAAA,OAAO,IAAI,eAAe,MAAA,EAAQ,OAAA,EAAS,EAAE,GAAG,IAAA,EAAM,YAAY,CAAA;AAAA,IACpE;AACE,MAAA,IAAI,UAAU,GAAA,EAAK,OAAO,IAAI,mBAAA,CAAoB,MAAA,EAAQ,SAAS,IAAI,CAAA;AACvE,MAAA,OAAO,IAAI,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA;AAE/C;;;AC3IA,IAAM,aAAA,GAAgB,0BAAA;AACtB,IAAM,aAAA,GAAgB,8BAAA;AACtB,IAAM,kBAAA,GAAqB,GAAA;AAC3B,IAAM,mBAAA,GAAsB,CAAA;AA6C5B,SAAS,SAAA,GAAqB;AAC5B,EAAA,OAAO,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,OAAO,QAAA,KAAa,WAAA;AACrE;AAGA,SAAS,eAAe,WAAA,EAAuC;AAC7D,EAAA,OAAO,WAAA,KAAgB,SAAS,aAAA,GAAgB,aAAA;AAClD;AAGO,SAAS,eAAe,OAAA,EAAyC;AACtE,EAAA,IAAI,WAAU,EAAG;AACf,IAAA,MAAM,IAAI,UAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,WAAW,gEAAgE,CAAA;AAAA,EACvF;AAEA,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,IAAS,UAAA,CAAW,KAAA;AAC9C,EAAA,IAAI,OAAO,cAAc,UAAA,EAAY;AACnC,IAAA,MAAM,IAAI,UAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,kBAAA;AACnC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,IAAK,UAAU,CAAA,EAAG;AAC5C,IAAA,MAAM,IAAI,WAAW,yCAAyC,CAAA;AAAA,EAChE;AAEA,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,mBAAA;AACzC,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,UAAU,CAAA,IAAK,aAAa,CAAA,EAAG;AACnD,IAAA,MAAM,IAAI,WAAW,uCAAuC,CAAA;AAAA,EAC9D;AAEA,EAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,IAAe,YAAA;AAC3C,EAAA,IAAI,WAAA,KAAgB,YAAA,IAAgB,WAAA,KAAgB,MAAA,EAAQ;AAC1D,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,qBAAA,EAAwB,WAAW,CAAA,6BAAA,CAA+B,CAAA;AAAA,EACzF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,OAAA,EAAS,eAAe,WAAW,CAAA;AAAA,IACnC,OAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA,EAAO,OAAA,CAAQ,KAAA,IAAS,SAAA,CAAU,KAAK,UAAU;AAAA,GACnD;AACF;;;ACrGO,IAAM,OAAA,GAAU;;;ACkBvB,IAAM,aAAA,GAAgB,GAAA;AACtB,IAAM,YAAA,GAAe,GAAA;AAGd,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,IAAA,EAAuB;AAAvB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAwB;AAAA,EAErD,GAAA,CAAO,IAAA,EAAc,OAAA,GAAsB,EAAC,EAAe;AACzD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAW,KAAA,EAAO,IAAA,EAAM,OAAO,CAAA;AAAA,EAC7C;AAAA,EAEA,MAAc,OAAA,CAAW,MAAA,EAAgB,IAAA,EAAc,OAAA,EAAiC;AACtF,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,QAAQ,KAAK,CAAA;AAC7C,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,IAAA,CAAK,IAAA,CAAK,OAAA;AAC7C,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,IAAA,CAAK,IAAA,CAAK,UAAA;AAEnD,IAAA,IAAI,OAAA,GAAU,CAAA;AAEd,IAAA,WAAS;AACP,MAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,OAAA,CAAQ,MAAA,EAAQ,OAAO,CAAA;AACjD,MAAA,IAAI,QAAA;AAEJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,GAAA,EAAK;AAAA,UACpC,MAAA;AAAA,UACA,OAAA,EAAS,YAAA,CAAa,IAAA,CAAK,IAAA,CAAK,QAAQ,OAAO,CAAA;AAAA,UAC/C,QAAQ,KAAA,CAAM;AAAA,SACf,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,KAAA,CAAM,OAAA,EAAQ;AACd,QAAA,MAAM,MAAA,GAAS,aAAA,CAAc,GAAA,EAAK,KAAA,EAAO,QAAQ,MAAM,CAAA;AAEvD,QAAA,IAAI,MAAA,YAAkB,mBAAmB,MAAM,MAAA;AAC/C,QAAA,IAAI,UAAU,UAAA,EAAY;AACxB,UAAA,OAAA,IAAW,CAAA;AACX,UAAA,MAAM,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAC,CAAA;AAC5B,UAAA;AAAA,QACF;AACA,QAAA,MAAM,MAAA;AAAA,MACR;AAEA,MAAA,KAAA,CAAM,OAAA,EAAQ;AAEd,MAAA,IAAI,SAAS,EAAA,EAAI;AACf,QAAA,OAAO,UAAa,QAAQ,CAAA;AAAA,MAC9B;AAEA,MAAA,IAAI,iBAAA,CAAkB,QAAA,CAAS,MAAM,CAAA,IAAK,UAAU,UAAA,EAAY;AAC9D,QAAA,OAAA,IAAW,CAAA;AACX,QAAA,MAAM,MAAM,eAAA,CAAgB,QAAA,CAAS,OAAO,CAAA,IAAK,OAAA,CAAQ,OAAO,CAAC,CAAA;AACjE,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,MAAM,kBAAkB,QAAQ,CAAA;AAAA,IACxC;AAAA,EACF;AAAA,EAEQ,QAAA,CAAS,MAAc,KAAA,EAA6B;AAC1D,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,CAAA,EAAG,KAAK,IAAA,CAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA;AACjD,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAChD,QAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM,GAAA,CAAI,aAAa,GAAA,CAAI,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,MACpF;AAAA,IACF;AACA,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AACF,CAAA;AAEA,SAAS,YAAA,CAAa,QAAgB,OAAA,EAAyC;AAC7E,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,WAAA,EAAa,MAAA;AAAA,IACb,MAAA,EAAQ;AAAA,GACV;AACA,EAAA,MAAM,KAAK,SAAA,EAAU;AACrB,EAAA,IAAI,EAAA,EAAI,OAAA,CAAQ,YAAY,CAAA,GAAI,EAAA;AAChC,EAAA,IAAI,UAAU,CAAA,EAAG,OAAA,CAAQ,qBAAqB,CAAA,GAAI,OAAO,OAAO,CAAA;AAChE,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,SAAA,GAAoB;AAC3B,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,UAAU,IAAA,EAAM;AAC5D,IAAA,OAAO,CAAA,UAAA,EAAa,OAAO,CAAA,OAAA,EAAU,OAAA,CAAQ,SAAS,IAAI,CAAA,CAAA,CAAA;AAAA,EAC5D;AACA,EAAA,OAAO,aAAa,OAAO,CAAA,CAAA;AAC7B;AAGA,SAAS,WAAA,CAAY,YAAqC,SAAA,EAAmB;AAC3E,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,UAAA,CAAW,KAAA,CAAM,IAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AAAA,EACvC,GAAG,SAAS,CAAA;AAEZ,EAAA,MAAM,WAAA,GAAc,MAAM,UAAA,CAAW,KAAA,CAAM,YAAY,MAAM,CAAA;AAC7D,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,IAAI,UAAA,CAAW,OAAA,EAAS,UAAA,CAAW,KAAA,CAAM,WAAW,MAAM,CAAA;AAAA,oBAC1C,gBAAA,CAAiB,OAAA,EAAS,aAAa,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO;AAAA,IACL,QAAQ,UAAA,CAAW,MAAA;AAAA,IACnB,YAAY,MAAM,QAAA;AAAA,IAClB,SAAS,MAAM;AACb,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,UAAA,EAAY,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAAA,IACtD;AAAA,GACF;AACF;AAEA,SAAS,aAAA,CACP,GAAA,EACA,KAAA,EACA,UAAA,EACY;AACZ,EAAA,IAAI,UAAA,EAAY,OAAA,EAAS,OAAO,IAAI,iBAAA,EAAkB;AACtD,EAAA,IAAI,KAAA,CAAM,UAAA,EAAW,EAAG,OAAO,IAAI,yBAAA,EAA0B;AAC7D,EAAA,OAAO,IAAI,kBAAA,CAAmB,kBAAA,EAAoB,EAAE,KAAA,EAAO,KAAK,CAAA;AAClE;AAEA,SAAS,kBAAkB,MAAA,EAAyB;AAClD,EAAA,OAAO,WAAW,GAAA,IAAO,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,OAAO,MAAA,IAAU,GAAA;AACzE;AAEA,eAAe,UAAa,QAAA,EAAgC;AAC1D,EAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,WAAW,wCAAwC,CAAA;AAAA,EAC/D;AACF;AAEA,eAAe,kBAAkB,QAAA,EAAuC;AACtE,EAAA,IAAI,WAA6B,EAAC;AAClC,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,MAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU,QAAA,GAAW,MAAA;AAAA,IACvD;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,YAAA;AAAA,IACL,QAAA,CAAS,MAAA;AAAA,IACT,QAAA;AAAA,IACA,QAAA,CAAS,OAAA;AAAA,IACT,eAAA,CAAgB,SAAS,OAAO;AAAA,GAClC;AACF;AAGA,SAAS,gBAAgB,OAAA,EAAsC;AAC7D,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA;AACvC,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AACnB,EAAA,MAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC5B,EAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,SAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,GAAU,GAAI,CAAA;AAC7D,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC/B,EAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAA,GAAS,IAAA,CAAK,GAAA,EAAK,CAAA;AACjE,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,QAAQ,OAAA,EAAyB;AACxC,EAAA,MAAM,UAAU,IAAA,CAAK,GAAA,CAAI,cAAc,aAAA,GAAgB,CAAA,KAAM,UAAU,CAAA,CAAE,CAAA;AACzE,EAAA,OAAO,IAAA,CAAK,QAAO,GAAI,OAAA;AACzB;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;;;AC9LO,IAAe,cAAf,MAA2B;AAAA,EAChC,YAA+B,MAAA,EAAuB;AAAvB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAwB;AACzD,CAAA;;;ACKO,IAAM,SAAA,GAAN,cAAwB,WAAA,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAKzC,IAAA,CAAK,QAA6B,OAAA,EAAoD;AACpF,IAAA,IAAI,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM,IAAI,WAAW,oBAAoB,CAAA;AAC9D,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAqB,sBAAA,EAAwB;AAAA,MAC9D,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAO;AAAA,MAC/B,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AACF,CAAA;;;ACUA,IAAM,wBAAA,GAA2C,IAAA;AAE1C,IAAM,QAAA,GAAN,cAAuB,WAAA,CAAY;AAAA,EAWxC,MAAM,IAAA,CACJ,MAAA,GAA4B,IAC5B,OAAA,EACoD;AACpD,IAAA,MAAM,QAAQ,MAAA,CAAO,QAAA,GAAW,EAAE,QAAA,EAAU,MAAA,CAAO,UAAS,GAAI,MAAA;AAEhE,IAAA,IAAI,CAAC,OAAO,eAAA,EAAiB;AAC3B,MAAA,OAAO,IAAA,CAAK,OAAO,GAAA,CAAuB,WAAA,EAAa,EAAE,KAAA,EAAO,GAAG,SAAS,CAAA;AAAA,IAC9E;AAEA,IAAA,MAAM,CAAC,KAAA,EAAO,SAAS,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MAC3C,IAAA,CAAK,OAAO,GAAA,CAAuB,WAAA,EAAa,EAAE,KAAA,EAAO,GAAG,SAAS,CAAA;AAAA,MACrE,IAAA,CAAK,MAAA,CACF,GAAA,CAAqC,qBAAA,EAAuB,EAAE,KAAA,EAAO,GAAG,OAAA,EAAS,CAAA,CAEjF,KAAA,CAAM,OAAO,EAAC,CAAqC;AAAA,KACvD,CAAA;AAED,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,GAAG,IAAA,EAAM,QAAA,EAAU,SAAA,CAAU,IAAA,CAAK,EAAE,CAAA,IAAK,MAAK,CAAE,CAAA;AAAA,EAChF;AAAA,EAcA,MAAM,GAAA,CACJ,IAAA,EACA,MAAA,GAA2B,IAC3B,OAAA,EAC4D;AAC5D,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,MAAA,CAAO,GAAA;AAAA,MAChC,CAAA,UAAA,EAAa,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAA;AAAA,MACrC;AAAA,KACF;AAEA,IAAA,IAAI,CAAC,MAAA,CAAO,oBAAA,EAAsB,OAAO,OAAA;AAIzC,IAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,MAAA,CAC9B,GAAA,CAA0B,aAAa,kBAAA,CAAmB,OAAA,CAAQ,EAAE,CAAC,CAAA,MAAA,CAAA,EAAU;AAAA,MAC9E,KAAA,EAAO,EAAE,SAAA,EAAW,MAAA,CAAO,kBAAkB,wBAAA,EAAyB;AAAA,MACtE,GAAG;AAAA,KACJ,CAAA,CACA,KAAA,CAAM,MAAM,IAAI,CAAA;AAEnB,IAAA,OAAO,EAAE,GAAG,OAAA,EAAS,aAAA,EAAc;AAAA,EACrC;AACF,CAAA;;;ACxEO,IAAM,QAAN,MAAY;AAAA,EACR,QAAA;AAAA,EACA,SAAA;AAAA,EACQ,IAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAyB,EAAC,EAAG;AACvC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,aAAA,CAAc,cAAA,CAAe,OAAO,CAAC,CAAA;AACrD,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,QAAA,CAAS,IAAA,CAAK,IAAI,CAAA;AACtC,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA,EAIA,OAAgB,UAAA,GAAa,UAAA;AAAA,EAC7B,OAAgB,QAAA,GAAW,QAAA;AAAA,EAC3B,OAAgB,eAAA,GAAkB,eAAA;AAAA,EAClC,OAAgB,mBAAA,GAAsB,mBAAA;AAAA,EACtC,OAAgB,qBAAA,GAAwB,qBAAA;AAAA,EACxC,OAAgB,aAAA,GAAgB,aAAA;AAAA,EAChC,OAAgB,aAAA,GAAgB,aAAA;AAAA,EAChC,OAAgB,wBAAA,GAA2B,wBAAA;AAAA,EAC3C,OAAgB,cAAA,GAAiB,cAAA;AAAA,EACjC,OAAgB,mBAAA,GAAsB,mBAAA;AAAA,EACtC,OAAgB,kBAAA,GAAqB,kBAAA;AAAA,EACrC,OAAgB,yBAAA,GAA4B,yBAAA;AAAA,EAC5C,OAAgB,iBAAA,GAAoB,iBAAA;AACtC;;;ACsJO,SAAS,wBACd,KAAA,EACgC;AAChC,EAAA,OAAQ,MAAgC,gBAAA,KAAqB,IAAA;AAC/D","file":"index.js","sourcesContent":["/**\n * Error hierarchy thrown by the SDK.\n *\n * Everything extends {@link CestoError}. Server (non-2xx) responses become an\n * {@link APIError} subclass built from the API's `{ code, message, details,\n * requestId }` envelope; transport problems become {@link APIConnectionError}\n * (or its timeout subclass); caller cancellation becomes {@link APIUserAbortError}.\n */\n\n/** Base class for every error the SDK throws. */\nexport class CestoError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n // Restore the prototype chain for `instanceof` across the transpile target.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Parsed `{ code, message, details, requestId }` envelope from the API. */\nexport interface APIErrorEnvelope {\n code?: string;\n message?: string;\n details?: unknown;\n requestId?: string;\n}\n\n/** A non-2xx HTTP response. */\nexport class APIError extends CestoError {\n /** HTTP status code. */\n readonly status: number;\n /** Machine-readable error code from the API envelope (e.g. `RESOURCE_NOT_FOUND`). */\n readonly code?: string;\n /** Correlation id from the API envelope, useful when reporting issues. */\n readonly requestId?: string;\n /** Structured error details from the API envelope. */\n readonly details?: unknown;\n /** Response headers. */\n readonly headers?: Headers;\n\n constructor(\n status: number,\n message: string,\n opts: { code?: string; requestId?: string; details?: unknown; headers?: Headers } = {},\n ) {\n super(message);\n this.status = status;\n this.code = opts.code;\n this.requestId = opts.requestId;\n this.details = opts.details;\n this.headers = opts.headers;\n }\n}\n\nexport class BadRequestError extends APIError {}\nexport class AuthenticationError extends APIError {}\nexport class PermissionDeniedError extends APIError {}\nexport class NotFoundError extends APIError {}\nexport class ConflictError extends APIError {}\nexport class UnprocessableEntityError extends APIError {}\n\n/** HTTP 429. Carries `retryAfter` (ms) when the server sent a `Retry-After` header. */\nexport class RateLimitError extends APIError {\n /** Milliseconds to wait before retrying, derived from `Retry-After`. */\n readonly retryAfter?: number;\n\n constructor(\n status: number,\n message: string,\n opts: {\n code?: string;\n requestId?: string;\n details?: unknown;\n headers?: Headers;\n retryAfter?: number;\n } = {},\n ) {\n super(status, message, opts);\n this.retryAfter = opts.retryAfter;\n }\n}\n\nexport class InternalServerError extends APIError {}\n\n/** A network-level failure (DNS, connection reset, fetch threw). */\nexport class APIConnectionError extends CestoError {\n readonly cause?: unknown;\n constructor(message = 'Connection error', opts: { cause?: unknown } = {}) {\n super(message);\n this.cause = opts.cause;\n }\n}\n\n/** The request exceeded the configured timeout. */\nexport class APIConnectionTimeoutError extends APIConnectionError {\n constructor(message = 'Request timed out') {\n super(message);\n }\n}\n\n/** The caller's `AbortSignal` fired. */\nexport class APIUserAbortError extends CestoError {\n constructor(message = 'Request was aborted') {\n super(message);\n }\n}\n\n/** Build the right {@link APIError} subclass from a parsed error response. */\nexport function makeAPIError(\n status: number,\n envelope: APIErrorEnvelope,\n headers: Headers,\n retryAfter?: number,\n): APIError {\n const message = envelope.message || `HTTP ${status}`;\n const opts = {\n code: envelope.code,\n requestId: envelope.requestId,\n details: envelope.details,\n headers,\n };\n\n switch (status) {\n case 400:\n return new BadRequestError(status, message, opts);\n case 401:\n return new AuthenticationError(status, message, opts);\n case 403:\n return new PermissionDeniedError(status, message, opts);\n case 404:\n return new NotFoundError(status, message, opts);\n case 409:\n return new ConflictError(status, message, opts);\n case 422:\n return new UnprocessableEntityError(status, message, opts);\n case 429:\n return new RateLimitError(status, message, { ...opts, retryAfter });\n default:\n if (status >= 500) return new InternalServerError(status, message, opts);\n return new APIError(status, message, opts);\n }\n}\n","import { CestoError } from './errors.js';\n\nconst PROD_BASE_URL = 'https://backend.cesto.co';\nconst BETA_BASE_URL = 'https://dev.backend.cesto.co';\nconst DEFAULT_TIMEOUT_MS = 60_000;\nconst DEFAULT_MAX_RETRIES = 2;\n\n/** Which deployed Cesto backend to target. */\nexport type CestoEnvironment = 'PRODUCTION' | 'BETA';\n\n/** Options for constructing a {@link Cesto} client. */\nexport interface ClientOptions {\n /**\n * Secret API key (`cesto_sk_…`). Required — the constructor throws if omitted.\n * Read it from your environment yourself, e.g. `apiKey: process.env.CESTO_API_KEY`.\n */\n apiKey?: string;\n /**\n * Which backend to target in a deployed build (`NODE_ENV=production`):\n * `PRODUCTION` → backend.cesto.co, `BETA` → dev.backend.cesto.co. Default `PRODUCTION`.\n */\n environment?: CestoEnvironment;\n /** Per-request timeout in milliseconds. Default `60000`. */\n timeout?: number;\n /** Max automatic retries on transient failures. Default `2`. */\n maxRetries?: number;\n /** Custom fetch implementation (e.g. undici, a test mock). Default `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\n/** Per-request overrides accepted by every resource method. */\nexport interface RequestOptions {\n /** Override the client timeout (ms) for this request. */\n timeout?: number;\n /** Override the client retry count for this request (e.g. `0` to disable). */\n maxRetries?: number;\n /** Caller cancellation; composed with the internal timeout signal. */\n signal?: AbortSignal;\n}\n\n/** Fully-resolved, validated client configuration. */\nexport interface ResolvedOptions {\n apiKey: string;\n /** Normalized base URL, no trailing slash. */\n baseURL: string;\n timeout: number;\n maxRetries: number;\n fetch: typeof fetch;\n}\n\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof window.document !== 'undefined';\n}\n\n/** Resolve the backend URL as per `environment`. */\nfunction resolveBaseURL(environment: CestoEnvironment): string {\n return environment === 'BETA' ? BETA_BASE_URL : PROD_BASE_URL;\n}\n\n/** Validate and normalize {@link ClientOptions} into {@link ResolvedOptions}. */\nexport function resolveOptions(options: ClientOptions): ResolvedOptions {\n if (isBrowser()) {\n throw new CestoError(\n 'The Cesto SDK is server-side only. It must not run in a browser — a secret key ' +\n '(cesto_sk_…) would be exposed to end users.',\n );\n }\n\n const apiKey = options.apiKey\n if (!apiKey) {\n throw new CestoError('Missing API key. Pass { apiKey } when constructing the client.');\n }\n\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (typeof fetchImpl !== 'function') {\n throw new CestoError(\n 'No fetch implementation found. Use Node 18+ or pass a custom { fetch } in ClientOptions.',\n );\n }\n\n const timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n if (!Number.isFinite(timeout) || timeout < 0) {\n throw new CestoError('`timeout` must be a finite number >= 0.');\n }\n\n const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n if (!Number.isInteger(maxRetries) || maxRetries < 0) {\n throw new CestoError('`maxRetries` must be an integer >= 0.');\n }\n\n const environment = options.environment ?? 'PRODUCTION';\n if (environment !== 'PRODUCTION' && environment !== 'BETA') {\n throw new CestoError(`Invalid environment: ${environment}. Use 'PRODUCTION' or 'BETA'.`);\n }\n\n return {\n apiKey,\n baseURL: resolveBaseURL(environment),\n timeout,\n maxRetries,\n fetch: options.fetch ?? fetchImpl.bind(globalThis),\n };\n}\n","/** SDK version. Keep in sync with package.json `version`. */\nexport const VERSION = '0.0.1';\n","import {\n APIConnectionError,\n APIConnectionTimeoutError,\n type APIError,\n type APIErrorEnvelope,\n APIUserAbortError,\n CestoError,\n makeAPIError,\n} from './errors.js';\nimport type { RequestOptions, ResolvedOptions } from './options.js';\nimport { VERSION } from './version.js';\n\n/** Query parameters; `undefined`/`null` values are skipped. */\nexport type QueryParams = Record<string, string | number | boolean | undefined | null>;\n\ninterface GetOptions extends RequestOptions {\n query?: QueryParams;\n}\n\nconst RETRY_BASE_MS = 500;\nconst RETRY_CAP_MS = 8_000;\n\n/** Internal transport: builds requests, applies auth, retries, and parses JSON. */\nexport class APIClientCore {\n constructor(private readonly opts: ResolvedOptions) {}\n\n get<T>(path: string, options: GetOptions = {}): Promise<T> {\n return this.request<T>('GET', path, options);\n }\n\n private async request<T>(method: string, path: string, options: GetOptions): Promise<T> {\n const url = this.buildURL(path, options.query);\n const timeout = options.timeout ?? this.opts.timeout;\n const maxRetries = options.maxRetries ?? this.opts.maxRetries;\n\n let attempt = 0;\n // Loop: returns on success/non-retryable error, retries transient failures.\n for (;;) {\n const timer = withTimeout(options.signal, timeout);\n let response: Response;\n\n try {\n response = await this.opts.fetch(url, {\n method,\n headers: buildHeaders(this.opts.apiKey, attempt),\n signal: timer.signal,\n });\n } catch (err) {\n timer.cleanup();\n const mapped = mapFetchError(err, timer, options.signal);\n // Never retry a user abort.\n if (mapped instanceof APIUserAbortError) throw mapped;\n if (attempt < maxRetries) {\n attempt += 1;\n await sleep(backoff(attempt));\n continue;\n }\n throw mapped;\n }\n\n timer.cleanup();\n\n if (response.ok) {\n return parseJSON<T>(response);\n }\n\n if (shouldRetryStatus(response.status) && attempt < maxRetries) {\n attempt += 1;\n await sleep(parseRetryAfter(response.headers) ?? backoff(attempt));\n continue;\n }\n\n throw await errorFromResponse(response);\n }\n }\n\n private buildURL(path: string, query?: QueryParams): string {\n const url = new URL(`${this.opts.baseURL}${path}`);\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) url.searchParams.set(key, String(value));\n }\n }\n return url.toString();\n }\n}\n\nfunction buildHeaders(apiKey: string, attempt: number): Record<string, string> {\n const headers: Record<string, string> = {\n 'X-API-Key': apiKey,\n Accept: 'application/json',\n };\n const ua = userAgent();\n if (ua) headers['User-Agent'] = ua;\n if (attempt > 0) headers['x-cesto-retry-count'] = String(attempt);\n return headers;\n}\n\nfunction userAgent(): string {\n if (typeof process !== 'undefined' && process.versions?.node) {\n return `cesto-sdk/${VERSION} (node/${process.versions.node})`;\n }\n return `cesto-sdk/${VERSION}`;\n}\n\n/** AbortController that fires on either the caller's signal or the timeout. */\nfunction withTimeout(userSignal: AbortSignal | undefined, timeoutMs: number) {\n const controller = new AbortController();\n let timedOut = false;\n\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort(new Error('timeout'));\n }, timeoutMs);\n\n const onUserAbort = () => controller.abort(userSignal?.reason);\n if (userSignal) {\n if (userSignal.aborted) controller.abort(userSignal.reason);\n else userSignal.addEventListener('abort', onUserAbort, { once: true });\n }\n\n return {\n signal: controller.signal,\n didTimeout: () => timedOut,\n cleanup: () => {\n clearTimeout(timer);\n userSignal?.removeEventListener('abort', onUserAbort);\n },\n };\n}\n\nfunction mapFetchError(\n err: unknown,\n timer: { didTimeout: () => boolean },\n userSignal: AbortSignal | undefined,\n): CestoError {\n if (userSignal?.aborted) return new APIUserAbortError();\n if (timer.didTimeout()) return new APIConnectionTimeoutError();\n return new APIConnectionError('Connection error', { cause: err });\n}\n\nfunction shouldRetryStatus(status: number): boolean {\n return status === 408 || status === 409 || status === 429 || status >= 500;\n}\n\nasync function parseJSON<T>(response: Response): Promise<T> {\n const text = await response.text();\n if (!text) return undefined as T;\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new CestoError('Failed to parse response body as JSON.');\n }\n}\n\nasync function errorFromResponse(response: Response): Promise<APIError> {\n let envelope: APIErrorEnvelope = {};\n try {\n const text = await response.text();\n if (text) {\n const parsed = JSON.parse(text) as unknown;\n if (parsed && typeof parsed === 'object') envelope = parsed as APIErrorEnvelope;\n }\n } catch {\n // Non-JSON error body — fall back to status-only error.\n }\n return makeAPIError(\n response.status,\n envelope,\n response.headers,\n parseRetryAfter(response.headers),\n );\n}\n\n/** Parse a `Retry-After` header (delta-seconds or HTTP-date) into milliseconds. */\nfunction parseRetryAfter(headers: Headers): number | undefined {\n const value = headers.get('retry-after');\n if (!value) return undefined;\n const seconds = Number(value);\n if (!Number.isNaN(seconds)) return Math.max(0, seconds * 1000);\n const dateMs = Date.parse(value);\n if (!Number.isNaN(dateMs)) return Math.max(0, dateMs - Date.now());\n return undefined;\n}\n\n/** Exponential backoff with full jitter, capped. */\nfunction backoff(attempt: number): number {\n const ceiling = Math.min(RETRY_CAP_MS, RETRY_BASE_MS * 2 ** (attempt - 1));\n return Math.random() * ceiling;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { APIClientCore } from '../core/request.js';\n\n/** Base class for resource groups; holds a reference to the transport. */\nexport abstract class APIResource {\n constructor(protected readonly client: APIClientCore) {}\n}\n","import { CestoError } from '../core/errors.js';\nimport type { RequestOptions } from '../core/options.js';\nimport type { PositionsResult } from '../types/positions.js';\nimport { APIResource } from './resource.js';\n\nexport interface PositionsListParams {\n /** External Solana wallet address (Phantom/Solflare). Required. */\n wallet: string;\n}\n\nexport class Positions extends APIResource {\n /**\n * List a user's open/closing positions, resolved from their external Solana\n * wallet. A wallet with no Cesto account returns an empty result (not an error).\n */\n list(params: PositionsListParams, options?: RequestOptions): Promise<PositionsResult> {\n if (!params?.wallet) throw new CestoError('wallet is required');\n return this.client.get<PositionsResult>('/positions/by-wallet', {\n query: { wallet: params.wallet },\n ...options,\n });\n }\n}\n","import type { RequestOptions } from '../core/options.js';\nimport type {\n ProductBacktest,\n ProductBacktestChart,\n ProductListItem,\n ProductVersionResponse,\n ProductWithBacktest,\n ProductWithBacktestChart,\n} from '../types/products.js';\nimport type { ChartTimeRange } from '../types/shared.js';\nimport { APIResource } from './resource.js';\n\nexport interface ProductListParams {\n /** Filter by category. */\n category?: string;\n /**\n * Also fetch backtested performance (`GET /products/analytics`) and merge it\n * onto each product as `backtest`. Fails gracefully → `backtest: null`.\n */\n includeBacktest?: boolean;\n}\n\nexport interface ProductGetParams {\n /**\n * Also fetch the product's backtested value chart and attach it as `backtestChart`.\n * Fails gracefully → `backtestChart: null`.\n */\n includeBacktestChart?: boolean;\n /** Chart window when `includeBacktestChart` is true. Default `'1y'`. */\n chartTimeRange?: ChartTimeRange;\n}\n\nconst DEFAULT_CHART_TIME_RANGE: ChartTimeRange = '1y';\n\nexport class Products extends APIResource {\n /** List products. */\n list(): Promise<ProductListItem[]>;\n list(\n params: ProductListParams & { includeBacktest?: false },\n options?: RequestOptions,\n ): Promise<ProductListItem[]>;\n list(\n params: ProductListParams & { includeBacktest: true },\n options?: RequestOptions,\n ): Promise<ProductWithBacktest[]>;\n async list(\n params: ProductListParams = {},\n options?: RequestOptions,\n ): Promise<ProductListItem[] | ProductWithBacktest[]> {\n const query = params.category ? { category: params.category } : undefined;\n\n if (!params.includeBacktest) {\n return this.client.get<ProductListItem[]>('/products', { query, ...options });\n }\n\n const [items, backtests] = await Promise.all([\n this.client.get<ProductListItem[]>('/products', { query, ...options }),\n this.client\n .get<Record<string, ProductBacktest>>('/products/analytics', { query, ...options })\n // Graceful: a failed/slow analytics fetch never breaks the list.\n .catch(() => ({}) as Record<string, ProductBacktest>),\n ]);\n\n return items.map((item) => ({ ...item, backtest: backtests[item.id] ?? null }));\n }\n\n /** Get a product by slug. */\n get(slug: string): Promise<ProductVersionResponse>;\n get(\n slug: string,\n params: ProductGetParams & { includeBacktestChart?: false },\n options?: RequestOptions,\n ): Promise<ProductVersionResponse>;\n get(\n slug: string,\n params: ProductGetParams & { includeBacktestChart: true },\n options?: RequestOptions,\n ): Promise<ProductWithBacktestChart>;\n async get(\n slug: string,\n params: ProductGetParams = {},\n options?: RequestOptions,\n ): Promise<ProductVersionResponse | ProductWithBacktestChart> {\n const product = await this.client.get<ProductVersionResponse>(\n `/products/${encodeURIComponent(slug)}`,\n options,\n );\n\n if (!params.includeBacktestChart) return product;\n\n // Sequential: the chart is keyed by productId, which we only have after the\n // detail fetch resolves the slug. Graceful: a chart failure → null.\n const backtestChart = await this.client\n .get<ProductBacktestChart>(`/products/${encodeURIComponent(product.id)}/graph`, {\n query: { timeRange: params.chartTimeRange ?? DEFAULT_CHART_TIME_RANGE },\n ...options,\n })\n .catch(() => null);\n\n return { ...product, backtestChart };\n }\n}\n","import {\n APIConnectionError,\n APIConnectionTimeoutError,\n APIError,\n APIUserAbortError,\n AuthenticationError,\n BadRequestError,\n CestoError,\n ConflictError,\n InternalServerError,\n NotFoundError,\n PermissionDeniedError,\n RateLimitError,\n UnprocessableEntityError,\n} from './core/errors.js';\nimport { type ClientOptions, resolveOptions } from './core/options.js';\nimport { APIClientCore } from './core/request.js';\nimport { Positions } from './resources/positions.js';\nimport { Products } from './resources/products.js';\n\n/**\n * The Cesto SDK client.\n *\n * @example\n * ```ts\n * const cesto = new Cesto({ apiKey: process.env.CESTO_API_KEY! });\n * const products = await cesto.products.list({ includeBacktest: true });\n * ```\n */\nexport class Cesto {\n readonly products: Products;\n readonly positions: Positions;\n private readonly core: APIClientCore;\n\n constructor(options: ClientOptions = {}) {\n this.core = new APIClientCore(resolveOptions(options));\n this.products = new Products(this.core);\n this.positions = new Positions(this.core);\n }\n\n // Error classes re-exposed for ergonomic `instanceof` checks:\n // catch (e) { if (e instanceof Cesto.NotFoundError) … }\n static readonly CestoError = CestoError;\n static readonly APIError = APIError;\n static readonly BadRequestError = BadRequestError;\n static readonly AuthenticationError = AuthenticationError;\n static readonly PermissionDeniedError = PermissionDeniedError;\n static readonly NotFoundError = NotFoundError;\n static readonly ConflictError = ConflictError;\n static readonly UnprocessableEntityError = UnprocessableEntityError;\n static readonly RateLimitError = RateLimitError;\n static readonly InternalServerError = InternalServerError;\n static readonly APIConnectionError = APIConnectionError;\n static readonly APIConnectionTimeoutError = APIConnectionTimeoutError;\n static readonly APIUserAbortError = APIUserAbortError;\n}\n","import type {\n ChartTimeRange,\n GeoStatus,\n IncentiveOverlayCampaign,\n PredictionMarketState,\n TokenPerformance,\n} from './shared.js';\n\n/** An item in `products.list()` — `GET /products`. */\nexport interface ProductListItem {\n id: string;\n slug: string;\n name: string;\n description: string | null;\n logoUrl: string | null;\n category: string | null;\n tags: string[];\n isActive: boolean;\n isPublished: boolean;\n pointMultiplier: number;\n metadata: Record<string, unknown> | null;\n geoStatus: GeoStatus;\n /** Active incentive campaigns; `[]` when none. */\n incentives: IncentiveOverlayCampaign[];\n}\n\n/** Backtested performance for a product — `GET /products/analytics` (per product). */\nexport interface ProductBacktest {\n protocolsInvolved: string[];\n tokensInvolved: string[];\n tokenPerformance: TokenPerformance | null;\n tokenPerformance7d: TokenPerformance | null;\n tokenPerformance30d: TokenPerformance | null;\n priceChange24h: number | null;\n tokenPriceChanges: Record<\n string,\n { priceChange24h: number | null; priceChange24hPercent: number | null }\n >;\n}\n\n/** `products.list({ includeBacktest: true })` — list item with backtest merged in. */\nexport type ProductWithBacktest = ProductListItem & {\n backtest: ProductBacktest | null;\n};\n\nexport interface ProductCreator {\n id: string;\n username: string | null;\n email: string | null;\n solanaWalletAddress: string | null;\n embeddedWalletAddress: string | null;\n}\n\nexport interface OndoTradingStatus {\n allTradable: boolean;\n currentSession: string;\n hasOndoTokens: boolean;\n tokens: unknown[];\n untradableTokens: unknown[];\n nextFullyTradableAt: string | null;\n nextFullyTradableSession: string | null;\n}\n\n/** Full product detail — `GET /products/:slug`. */\nexport interface ProductVersionResponse {\n id: string;\n versionId: string;\n version: number;\n changelog: string | null;\n minimumInvestment: string;\n inputTokenMint: string;\n inputTokenDecimals: number;\n about: string | null;\n riskNotes: string | null;\n resources: string | null;\n name: string;\n slug: string;\n description: string | null;\n logoUrl: string | null;\n category: string | null;\n tags: string[];\n isActive: boolean;\n isPublished: boolean;\n metadata: Record<string, unknown> | null;\n pointMultiplier: number;\n createdBy: string;\n creator: ProductCreator | null;\n tokensInvolved: string[];\n protocolsInvolved: string[];\n tokenPerformance: TokenPerformance | null;\n tokenPerformance7d: TokenPerformance | null;\n tokenPerformance30d: TokenPerformance | null;\n predictionMarkets?: PredictionMarketState[];\n canInvest: boolean;\n /** Raw workflow definition. */\n definition: unknown;\n geoStatus: GeoStatus;\n ondoTradingStatus: OndoTradingStatus;\n incentives?: IncentiveOverlayCampaign[];\n}\n\nexport interface BacktestChartTimeSeriesPoint {\n timestamp: string;\n portfolioValue: number;\n sp500Value?: number;\n mag7Value?: number;\n btcValue?: number;\n solValue?: number;\n usdcValue?: number;\n isLiquidated?: boolean;\n liquidationThreshold?: number;\n}\n\nexport interface BacktestChartMetrics {\n totalReturn: number;\n cagr: number;\n volatility: number;\n maxDrawdown: number;\n sharpe: number;\n}\n\nexport interface PredictionMarketEvent {\n ticker: string;\n marketTicker: string;\n seriesTicker: string;\n title: string;\n closeTime: number;\n currentProbability?: number;\n currentPrice: number;\n daysToClose: number;\n timeSeries: Array<{\n market_ticker: string;\n event_ticker: string;\n raw_numerical_forecast: number;\n numerical_forecast: number;\n formatted_forecast: string;\n end_period_ts: number;\n period_interval: number;\n }>;\n}\n\n/** Token-portfolio backtest chart — `GET /products/:id/graph` (non-prediction). */\nexport interface BacktestChart {\n workflowId: string;\n name: string;\n timeRange?: ChartTimeRange;\n timeSeries: BacktestChartTimeSeriesPoint[];\n /** Computed only when `timeRange === '1y'`; null otherwise. */\n metrics: BacktestChartMetrics | null;\n assetPerformance: Array<{ token: string; mint: string; returnPct: number }>;\n contributions: Array<{ token: string; mint: string; contribution: number }>;\n assetSparklines: Array<{\n token: string;\n mint: string;\n points: Array<{ timestamp: string; value: number; price: number }>;\n }>;\n checkpoints?: Array<{\n timestamp: string;\n version: number;\n fromVersion: number | null;\n changelog: string | null;\n added: Array<{ token: string; mint: string; allocation: number }>;\n removed: Array<{ token: string; mint: string; allocation: number }>;\n reweighted: Array<{ token: string; mint: string; fromPct: number; toPct: number }>;\n }>;\n liquidationInfo?: {\n hasLiquidations: boolean;\n liquidationEvents: Array<{\n timestamp: string;\n asset: string;\n liquidationPrice: number;\n actualPrice: number;\n }>;\n liquidationThresholds: Array<{\n asset: string;\n mint: string;\n liquidationPrice: number;\n entryPrice: number;\n leverage: number;\n direction: 'LONG' | 'SHORT';\n }>;\n };\n hasPredictionMarkets?: boolean;\n predictionMarketEvents?: PredictionMarketEvent[];\n incentives?: IncentiveOverlayCampaign[];\n}\n\n/** Prediction-market backtest chart — `GET /products/:id/graph` (prediction). */\nexport interface PredictionMarketChart {\n workflowId: string;\n name: string;\n predictionMarket: boolean;\n markets: PredictionMarketEvent[];\n incentives?: IncentiveOverlayCampaign[];\n}\n\n/** Union returned by the graph endpoint. Discriminate with {@link isPredictionMarketChart}. */\nexport type ProductBacktestChart = BacktestChart | PredictionMarketChart;\n\n/** `products.get(slug, { includeBacktestChart: true })` — detail with chart merged in. */\nexport type ProductWithBacktestChart = ProductVersionResponse & {\n backtestChart: ProductBacktestChart | null;\n};\n\n/** Type guard: is this chart the prediction-market variant? */\nexport function isPredictionMarketChart(\n chart: ProductBacktestChart,\n): chart is PredictionMarketChart {\n return (chart as PredictionMarketChart).predictionMarket === true;\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cesto/sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Typed, server-side TypeScript SDK for the Cesto read-only API.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Cesto",
|
|
8
|
+
"homepage": "https://github.com/cesto-co/cesto/tree/main/packages/sdk#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/cesto-co/cesto.git",
|
|
12
|
+
"directory": "packages/sdk"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/cesto-co/cesto/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"cesto",
|
|
19
|
+
"solana",
|
|
20
|
+
"defi",
|
|
21
|
+
"sdk",
|
|
22
|
+
"api-client",
|
|
23
|
+
"typescript",
|
|
24
|
+
"prediction-markets",
|
|
25
|
+
"portfolio"
|
|
26
|
+
],
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"import": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"require": {
|
|
35
|
+
"types": "./dist/index.d.cts",
|
|
36
|
+
"default": "./dist/index.cjs"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"main": "./dist/index.cjs",
|
|
41
|
+
"module": "./dist/index.js",
|
|
42
|
+
"types": "./dist/index.d.ts",
|
|
43
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"dev": "tsup --watch",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"test:watch": "vitest",
|
|
56
|
+
"lint": "biome check .",
|
|
57
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
58
|
+
"prepublishOnly": "pnpm run clean && pnpm run build"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/node": "^22.10.7",
|
|
62
|
+
"tsup": "^8.5.0",
|
|
63
|
+
"typescript": "5.5.4",
|
|
64
|
+
"vitest": "^3.2.4"
|
|
65
|
+
}
|
|
66
|
+
}
|