@coinlist-co/react 0.12.2-rc.bc20f5b → 0.12.2-rc.e1f6c82

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.
Files changed (33) hide show
  1. package/dist/{chunk-3WW5FLT7.js → chunk-EKLUJZ7T.js} +10 -10
  2. package/dist/chunk-EKLUJZ7T.js.map +1 -0
  3. package/dist/{chunk-C6GF7MDF.js → chunk-GIE4UWB3.js} +680 -619
  4. package/dist/chunk-GIE4UWB3.js.map +1 -0
  5. package/dist/chunk-MJ6YXZWH.js +22 -0
  6. package/dist/chunk-MJ6YXZWH.js.map +1 -0
  7. package/dist/{chunk-IZJ4JSSC.js → chunk-PIOQA6HW.js} +173 -234
  8. package/dist/chunk-PIOQA6HW.js.map +1 -0
  9. package/dist/client/index.d.ts +2414 -5239
  10. package/dist/client/index.js +683 -788
  11. package/dist/client/index.js.map +1 -1
  12. package/dist/server/index.d.ts +2 -32
  13. package/dist/server/index.js +6 -4
  14. package/dist/server/index.js.map +1 -1
  15. package/dist/{time-CVZpAkGY.d.cts → time-Bbqlt2x7.d.ts} +1907 -3183
  16. package/dist/{token-registry-snapshot-BkwA8KmD.d.ts → token-registry-snapshot-DttZXGvY.d.ts} +7 -41
  17. package/dist/universal/index.d.ts +57 -1044
  18. package/dist/universal/index.js +16 -42
  19. package/package.json +18 -14
  20. package/dist/chunk-3WW5FLT7.js.map +0 -1
  21. package/dist/chunk-C6GF7MDF.js.map +0 -1
  22. package/dist/chunk-IZJ4JSSC.js.map +0 -1
  23. package/dist/client/index.cjs +0 -20460
  24. package/dist/client/index.cjs.map +0 -1
  25. package/dist/client/index.d.cts +0 -8195
  26. package/dist/server/index.cjs +0 -4525
  27. package/dist/server/index.cjs.map +0 -1
  28. package/dist/server/index.d.cts +0 -382
  29. package/dist/time-CVZpAkGY.d.ts +0 -3987
  30. package/dist/token-registry-snapshot-bR14QehS.d.cts +0 -245
  31. package/dist/universal/index.cjs +0 -4562
  32. package/dist/universal/index.cjs.map +0 -1
  33. package/dist/universal/index.d.cts +0 -1362
@@ -1,4525 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/server/index.ts
21
- var server_exports = {};
22
- __export(server_exports, {
23
- ServerOffersNamespaceImpl: () => ServerOffersNamespaceImpl,
24
- ServerRequirementsNamespaceImpl: () => ServerRequirementsNamespaceImpl,
25
- WritableSessionStoreRequiredError: () => WritableSessionStoreRequiredError,
26
- createCoinListServer: () => createCoinListServer,
27
- emptySessionStore: () => emptySessionStore,
28
- pinoServerLogger: () => pinoServerLogger
29
- });
30
- module.exports = __toCommonJS(server_exports);
31
-
32
- // src/universal/api/internal-access-token-source.ts
33
- var SentWith = {
34
- userToken: (token) => ({
35
- type: "user-token",
36
- token
37
- }),
38
- noUserToken: { type: "no-user-token" }
39
- };
40
- var TokenTrigger = {
41
- beforeRequest: { type: "before-request" },
42
- after401: (rejected) => ({
43
- type: "after-401",
44
- rejected
45
- })
46
- };
47
- function isRejectedToken(token, rejected) {
48
- switch (rejected.type) {
49
- case "user-token":
50
- return rejected.token.value === token.value;
51
- case "no-user-token":
52
- return false;
53
- }
54
- }
55
-
56
- // src/universal/api/http-attributes.ts
57
- var empty = {};
58
- var concat = (left, right) => ({
59
- ...left,
60
- ...right
61
- });
62
- var concatAll = (...items) => {
63
- let result = empty;
64
- for (const item of items) {
65
- result = concat(result, item);
66
- }
67
- return result;
68
- };
69
- var protectedRequest = () => ({ protected: true });
70
- var userAgent = () => ({ userAgent: true });
71
- var idempotencyKey = () => ({
72
- idempotencyKey: true
73
- });
74
- var clientCredentials = (credentials) => ({
75
- clientCredentials: credentials
76
- });
77
- var retryAttempt = (attempt) => ({
78
- retryAttempt: attempt
79
- });
80
- var renewAttempted = (value) => ({
81
- renewAttempted: value
82
- });
83
- var notRetryable = () => ({ retryable: false });
84
- var sentWith = (token) => ({
85
- sentWith: token
86
- });
87
- var requestId = (id) => ({ requestId: id });
88
- var getRequestId = (attrs) => attrs?.requestId ?? null;
89
- var isProtected = (attrs) => attrs?.protected === true;
90
- var needUserAgent = (attrs) => attrs?.userAgent === true;
91
- var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
92
- var getRetryAttempt = (attrs) => attrs?.retryAttempt ?? 0;
93
- var wasRenewAttempted = (attrs) => attrs?.renewAttempted === true;
94
- var isRetryable = (attrs) => attrs?.retryable !== false;
95
- var getSentWith = (attrs) => attrs?.sentWith === void 0 ? SentWith.noUserToken : SentWith.userToken(attrs.sentWith);
96
- var getClientCredentials = (attrs) => attrs?.clientCredentials;
97
- var Attributes = {
98
- empty,
99
- concat,
100
- concatAll,
101
- protected: protectedRequest,
102
- isProtected,
103
- userAgent,
104
- needUserAgent,
105
- idempotencyKey,
106
- isIdempotent,
107
- retryAttempt,
108
- getRetryAttempt,
109
- renewAttempted,
110
- wasRenewAttempted,
111
- notRetryable,
112
- isRetryable,
113
- sentWith,
114
- getSentWith,
115
- clientCredentials,
116
- getClientCredentials,
117
- requestId,
118
- getRequestId
119
- };
120
-
121
- // src/universal/api/http.ts
122
- var HttpError = class extends Error {
123
- constructor(response) {
124
- super(`Request failed with ${response.status} status`);
125
- this.name = "HttpError";
126
- this.response = response;
127
- }
128
- /**
129
- * Correlates this failure with the `[HTTP]` log lines for the same request,
130
- * which carry the method, the URL, the duration and every retry. `null` when
131
- * the response did not come from an {@link HttpClient}.
132
- *
133
- * Worth quoting in a bug report: it is what makes a log excerpt readable.
134
- */
135
- get requestId() {
136
- return this.response.requestId ?? null;
137
- }
138
- };
139
- function apiErrorCode(error) {
140
- if (!(error instanceof HttpError)) return null;
141
- const body = error.response.body;
142
- if (typeof body !== "object" || body === null) return null;
143
- const code = body.code;
144
- return typeof code === "string" ? code : null;
145
- }
146
- async function makeRequest(request) {
147
- const headers = {
148
- Accept: "application/json",
149
- ...request.method === "POST" && request.body !== void 0 ? { "Content-Type": "application/json" } : {},
150
- ...request.headers ?? {}
151
- };
152
- const init = {
153
- method: request.method,
154
- headers,
155
- ...request.redirect !== void 0 ? { redirect: request.redirect } : {}
156
- };
157
- if (request.method === "POST" && request.body !== void 0) {
158
- init.body = JSON.stringify(request.body);
159
- }
160
- const response = await fetch(
161
- buildUrlWithQueryParams(request.url, request.queryParams),
162
- init
163
- );
164
- const responseHeaders = headersToRecord(response.headers);
165
- if (response.status === 204 || response.status === 205) {
166
- return {
167
- status: response.status,
168
- body: null,
169
- headers: responseHeaders
170
- };
171
- }
172
- if (response.status >= 300 && response.status < 400) {
173
- await response.text();
174
- return {
175
- status: response.status,
176
- body: null,
177
- headers: responseHeaders
178
- };
179
- }
180
- const text = await response.text();
181
- let body;
182
- try {
183
- body = text ? JSON.parse(text) : null;
184
- } catch (_) {
185
- throw new HttpError({
186
- status: response.status,
187
- headers: responseHeaders,
188
- body: text
189
- });
190
- }
191
- return {
192
- status: response.status,
193
- body,
194
- headers: responseHeaders
195
- };
196
- }
197
- function buildUrlWithQueryParams(url, queryParams) {
198
- if (!queryParams) {
199
- return url;
200
- }
201
- const searchParams = new URLSearchParams();
202
- for (const [key, value] of Object.entries(queryParams)) {
203
- if (value === void 0 || value === null) {
204
- continue;
205
- }
206
- if (Array.isArray(value)) {
207
- for (const item of value) {
208
- if (item === void 0 || item === null) {
209
- continue;
210
- }
211
- searchParams.append(key, String(item));
212
- }
213
- continue;
214
- }
215
- searchParams.append(key, String(value));
216
- }
217
- const queryString = searchParams.toString();
218
- if (!queryString) {
219
- return url;
220
- }
221
- return url.includes("?") ? `${url}&${queryString}` : `${url}?${queryString}`;
222
- }
223
- function headersToRecord(headers) {
224
- const record = {};
225
- headers.forEach((value, key) => {
226
- record[key.toLowerCase()] = value;
227
- });
228
- return record;
229
- }
230
- function concatAttributes(request, attrs) {
231
- const nextAttributes = Attributes.concat(
232
- request.attributes ?? Attributes.empty,
233
- attrs
234
- );
235
- const nextRequest = {
236
- ...request,
237
- attributes: nextAttributes
238
- };
239
- return nextRequest;
240
- }
241
- var Request = {
242
- concatAttributes
243
- };
244
-
245
- // src/universal/api/frontline/config.ts
246
- var PUBLIC_API_BASE_URL = "https://api.coinlist.co";
247
- var HEADER_API_VERSION = "X-API-Version";
248
- var HEADER_IDEMPOTENCY_KEY = "Idempotency-Key";
249
- var API_VERSION = "2025-10-17";
250
-
251
- // src/universal/core/shared/observability/log-cause.ts
252
- var import_viem = require("viem");
253
-
254
- // src/universal/types/errors.ts
255
- var NotImplementedError = class extends Error {
256
- constructor(message = "Not implemented yet") {
257
- super(message);
258
- this.name = "NotImplementedError";
259
- }
260
- };
261
- var NotAuthenticatedError = class extends Error {
262
- constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
263
- super(message);
264
- this.name = "NotAuthenticatedError";
265
- }
266
- };
267
- var ValidationError = class extends Error {
268
- constructor(message) {
269
- super(message);
270
- this.name = "ValidationError";
271
- }
272
- };
273
- var InvariantError = class extends Error {
274
- constructor(message) {
275
- super(message);
276
- this.name = "InvariantError";
277
- }
278
- };
279
- var MathError = class extends Error {
280
- constructor(message) {
281
- super(message);
282
- this.name = "MathError";
283
- }
284
- };
285
-
286
- // src/universal/core/shared/observability/log-cause.ts
287
- function classifyLogCause(error) {
288
- if (error instanceof HttpError) {
289
- return httpCause(error);
290
- }
291
- if (error instanceof ValidationError) {
292
- return { type: "validation", message: error.message };
293
- }
294
- if (error instanceof InvariantError) {
295
- return { type: "invariant", message: error.message };
296
- }
297
- if (error instanceof MathError) {
298
- return { type: "math", message: error.message };
299
- }
300
- if (error instanceof NotAuthenticatedError) {
301
- return { type: "not-authenticated" };
302
- }
303
- if (error instanceof NotImplementedError) {
304
- return { type: "not-implemented" };
305
- }
306
- if (error instanceof import_viem.BaseError) {
307
- const http2 = error.walk((e) => e instanceof HttpError);
308
- if (http2 instanceof HttpError) {
309
- return httpCause(http2);
310
- }
311
- return { type: "rpc", reason: rpcFailureReason(error) };
312
- }
313
- return { type: "generic-error", name: errorName(error) };
314
- }
315
- function rpcFailureReason(error) {
316
- if (error.walk((e) => e instanceof import_viem.ContractFunctionRevertedError)) {
317
- return "reverted";
318
- }
319
- if (error.walk((e) => e instanceof import_viem.RpcError)) {
320
- return "node-rejected";
321
- }
322
- if (error.walk(
323
- (e) => e instanceof import_viem.HttpRequestError || e instanceof import_viem.WebSocketRequestError || e instanceof import_viem.SocketClosedError || e instanceof import_viem.TimeoutError
324
- )) {
325
- return "transport";
326
- }
327
- if (error instanceof import_viem.ContractFunctionExecutionError) {
328
- return "malformed-response";
329
- }
330
- return "unknown";
331
- }
332
- function describeErrorUnredacted(error) {
333
- if (error instanceof HttpError) {
334
- return describeHttpErrorRedacted(error);
335
- }
336
- if (error instanceof Error) {
337
- return `${error.name}: ${error.message}`;
338
- }
339
- return `thrown non-error: ${stringifyUnredacted(error)}`;
340
- }
341
- function stringifyUnredacted(value) {
342
- if (value === void 0) return "";
343
- try {
344
- return JSON.stringify(
345
- value,
346
- (_key, item) => typeof item === "bigint" ? `${item}` : item
347
- ) ?? String(value);
348
- } catch (_) {
349
- return "<unserializable>";
350
- }
351
- }
352
- function describeHttpErrorRedacted(error) {
353
- const code = apiErrorCode(error);
354
- const status = error.response.status;
355
- return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
356
- }
357
- function errorName(error) {
358
- return error instanceof Error ? error.name : `non-error ${typeof error}`;
359
- }
360
- function httpCause(error) {
361
- return {
362
- type: "http",
363
- requestId: error.requestId,
364
- status: error.response.status,
365
- code: apiErrorCode(error),
366
- eventId: apiErrorEventId(error)
367
- };
368
- }
369
- function apiErrorEventId(error) {
370
- const body = error.response.body;
371
- if (typeof body !== "object" || body === null) return null;
372
- const eventId = body.event_id;
373
- return typeof eventId === "string" ? eventId : null;
374
- }
375
-
376
- // src/universal/core/shared/observability/internal-logger.ts
377
- function internalLogger(logger, scope) {
378
- return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
379
- }
380
- var LEVEL_RANK = {
381
- none: 0,
382
- error: 1,
383
- warn: 2,
384
- info: 3,
385
- debug: 4
386
- };
387
- function scopedLogger(logger, scope, bindings) {
388
- const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
389
- const safe = (event) => ({
390
- msg: event.msg,
391
- scope,
392
- bindings,
393
- fields: event.fields ?? {},
394
- ...event.cause === void 0 ? {} : { cause: event.cause }
395
- });
396
- const unredacted = (event) => ({
397
- msg: event.msg,
398
- scope,
399
- bindings,
400
- fields: event.fields ?? {}
401
- });
402
- const self = {
403
- child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
404
- debug: (event) => {
405
- if (admits("debug")) logger.debug(() => unredacted(event()));
406
- },
407
- info: (event) => {
408
- if (admits("info")) logger.info(() => safe(event()));
409
- },
410
- warn: (event) => {
411
- if (admits("warn")) logger.warn(() => safe(event()));
412
- },
413
- error: (event) => {
414
- if (admits("error")) logger.error(() => safe(event()));
415
- },
416
- failure: (event, error) => {
417
- if (admits("debug"))
418
- logger.debug(() => unredacted(verbatim(event(), error)));
419
- if (admits("error")) logger.error(() => safe(classified(event(), error)));
420
- },
421
- warning: (event, error) => {
422
- if (admits("debug"))
423
- logger.debug(() => unredacted(verbatim(event(), error)));
424
- if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
425
- },
426
- wrap: async (op, params, run) => {
427
- const opLog = self.child({ op });
428
- opLog.debug(() => ({ msg: "call", fields: { params } }));
429
- try {
430
- return await run();
431
- } catch (error) {
432
- opLog.failure(() => ({ msg: "call failed" }), error);
433
- throw error;
434
- }
435
- }
436
- };
437
- return self;
438
- }
439
- function verbatim(event, error) {
440
- return {
441
- msg: event.msg,
442
- fields: { ...event.fields, error: describeErrorUnredacted(error) }
443
- };
444
- }
445
- function classified(event, error) {
446
- return { ...event, cause: event.cause ?? classifyLogCause(error) };
447
- }
448
- var noopInternalLogger = {
449
- child: () => noopInternalLogger,
450
- debug: () => void 0,
451
- info: () => void 0,
452
- warn: () => void 0,
453
- error: () => void 0,
454
- failure: () => void 0,
455
- warning: () => void 0,
456
- wrap: (_op, _params, run) => run()
457
- };
458
-
459
- // src/universal/api/http-client.ts
460
- var HttpClient = class {
461
- constructor(config, middleware = {}, logger = null, options = {}) {
462
- this.config = config;
463
- this.middleware = middleware;
464
- this.log = internalLogger(logger, "HTTP");
465
- this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
466
- }
467
- async send(request) {
468
- return this.runRequestWithAfterMiddleware(request);
469
- }
470
- /**
471
- * Runs beforeRequest, executeRequest, then the full afterRequest middleware
472
- * chain. Used by send() and by the retry() callback so that when a
473
- * middleware calls retry(), the retried response also goes through all
474
- * afterRequest middleware (e.g. session renewal, retry). Middleware
475
- * must use request.attributes.retryAttempt (or similar) to avoid infinite
476
- * recursion when they trigger retries.
477
- */
478
- async runRequestWithAfterMiddleware(request) {
479
- const preparedRequest = await this.runBeforeRequestMiddleware(
480
- this.withClientDefaults(request)
481
- );
482
- let response = await this.executeRequest(preparedRequest);
483
- for (const middleware of this.middleware.afterRequest ?? []) {
484
- let retried = false;
485
- response = await middleware({
486
- request: preparedRequest,
487
- response,
488
- retry: (nextRequest = preparedRequest) => {
489
- retried = true;
490
- return this.runRequestWithAfterMiddleware(nextRequest);
491
- }
492
- });
493
- if (retried) {
494
- return response;
495
- }
496
- }
497
- return response;
498
- }
499
- withClientDefaults(request) {
500
- const url = this.resolveUrl(request.url);
501
- const headers = {
502
- ...request.headers ?? {},
503
- ...this.config.xApiVersion !== void 0 ? { [HEADER_API_VERSION]: this.config.xApiVersion } : {}
504
- };
505
- return {
506
- ...request,
507
- url,
508
- headers,
509
- // Only when absent: a retry or a post-renewal re-send arrives with the
510
- // first attempt's id already on it, and keeping it is the whole point.
511
- attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
512
- request.attributes ?? Attributes.empty,
513
- Attributes.requestId(this.makeRequestId())
514
- ) : request.attributes
515
- };
516
- }
517
- /**
518
- * Resolves a request URL against the client's baseUrl.
519
- *
520
- * @internal Public only for testing. Do not use in application code; use
521
- * {@link HttpClient.send} with a path and the client will resolve the URL.
522
- */
523
- resolveUrl(url) {
524
- if (url.startsWith("http://") || url.startsWith("https://")) {
525
- return url;
526
- }
527
- const base2 = this.config.baseUrl.replace(/\/$/, "");
528
- const path = url.startsWith("/") ? url : `/${url}`;
529
- return base2 + path;
530
- }
531
- async runBeforeRequestMiddleware(initialRequest) {
532
- let request = initialRequest;
533
- for (const middleware of this.middleware.beforeRequest ?? []) {
534
- request = await middleware(request);
535
- }
536
- return request;
537
- }
538
- /**
539
- * One physical attempt, logged as one line.
540
- *
541
- * A non-2xx is a `warn` rather than an `error` because the wire does not
542
- * know whether it is a failure: the retry middleware may turn a 503 into a
543
- * success, and the token registry reads a 404 as "not listed". The namespace
544
- * above decides, and logs the `error` when it does.
545
- */
546
- async executeRequest(request) {
547
- const requestId2 = Attributes.getRequestId(request.attributes);
548
- const log = requestId2 === null ? this.log : this.log.child({ requestId: requestId2 });
549
- const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
550
- const startedAt = Date.now();
551
- log.debug(() => ({
552
- msg: "request sent",
553
- fields: describeRequestUnredacted(request)
554
- }));
555
- try {
556
- const response = await makeRequest(request);
557
- const elapsed = Date.now() - startedAt;
558
- const outcome = () => ({
559
- msg: "request completed",
560
- fields: {
561
- ...identifyRequest(request),
562
- "http.response.status_code": response.status,
563
- duration_ms: elapsed,
564
- attempt
565
- }
566
- });
567
- if (response.status >= 200 && response.status < 300) {
568
- log.info(outcome);
569
- } else {
570
- log.warn(outcome);
571
- }
572
- log.debug(() => ({
573
- msg: "response received",
574
- fields: { body: response.body }
575
- }));
576
- return requestId2 === null ? response : { ...response, requestId: requestId2 };
577
- } catch (error) {
578
- const elapsed = Date.now() - startedAt;
579
- log.warning(
580
- () => ({
581
- msg: "request threw",
582
- fields: {
583
- ...identifyRequest(request),
584
- duration_ms: elapsed,
585
- attempt
586
- }
587
- }),
588
- error
589
- );
590
- throw error;
591
- }
592
- }
593
- };
594
- function identifyRequest(request) {
595
- const { host, path } = splitUrl(request.url);
596
- return {
597
- "http.request.method": request.method,
598
- "server.address": host,
599
- "url.path": path
600
- };
601
- }
602
- function splitUrl(url) {
603
- try {
604
- const parsed = new URL(url);
605
- return { host: parsed.host, path: parsed.pathname };
606
- } catch (_) {
607
- return { host: null, path: url };
608
- }
609
- }
610
- function defaultMakeRequestId() {
611
- return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
612
- }
613
- function describeRequestUnredacted(request) {
614
- return {
615
- "http.request.method": request.method,
616
- "url.full": buildUrlWithQueryParams(request.url, request.queryParams),
617
- headers: request.headers,
618
- ...request.method === "POST" ? { body: request.body } : {}
619
- };
620
- }
621
-
622
- // src/universal/api/middleware/attach-session-middleware.ts
623
- function attachSessionMiddleware(fetchAccessToken) {
624
- return async (request) => {
625
- if (!Attributes.isProtected(request.attributes)) {
626
- return request;
627
- }
628
- const userToken = await fetchAccessToken(TokenTrigger.beforeRequest);
629
- if (userToken !== null) {
630
- return withBearer(
631
- {
632
- ...request,
633
- attributes: Attributes.concat(
634
- request.attributes ?? Attributes.empty,
635
- Attributes.sentWith(userToken)
636
- )
637
- },
638
- userToken.value
639
- );
640
- }
641
- const clientCreds = Attributes.getClientCredentials(request.attributes);
642
- if (clientCreds) {
643
- return withBearer(request, clientCreds.value);
644
- }
645
- return request;
646
- };
647
- }
648
- function withBearer(request, token) {
649
- return {
650
- ...request,
651
- headers: {
652
- ...request.headers ?? {},
653
- Authorization: `Bearer ${token}`
654
- }
655
- };
656
- }
657
-
658
- // src/universal/core/shared/utils/crypto.ts
659
- function getUUIDv4() {
660
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
661
- return crypto.randomUUID();
662
- }
663
- if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
664
- const bytes = new Uint8Array(16);
665
- crypto.getRandomValues(bytes);
666
- bytes[6] = bytes[6] & 15 | 64;
667
- bytes[8] = bytes[8] & 63 | 128;
668
- const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
669
- return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
670
- }
671
- return `${Date.now()}-${Math.random().toString(36).slice(2, 12)}`;
672
- }
673
- function notBlankStringOrNull(value) {
674
- if (value?.trim()) {
675
- return value;
676
- } else {
677
- return null;
678
- }
679
- }
680
-
681
- // src/universal/api/middleware/idempotency-key.ts
682
- var idempotencyKeyMiddleware = async (request) => {
683
- if (!Attributes.isIdempotent(request.attributes)) {
684
- return request;
685
- }
686
- const existingHeaders = request.headers ?? {};
687
- if (existingHeaders[HEADER_IDEMPOTENCY_KEY]) {
688
- return request;
689
- }
690
- return {
691
- ...request,
692
- headers: {
693
- ...existingHeaders,
694
- [HEADER_IDEMPOTENCY_KEY]: getUUIDv4()
695
- }
696
- };
697
- };
698
-
699
- // src/universal/api/middleware/request-retry.ts
700
- var MAX_ATTEMPTS = 3;
701
- var INITIAL_DELAY_MS = 300;
702
- var MAX_DELAY_MS = 2e3;
703
- var RETRYABLE_4XX = /* @__PURE__ */ new Set([408, 409, 429]);
704
- function isRetryableStatus(status) {
705
- return status >= 500 && status < 600 || RETRYABLE_4XX.has(status);
706
- }
707
- function getRetryDelayMs(attempt) {
708
- return Math.min(INITIAL_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS);
709
- }
710
- function createRequestRetryMiddleware(options = {}) {
711
- const delayFn = options.delayFn ?? defaultDelay;
712
- return async ({ request, response, retry }) => {
713
- if (!isRetryableStatus(response.status) || !Attributes.isRetryable(request.attributes)) {
714
- return response;
715
- }
716
- const currentAttempt = Attributes.getRetryAttempt(request.attributes);
717
- if (currentAttempt >= MAX_ATTEMPTS - 1) {
718
- return response;
719
- }
720
- const nextAttempt = currentAttempt + 1;
721
- await delayFn(getRetryDelayMs(nextAttempt));
722
- const nextRequest = Request.concatAttributes(
723
- request,
724
- Attributes.retryAttempt(nextAttempt)
725
- );
726
- return retry(nextRequest);
727
- };
728
- }
729
- function defaultDelay(ms) {
730
- return new Promise((resolve) => setTimeout(resolve, ms));
731
- }
732
- var requestRetryMiddleware = createRequestRetryMiddleware();
733
-
734
- // src/universal/api/middleware/session-renewal.ts
735
- function renewSessionMiddleware(fetchAccessToken) {
736
- return async ({ request, response, retry }) => {
737
- if (response.status !== 401) {
738
- return response;
739
- }
740
- if (!Attributes.isProtected(request.attributes)) {
741
- return response;
742
- }
743
- if (Attributes.wasRenewAttempted(request.attributes)) {
744
- return response;
745
- }
746
- const newToken = await fetchAccessToken(
747
- TokenTrigger.after401(Attributes.getSentWith(request.attributes))
748
- );
749
- if (newToken) {
750
- const nextRequest = Request.concatAttributes(
751
- request,
752
- Attributes.renewAttempted(true)
753
- );
754
- return retry(nextRequest);
755
- } else {
756
- return response;
757
- }
758
- };
759
- }
760
-
761
- // src/universal/api/authenticated-api-client.ts
762
- var AuthenticatedApiClient = class {
763
- constructor(config, fetchAccessToken, additionalBeforeRequest = [], logger = null) {
764
- this.httpClient = new HttpClient(
765
- config,
766
- {
767
- beforeRequest: [
768
- attachSessionMiddleware(fetchAccessToken),
769
- ...additionalBeforeRequest,
770
- idempotencyKeyMiddleware
771
- ],
772
- afterRequest: [
773
- renewSessionMiddleware(fetchAccessToken),
774
- requestRetryMiddleware
775
- ]
776
- },
777
- logger
778
- );
779
- }
780
- async send(request) {
781
- const response = await this.httpClient.send(request);
782
- if (response.status >= 200 && response.status < 300) {
783
- return response.body;
784
- } else {
785
- throw new HttpError(response);
786
- }
787
- }
788
- };
789
-
790
- // src/server/core/api/api-client.ts
791
- var ApiClient = class {
792
- constructor(config, fetchAccessToken, logger = null) {
793
- this.client = new AuthenticatedApiClient(
794
- config,
795
- fetchAccessToken,
796
- [],
797
- logger
798
- );
799
- }
800
- async send(request) {
801
- return this.client.send(request);
802
- }
803
- };
804
-
805
- // src/universal/types/time.ts
806
- var MAX_EPOCH_MILLIS = 864e13;
807
- var EpochMillis = {
808
- /**
809
- * @throws {@link ValidationError} unless `value` is an integer a `Date` can
810
- * represent: at most {@link MAX_EPOCH_MILLIS} either side of the epoch.
811
- */
812
- of: (value) => {
813
- if (!Number.isInteger(value) || Math.abs(value) > MAX_EPOCH_MILLIS) {
814
- throw new ValidationError(
815
- `EpochMillis must be an integer within \xB1${MAX_EPOCH_MILLIS}, got ${value}`
816
- );
817
- }
818
- return value;
819
- },
820
- /** The wall clock. Code that needs the time takes a `TimeEff` instead. */
821
- now: () => EpochMillis.of(Date.now()),
822
- /** @throws {@link ValidationError} for an invalid `Date`. */
823
- fromDate: (date) => EpochMillis.of(date.getTime()),
824
- /** How long after `from` the instant `to` is; negative if it is before. */
825
- elapsed: (from, to) => Millis.of(to - from),
826
- plus: (at, duration) => EpochMillis.of(at + duration)
827
- };
828
- var Millis = {
829
- of: (value) => value
830
- };
831
- var Seconds = {
832
- /**
833
- * @throws {@link ValidationError} unless `value` is a non-negative integer.
834
- */
835
- of: (value) => {
836
- if (!Number.isInteger(value) || value < 0) {
837
- throw new ValidationError(
838
- `Seconds must be a non-negative integer, got ${value}`
839
- );
840
- }
841
- return value;
842
- },
843
- toMillis: (value) => Millis.of(value * 1e3)
844
- };
845
- function isExpired({
846
- expiresAt,
847
- now,
848
- buffer = Millis.of(0)
849
- }) {
850
- return now >= expiresAt - buffer;
851
- }
852
-
853
- // src/universal/core/shared/effects.ts
854
- var systemTime = { time: { now: EpochMillis.now } };
855
-
856
- // src/server/core/session-refresh.ts
857
- var VERDICT_MIN_GAP = Millis.of(5e3);
858
- var REJECTION_MEMORY = Millis.of(6e4);
859
- var RefreshKey = {
860
- of: ({
861
- clientId,
862
- session
863
- }) => {
864
- const identity = session.refreshToken === void 0 ? ["access", session.accessToken.value] : ["refresh", session.refreshToken];
865
- return JSON.stringify([clientId, ...identity]);
866
- }
867
- };
868
- var RefreshCoordinator = class {
869
- constructor(env = systemTime) {
870
- this.env = env;
871
- this.inFlight = /* @__PURE__ */ new Map();
872
- this.rejections = /* @__PURE__ */ new Map();
873
- }
874
- /**
875
- * Runs `exchange` for `key` unless one is already in flight, in which case
876
- * the caller joins it. `joined` tells the caller whether it led: only the
877
- * leader reports the outcome, so a burst of N produces one verdict, one log
878
- * line and one `onSessionExpired`.
879
- */
880
- refresh(key, exchange) {
881
- const existing = this.inFlight.get(key);
882
- if (existing !== void 0) {
883
- return { outcome: existing, joined: true };
884
- }
885
- const outcome = this.run(key, exchange).finally(() => {
886
- this.inFlight.delete(key);
887
- });
888
- this.inFlight.set(key, outcome);
889
- return { outcome, joined: false };
890
- }
891
- async run(key, exchange) {
892
- this.forgetStale(this.env.time.now());
893
- if (this.rejections.get(key)?.type === "expired") {
894
- return { type: "already-expired" };
895
- }
896
- const result = await exchange();
897
- switch (result.type) {
898
- case "renewed":
899
- case "unknown":
900
- return result;
901
- case "rejected":
902
- case "unrenewable": {
903
- const judged = judge({
904
- result: result.type,
905
- prior: this.rejections.get(key),
906
- now: this.env.time.now()
907
- });
908
- this.rejections.set(key, judged.memory);
909
- return { type: judged.outcome };
910
- }
911
- }
912
- }
913
- forgetStale(now) {
914
- for (const [key, rejection] of this.rejections) {
915
- if (EpochMillis.elapsed(rejectedAt(rejection), now) > REJECTION_MEMORY) {
916
- this.rejections.delete(key);
917
- }
918
- }
919
- }
920
- };
921
- function judge({
922
- result,
923
- prior,
924
- now
925
- }) {
926
- const verdict = {
927
- outcome: "expired",
928
- memory: { type: "expired", at: now }
929
- };
930
- switch (result) {
931
- case "unrenewable":
932
- return verdict;
933
- case "rejected":
934
- switch (prior?.type) {
935
- case void 0:
936
- return {
937
- outcome: "suspected",
938
- memory: { type: "suspected", since: now }
939
- };
940
- case "suspected":
941
- return EpochMillis.elapsed(prior.since, now) >= VERDICT_MIN_GAP ? verdict : { outcome: "suspected", memory: prior };
942
- case "expired":
943
- return { outcome: "expired", memory: prior };
944
- }
945
- }
946
- }
947
- function rejectedAt(rejection) {
948
- switch (rejection.type) {
949
- case "suspected":
950
- return rejection.since;
951
- case "expired":
952
- return rejection.at;
953
- }
954
- }
955
- var processRefreshCoordinator = new RefreshCoordinator();
956
-
957
- // src/server/shared/errors.ts
958
- var WritableSessionStoreRequiredError = class extends Error {
959
- constructor(message = "This operation requires a writable SessionStore. Provide a `setSession` implementation in your SessionStore to persist or clear OAuth sessions.") {
960
- super(message);
961
- this.name = "WritableSessionStoreRequiredError";
962
- }
963
- };
964
-
965
- // src/universal/core/auth/session-expired.ts
966
- function notifySessionExpired(onSessionExpired, log) {
967
- if (onSessionExpired === void 0) {
968
- return;
969
- }
970
- Promise.resolve().then(onSessionExpired).catch(
971
- (error) => log.failure(() => ({ msg: "onSessionExpired threw" }), error)
972
- );
973
- }
974
-
975
- // src/universal/types/oauth-session.ts
976
- var ClientCredentialsOAuth = (value) => value;
977
- var OAuthRefreshToken = (value) => value;
978
- var OAuthSession = {
979
- fromDto: (dto) => {
980
- const expiresAt = new Date(Date.now() + dto.expires_in * 1e3);
981
- return {
982
- accessToken: {
983
- value: dto.access_token,
984
- expiresAt
985
- },
986
- ...dto.refresh_token != null && dto.refresh_token !== "" ? { refreshToken: OAuthRefreshToken(dto.refresh_token) } : void 0
987
- };
988
- }
989
- };
990
-
991
- // src/server/core/server-auth-namespace-impl.ts
992
- var ServerAuthNamespaceImpl = class {
993
- constructor(api, config) {
994
- this.api = api;
995
- this.config = config;
996
- this.log = internalLogger(config.logger ?? null, "AUTH");
997
- }
998
- async completeOAuth(params) {
999
- return this.log.wrap("completeOAuth", void 0, async () => {
1000
- const setSession = this.writableSessionStore();
1001
- const sessionDto = await this.api.send({
1002
- method: "POST",
1003
- url: `/oauth/token`,
1004
- body: {
1005
- grant_type: "authorization_code",
1006
- code: params.code,
1007
- redirect_uri: this.config.redirectUri,
1008
- client_id: this.config.clientId,
1009
- client_secret: this.config.clientSecret,
1010
- code_verifier: params.codeVerifier
1011
- },
1012
- attributes: Attributes.notRetryable()
1013
- });
1014
- const session = OAuthSession.fromDto(sessionDto);
1015
- await setSession(session);
1016
- return session;
1017
- });
1018
- }
1019
- async getAccessToken() {
1020
- return this.tokenFor(TokenTrigger.beforeRequest);
1021
- }
1022
- /**
1023
- * {@link getAccessToken} with the reason the SDK is asking, which is what
1024
- * the authenticated HTTP pipeline calls: after a 401 the token's own expiry
1025
- * no longer matters, because the API has answered for it.
1026
- */
1027
- async tokenFor(trigger) {
1028
- return this.log.wrap(
1029
- "getAccessToken",
1030
- void 0,
1031
- () => this.readAccessToken(trigger)
1032
- );
1033
- }
1034
- async readAccessToken(trigger) {
1035
- const sessionStore = this.config.sessionStore;
1036
- const classification = classifyAccessToken({
1037
- session: await sessionStore.getSession(),
1038
- store: sessionStoreAccess(sessionStore),
1039
- trigger,
1040
- now: this.config.time.now(),
1041
- buffer: Seconds.toMillis(this.config.accessTokenExpiryBufferSeconds)
1042
- });
1043
- switch (classification.type) {
1044
- case "no-session":
1045
- case "refuse":
1046
- return null;
1047
- case "serve":
1048
- return classification.token;
1049
- case "serve-stale":
1050
- this.log.child({ op: "getAccessToken" }).warn(() => ({
1051
- msg: "serving an expired token: the session store is read-only, so it cannot be refreshed"
1052
- }));
1053
- return classification.token;
1054
- case "refresh":
1055
- return this.refresh(classification);
1056
- }
1057
- }
1058
- /**
1059
- * Refreshes through the process-wide coordinator, then acts on the outcome
1060
- * for this caller's own store. The store is written before anything is
1061
- * logged or the host is notified, so `onSessionExpired` always finds it
1062
- * cleared.
1063
- */
1064
- async refresh({
1065
- session,
1066
- setSession,
1067
- fallback
1068
- }) {
1069
- const log = this.log.child({ op: "refresh" });
1070
- const key = RefreshKey.of({ clientId: this.config.clientId, session });
1071
- const { outcome, joined } = this.config.refreshes.refresh(
1072
- key,
1073
- () => this.exchange(session.refreshToken)
1074
- );
1075
- if (joined) {
1076
- log.debug(() => ({ msg: "joined a refresh already in flight" }));
1077
- }
1078
- const result = await outcome;
1079
- switch (result.type) {
1080
- case "renewed":
1081
- await setSession(result.session);
1082
- if (!joined) {
1083
- log.info(() => ({ msg: "session renewed" }));
1084
- }
1085
- return result.session.accessToken;
1086
- case "suspected":
1087
- if (!joined) {
1088
- log.warn(() => ({
1089
- msg: "refresh rejected; not clearing until it is confirmed"
1090
- }));
1091
- }
1092
- return fallback;
1093
- case "expired":
1094
- await setSession(null);
1095
- if (!joined) {
1096
- log.info(() => ({
1097
- msg: "session expired",
1098
- fields: {
1099
- reason: session.refreshToken === void 0 ? "no-refresh-token" : "refresh-rejected"
1100
- }
1101
- }));
1102
- notifySessionExpired(this.config.onSessionExpired, log);
1103
- }
1104
- return null;
1105
- case "already-expired":
1106
- await setSession(null);
1107
- return null;
1108
- case "unknown":
1109
- if (fallback === null) {
1110
- throw result.error;
1111
- }
1112
- if (!joined) {
1113
- log.warning(
1114
- () => ({ msg: "refresh failed; serving the current token" }),
1115
- result.error
1116
- );
1117
- }
1118
- return fallback;
1119
- }
1120
- }
1121
- /**
1122
- * One `POST /oauth/token`, total: every failure comes back as a value, so
1123
- * the coordinator can judge it once for everyone who joined.
1124
- *
1125
- * Never retried. The refresh token is single-use, so a retry of an attempt
1126
- * that reached the server would present a token already rotated away, and
1127
- * its `invalid_grant` would be judged as a rejection of the session.
1128
- */
1129
- async exchange(refreshToken) {
1130
- if (refreshToken === void 0) {
1131
- return { type: "unrenewable" };
1132
- }
1133
- try {
1134
- const sessionDto = await this.api.send({
1135
- method: "POST",
1136
- url: `/oauth/token`,
1137
- body: {
1138
- grant_type: "refresh_token",
1139
- refresh_token: refreshToken,
1140
- client_id: this.config.clientId,
1141
- client_secret: this.config.clientSecret
1142
- },
1143
- attributes: Attributes.notRetryable()
1144
- });
1145
- return { type: "renewed", session: OAuthSession.fromDto(sessionDto) };
1146
- } catch (error) {
1147
- return isInvalidGrant(error) ? { type: "rejected" } : { type: "unknown", error };
1148
- }
1149
- }
1150
- async clientCredentials() {
1151
- return this.log.wrap("clientCredentials", void 0, async () => {
1152
- const sessionDto = await this.api.send({
1153
- method: "POST",
1154
- url: `/oauth/token`,
1155
- body: {
1156
- grant_type: "client_credentials",
1157
- client_id: this.config.clientId,
1158
- client_secret: this.config.clientSecret
1159
- }
1160
- });
1161
- const session = OAuthSession.fromDto(sessionDto);
1162
- return ClientCredentialsOAuth(session.accessToken);
1163
- });
1164
- }
1165
- async logout() {
1166
- return this.log.wrap("logout", void 0, () => this.revokeAndClear());
1167
- }
1168
- async revokeAndClear() {
1169
- const setSession = this.writableSessionStore();
1170
- const session = await this.config.sessionStore.getSession();
1171
- if (session == null) return;
1172
- try {
1173
- await this.api.send({
1174
- method: "POST",
1175
- url: `/oauth/revoke`,
1176
- body: {
1177
- token: session.accessToken.value,
1178
- client_id: this.config.clientId,
1179
- client_secret: this.config.clientSecret
1180
- }
1181
- });
1182
- } catch (err) {
1183
- if (this.config.strict) {
1184
- throw err;
1185
- }
1186
- this.log.child({ op: "logout" }).warning(
1187
- () => ({ msg: "revoke failed; local session cleared regardless" }),
1188
- err
1189
- );
1190
- }
1191
- await setSession(null);
1192
- }
1193
- /**
1194
- * Returns the store's `setSession`, or throws - the guard every
1195
- * session-writing operation shares.
1196
- */
1197
- writableSessionStore() {
1198
- const store = sessionStoreAccess(this.config.sessionStore);
1199
- switch (store.type) {
1200
- case "writable":
1201
- return store.setSession;
1202
- case "read-only":
1203
- throw new WritableSessionStoreRequiredError();
1204
- }
1205
- }
1206
- };
1207
- function classifyAccessToken({
1208
- session,
1209
- store,
1210
- trigger,
1211
- now,
1212
- buffer
1213
- }) {
1214
- if (session === null) {
1215
- return { type: "no-session" };
1216
- }
1217
- const token = session.accessToken;
1218
- const stale = isExpired({
1219
- expiresAt: EpochMillis.fromDate(token.expiresAt),
1220
- now,
1221
- buffer
1222
- });
1223
- switch (store.type) {
1224
- case "read-only":
1225
- return classifyReadOnly(token, trigger, stale);
1226
- case "writable": {
1227
- if (!needsRefresh(token, trigger, stale)) {
1228
- return { type: "serve", token };
1229
- }
1230
- const fallback = fallbackToken(token, trigger, now);
1231
- return session.refreshToken === void 0 && fallback !== null ? { type: "serve", token: fallback } : {
1232
- type: "refresh",
1233
- session,
1234
- setSession: store.setSession,
1235
- fallback
1236
- };
1237
- }
1238
- }
1239
- }
1240
- function classifyReadOnly(token, trigger, stale) {
1241
- switch (trigger.type) {
1242
- case "after-401":
1243
- return isRejectedToken(token, trigger.rejected) ? { type: "refuse" } : { type: "serve", token };
1244
- case "before-request":
1245
- return stale ? { type: "serve-stale", token } : { type: "serve", token };
1246
- }
1247
- }
1248
- function sessionStoreAccess(sessionStore) {
1249
- const setSession = sessionStore.setSession?.bind(sessionStore);
1250
- return setSession === void 0 ? { type: "read-only" } : { type: "writable", setSession };
1251
- }
1252
- function needsRefresh(token, trigger, stale) {
1253
- switch (trigger.type) {
1254
- case "before-request":
1255
- return stale;
1256
- case "after-401":
1257
- return trigger.rejected.type === "no-user-token" || isRejectedToken(token, trigger.rejected) || stale;
1258
- }
1259
- }
1260
- function fallbackToken(token, trigger, now) {
1261
- const unexpired = !isExpired({
1262
- expiresAt: EpochMillis.fromDate(token.expiresAt),
1263
- now
1264
- });
1265
- switch (trigger.type) {
1266
- case "after-401":
1267
- return unexpired && !isRejectedToken(token, trigger.rejected) ? token : null;
1268
- case "before-request":
1269
- return unexpired ? token : null;
1270
- }
1271
- }
1272
- function isInvalidGrant(error) {
1273
- if (!(error instanceof HttpError) || error.response.status !== 400) {
1274
- return false;
1275
- }
1276
- const body = error.response.body;
1277
- return typeof body === "object" && body !== null && "error" in body && body.error === "invalid_grant";
1278
- }
1279
-
1280
- // src/universal/api/pagination.ts
1281
- async function fetchAllPages(fetchPage, baseParams) {
1282
- const items = [];
1283
- let cursor = null;
1284
- do {
1285
- const params = {
1286
- ...baseParams ?? {},
1287
- after: cursor ?? void 0
1288
- };
1289
- const page = await fetchPage(params);
1290
- items.push(...page.data);
1291
- cursor = page.startingAfter;
1292
- } while (cursor);
1293
- return items;
1294
- }
1295
-
1296
- // src/universal/types/blockchain/core.ts
1297
- var ETHEREUM_CHAINS = {
1298
- ethereum_mainnet: true,
1299
- ethereum_sepolia: true,
1300
- base_mainnet: true,
1301
- base_sepolia: true
1302
- };
1303
- var EthereumChain = (value) => {
1304
- if (!Object.keys(ETHEREUM_CHAINS).includes(value)) {
1305
- throw new ValidationError(`Unsupported Ethereum chain: "${value}"`);
1306
- }
1307
- return value;
1308
- };
1309
- var SOLANA_CHAINS = {
1310
- solana_mainnet: true,
1311
- solana_devnet: true
1312
- };
1313
- var isChain = (value) => Object.keys(ETHEREUM_CHAINS).includes(value) || Object.keys(SOLANA_CHAINS).includes(value);
1314
- var Chain = (value) => {
1315
- if (!isChain(value)) {
1316
- throw new ValidationError(`Unsupported chain: "${value}"`);
1317
- }
1318
- return value;
1319
- };
1320
- var EvmWalletAddress = (value) => value;
1321
- var EvmContractAddress = (value) => value;
1322
- var HexEncodedTransactionData = (value) => value;
1323
- var MAX_ASSET_DECIMALS = 77;
1324
- var AssetDecimals = (value) => {
1325
- if (!Number.isInteger(value)) {
1326
- throw new ValidationError(`Asset decimals must be an integer: ${value}`);
1327
- }
1328
- if (value < 0 || value > MAX_ASSET_DECIMALS) {
1329
- throw new ValidationError(
1330
- `Asset decimals out of range [0, ${MAX_ASSET_DECIMALS}]: ${value}`
1331
- );
1332
- }
1333
- return value;
1334
- };
1335
- var STABLE_DECIMALS = AssetDecimals(6);
1336
- var DecimalString = (value) => value;
1337
- var MAX_UINT_256 = 2n ** 256n - 1n;
1338
- var assertUint256 = (value) => {
1339
- if (isUint256(value)) return value;
1340
- throw new InvariantError(`Value out of uint256 bounds: ${value}`);
1341
- };
1342
- var parseUint256 = (value, label) => {
1343
- if (isUint256(value)) return value;
1344
- throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
1345
- };
1346
- var isUint256 = (value) => value >= 0n && value <= MAX_UINT_256;
1347
- var BlockchainAmount = Object.assign(
1348
- (value) => value,
1349
- {
1350
- add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
1351
- sub: (a, b) => combineAmounts(a, b, (x, y) => x - y),
1352
- mul: multiplyAmounts,
1353
- div: divideAmounts
1354
- }
1355
- );
1356
- function multiplyAmounts(a, b) {
1357
- const product = a.raw * b.raw;
1358
- return BlockchainAmount({
1359
- raw: product / 10n ** BigInt(b.decimals),
1360
- decimals: a.decimals
1361
- });
1362
- }
1363
- function divideAmounts(a, b) {
1364
- if (b.raw === 0n) {
1365
- throw new MathError("Cannot divide a BlockchainAmount by zero");
1366
- }
1367
- const scaled = a.raw * 10n ** BigInt(b.decimals);
1368
- return BlockchainAmount({ raw: scaled / b.raw, decimals: a.decimals });
1369
- }
1370
- function combineAmounts(a, b, op) {
1371
- if (a.decimals !== b.decimals) {
1372
- throw new InvariantError(
1373
- `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
1374
- );
1375
- }
1376
- const raw = op(a.raw, b.raw);
1377
- if (raw < 0n || raw > MAX_UINT_256) {
1378
- throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
1379
- }
1380
- return BlockchainAmount({ raw, decimals: a.decimals });
1381
- }
1382
- var AssetSymbol = (value) => value;
1383
-
1384
- // src/universal/core/shared/utils/wire.ts
1385
- function unknownTypeError(dto, model) {
1386
- const type = dto.type;
1387
- throw new ValidationError(
1388
- `${model}.type: unknown type ${JSON.stringify(type)}`
1389
- );
1390
- }
1391
- function requiredString(value, field) {
1392
- const text = notBlankStringOrNull(value);
1393
- if (text === null) {
1394
- throw new ValidationError(
1395
- `${field}: expected a non-blank string, got ${typeof value === "string" ? "a blank string" : String(value)}`
1396
- );
1397
- }
1398
- return text;
1399
- }
1400
- function requiredDate(value, field) {
1401
- const date = typeof value === "string" ? new Date(value) : null;
1402
- if (date === null || Number.isNaN(date.getTime())) {
1403
- throw new ValidationError(
1404
- `${field}: expected a date, got ${JSON.stringify(value)}`
1405
- );
1406
- }
1407
- return date;
1408
- }
1409
- function dateOrNull(value, field) {
1410
- return value === null ? null : requiredDate(value, field);
1411
- }
1412
- function decimalOrNull(value) {
1413
- return value === null ? null : DecimalString(value);
1414
- }
1415
- function requiredArray(value, field) {
1416
- if (!Array.isArray(value)) {
1417
- throw new ValidationError(
1418
- `${field}: expected an array, got ${typeof value}`
1419
- );
1420
- }
1421
- return value;
1422
- }
1423
-
1424
- // src/universal/types/offer.ts
1425
- var OfferId = (value) => value;
1426
- var OfferSlug = (value) => value;
1427
- var OFFER_TYPES = {
1428
- "coinlist::token_sale": true,
1429
- "superstate::swap": true,
1430
- "ondo::swap": true,
1431
- "centrifuge::vault": true
1432
- };
1433
- var isOfferType = (value) => Object.keys(OFFER_TYPES).includes(value);
1434
- var OfferEditorial = {
1435
- /**
1436
- * `model` prefixes the field in the error (`'Offer'`, `'OfferDetail'`), so
1437
- * the same three checks name the payload that failed them.
1438
- */
1439
- fromDto: (dto, model) => ({
1440
- tagline: requiredString(dto.tagline, `${model}.tagline`),
1441
- bannerUrl: requiredString(dto.banner_url, `${model}.banner_url`),
1442
- startsAt: requiredDate(dto.starts_at, `${model}.starts_at`)
1443
- })
1444
- };
1445
- var Offer = {
1446
- fromDto: (dto) => {
1447
- const tokens = requiredArray(dto.tokens, "Offer.tokens");
1448
- const base2 = {
1449
- id: OfferId(dto.id),
1450
- slug: OfferSlug(dto.slug),
1451
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1452
- tokens: OfferToken.listFromDto(tokens)
1453
- };
1454
- switch (dto.type) {
1455
- case "coinlist::token_sale":
1456
- return {
1457
- ...base2,
1458
- ...OfferEditorial.fromDto(dto, "Offer"),
1459
- type: dto.type,
1460
- logoUrl: requiredString(dto.logo_url, "Offer.logo_url")
1461
- };
1462
- case "superstate::swap":
1463
- return {
1464
- ...base2,
1465
- ...OfferEditorial.fromDto(dto, "Offer"),
1466
- type: dto.type,
1467
- logoUrl: notBlankStringOrNull(dto.logo_url)
1468
- };
1469
- // `tagline`, `banner_url` and `starts_at` arrive as `null` and are left
1470
- // on the wire: copying them would hand every consumer a `startsAt` that
1471
- // is 1970 for one variant and a date for the others.
1472
- case "ondo::swap":
1473
- case "centrifuge::vault":
1474
- return {
1475
- ...base2,
1476
- type: dto.type,
1477
- logoUrl: notBlankStringOrNull(dto.logo_url)
1478
- };
1479
- default:
1480
- return unknownTypeError(dto, "Offer");
1481
- }
1482
- },
1483
- /**
1484
- * Maps a page of offers, dropping every offer whose `type` this SDK does not
1485
- * name. The same reasoning as {@link OfferToken.listFromDto}: a plain `.map`
1486
- * would throw out of `fromDto` and, through `PaginatedResponse.fromDto`,
1487
- * reject the whole page, so one offer of an unknown type would blank the
1488
- * grid for every offer beside it. A single offer fetched by id still
1489
- * throws, because there is nothing beside it to keep.
1490
- */
1491
- listFromDto: (dtos) => dtos.filter((dto) => isOfferType(dto.type)).map(Offer.fromDto)
1492
- };
1493
- var OfferToken = {
1494
- fromDto: (dto) => ({
1495
- role: dto.role,
1496
- chain: Chain(dto.chain),
1497
- address: EvmContractAddress(dto.address)
1498
- }),
1499
- /**
1500
- * Maps an offer's token list, dropping every token on a chain this SDK does
1501
- * not name. Frontline's chain registry runs ahead of {@link Chain}, and a
1502
- * plain `.map` would throw out of `Offer.fromDto` and, through
1503
- * `PaginatedResponse.fromDto`, reject the whole offers page - which is how
1504
- * one Base token blanked production's offers list. Dropping costs that
1505
- * token's metadata alone: `coinlist.tokens.get` takes an `EthereumChain`,
1506
- * so nobody could have looked it up anyway.
1507
- *
1508
- * Same shape as `TokenMetadata.fromRegistryDto`.
1509
- */
1510
- listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferToken.fromDto)
1511
- };
1512
-
1513
- // src/universal/types/asset.ts
1514
- var AssetId = (value) => value;
1515
- var AssetCode = (value) => value;
1516
- var Asset = {
1517
- fromDto: (dto) => ({
1518
- id: AssetId(dto.id),
1519
- code: AssetCode(dto.code),
1520
- name: dto.name,
1521
- fractionalDigits: dto.fractional_digits
1522
- })
1523
- };
1524
-
1525
- // src/universal/types/trading.ts
1526
- var Ticker = (value) => value;
1527
- var Isin = (value) => value;
1528
-
1529
- // src/universal/types/offer-detail.ts
1530
- var OfferOptionId = (value) => value;
1531
- var OfferOptionSlug = (value) => value;
1532
- var OfferSwapContract = {
1533
- fromDto: (dto) => ({
1534
- chain: Chain(dto.chain),
1535
- address: EvmContractAddress(dto.address)
1536
- })
1537
- };
1538
- var OfferVaultContract = {
1539
- fromDto: (dto) => ({
1540
- chain: Chain(dto.chain),
1541
- address: EvmContractAddress(dto.address)
1542
- }),
1543
- /**
1544
- * Drops every proxy on a chain this SDK does not name, as
1545
- * `OfferToken.listFromDto` does: frontline publishes the full offer-token
1546
- * chain list, which runs ahead of {@link Chain}, and one unmodelled chain
1547
- * should not throw away the proxies the SDK can use.
1548
- */
1549
- listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferVaultContract.fromDto)
1550
- };
1551
- var OfferDetail = {
1552
- fromDto: (dto) => {
1553
- const fundingAssets = requiredArray(
1554
- dto.funding_assets,
1555
- "OfferDetail.funding_assets"
1556
- );
1557
- const options = requiredArray(dto.options, "OfferDetail.options");
1558
- const terms = requiredArray(dto.terms, "OfferDetail.terms");
1559
- const links = requiredArray(dto.links, "OfferDetail.links");
1560
- const faqs = requiredArray(dto.faqs, "OfferDetail.faqs");
1561
- const milestones = requiredArray(dto.milestones, "OfferDetail.milestones");
1562
- const tokens = requiredArray(dto.tokens, "OfferDetail.tokens");
1563
- const isin = notBlankStringOrNull(dto.isin);
1564
- const ticker = notBlankStringOrNull(dto.ticker);
1565
- const base2 = {
1566
- id: OfferId(dto.id),
1567
- slug: OfferSlug(dto.slug),
1568
- name: dto.name,
1569
- asset: Asset.fromDto(dto.asset),
1570
- fundingAssets: fundingAssets.map(Asset.fromDto),
1571
- tokens: OfferToken.listFromDto(tokens),
1572
- about: notBlankStringOrNull(dto.about),
1573
- category: dto.category,
1574
- issuer: notBlankStringOrNull(dto.issuer),
1575
- isin: isin === null ? null : Isin(isin),
1576
- ticker: ticker === null ? null : Ticker(ticker),
1577
- instrumentType: notBlankStringOrNull(dto.instrument_type),
1578
- listingVenue: notBlankStringOrNull(dto.listing_venue),
1579
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1580
- faqs: faqs.map(FaqItem.fromDto),
1581
- links: links.map(Link.fromDto),
1582
- milestones: milestones.map(Milestone.fromDto),
1583
- options: options.map(OfferOption.fromDto),
1584
- terms: terms.map(TermItem.fromDto)
1585
- };
1586
- switch (dto.type) {
1587
- case "coinlist::token_sale":
1588
- return {
1589
- ...base2,
1590
- ...OfferEditorial.fromDto(dto, "OfferDetail"),
1591
- type: dto.type,
1592
- logoUrl: requiredString(dto.logo_url, "OfferDetail.logo_url")
1593
- };
1594
- case "superstate::swap":
1595
- return {
1596
- ...base2,
1597
- ...OfferEditorial.fromDto(dto, "OfferDetail"),
1598
- type: dto.type,
1599
- logoUrl: notBlankStringOrNull(dto.logo_url)
1600
- };
1601
- // `tagline`, `banner_url` and `starts_at` arrive as `null` and are left
1602
- // on the wire, as in `Offer.fromDto`.
1603
- case "ondo::swap":
1604
- return {
1605
- ...base2,
1606
- type: dto.type,
1607
- logoUrl: notBlankStringOrNull(dto.logo_url),
1608
- swapContracts: requiredArray(
1609
- dto.swap_contracts,
1610
- "OfferDetail.swap_contracts"
1611
- ).map(OfferSwapContract.fromDto)
1612
- };
1613
- // No editorial, as for Ondo. `[]` is fine and a missing key is not, for
1614
- // the same reason as `swap_contracts`: this is the spender a user
1615
- // approves.
1616
- case "centrifuge::vault":
1617
- return {
1618
- ...base2,
1619
- type: dto.type,
1620
- logoUrl: notBlankStringOrNull(dto.logo_url),
1621
- vaultContracts: OfferVaultContract.listFromDto(
1622
- requiredArray(dto.vault_contracts, "OfferDetail.vault_contracts")
1623
- )
1624
- };
1625
- default:
1626
- return unknownTypeError(dto, "OfferDetail");
1627
- }
1628
- }
1629
- };
1630
- var OfferOption = {
1631
- fromDto: (dto) => ({
1632
- id: OfferOptionId(dto.id),
1633
- slug: OfferOptionSlug(dto.slug),
1634
- bidIncrement: dto.bid_increment,
1635
- floorPriceUsd: dto.floor_price_usd,
1636
- minimumPurchaseUsd: dto.minimum_purchase_usd,
1637
- priceUsd: dto.price_usd,
1638
- saleAgreementUrl: notBlankStringOrNull(dto.sale_agreement_url),
1639
- totalTokenSupply: dto.total_token_supply
1640
- })
1641
- };
1642
- var FaqItem = {
1643
- fromDto: (dto) => ({
1644
- question: notBlankStringOrNull(dto.question),
1645
- answer: notBlankStringOrNull(dto.answer)
1646
- })
1647
- };
1648
- var Link = {
1649
- fromDto: (dto) => ({
1650
- label: notBlankStringOrNull(dto.label),
1651
- url: notBlankStringOrNull(dto.url)
1652
- })
1653
- };
1654
- var TermItem = {
1655
- fromDto: (dto) => ({
1656
- key: notBlankStringOrNull(dto.key),
1657
- value: notBlankStringOrNull(dto.value)
1658
- })
1659
- };
1660
- var Milestone = {
1661
- fromDto: (dto) => ({
1662
- name: notBlankStringOrNull(dto.name),
1663
- schedule: notBlankStringOrNull(dto.schedule),
1664
- status: dto.status
1665
- })
1666
- };
1667
-
1668
- // src/universal/types/pagination.ts
1669
- var Cursor = (value) => value;
1670
- var PaginatedResponse = {
1671
- fromDto: (dto, itemMapper) => PaginatedResponse.fromDtoPage(dto, (items) => items.map(itemMapper)),
1672
- /**
1673
- * For a mapper that decides the page as a whole - one that drops items it
1674
- * cannot map, such as `Offer.listFromDto` - rather than item by item. The
1675
- * cursors are the wire's either way: dropping an item changes what the
1676
- * page holds, not where the next page starts.
1677
- */
1678
- fromDtoPage: (dto, pageMapper) => ({
1679
- data: pageMapper(dto.data),
1680
- startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
1681
- startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
1682
- })
1683
- };
1684
- var PaginationParams = {
1685
- toQueryParams: (params) => {
1686
- const queryParams = {};
1687
- if (params.after) {
1688
- queryParams.starting_after = params.after;
1689
- }
1690
- if (params.before) {
1691
- queryParams.starting_before = params.before;
1692
- }
1693
- if (params.limit) {
1694
- queryParams.limit = params.limit;
1695
- }
1696
- return queryParams;
1697
- }
1698
- };
1699
-
1700
- // src/universal/api/frontline/offers.ts
1701
- async function fetchOffers(api, clientCreds) {
1702
- return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));
1703
- }
1704
- async function fetchOffersPage(api, params, clientCreds) {
1705
- const queryParams = PaginationParams.toQueryParams(params);
1706
- const pageDto = await api.send({
1707
- method: "GET",
1708
- url: "/v1/offers",
1709
- queryParams,
1710
- attributes: Attributes.concat(
1711
- Attributes.protected(),
1712
- Attributes.clientCredentials(clientCreds)
1713
- )
1714
- });
1715
- return PaginatedResponse.fromDtoPage(pageDto, Offer.listFromDto);
1716
- }
1717
- async function fetchOfferDetails(api, id, clientCreds) {
1718
- const dto = await api.send({
1719
- method: "GET",
1720
- url: `/v1/offers/${id}`,
1721
- attributes: Attributes.concat(
1722
- Attributes.protected(),
1723
- Attributes.clientCredentials(clientCreds)
1724
- )
1725
- });
1726
- return OfferDetail.fromDto(dto);
1727
- }
1728
-
1729
- // src/server/core/server-offers-namespace.ts
1730
- var ServerOffersNamespaceImpl = class {
1731
- constructor(ctx) {
1732
- this.ctx = ctx;
1733
- this.log = internalLogger(ctx.logger, "OFFERS");
1734
- }
1735
- async list(clientCreds) {
1736
- return this.log.wrap("list", clientCreds, async () => {
1737
- await this.ctx.ensureAuthenticated(clientCreds);
1738
- return fetchOffers(this.ctx.api, clientCreds);
1739
- });
1740
- }
1741
- async listPage(params, clientCreds) {
1742
- return this.log.wrap("listPage", { params, clientCreds }, async () => {
1743
- await this.ctx.ensureAuthenticated(clientCreds);
1744
- return fetchOffersPage(this.ctx.api, params, clientCreds);
1745
- });
1746
- }
1747
- async get(id, clientCreds) {
1748
- return this.log.wrap("get", { id, clientCreds }, async () => {
1749
- await this.ctx.ensureAuthenticated(clientCreds);
1750
- return fetchOfferDetails(this.ctx.api, id, clientCreds);
1751
- });
1752
- }
1753
- };
1754
-
1755
- // src/universal/types/requirement.ts
1756
- var RequirementId = (value) => value;
1757
- var Requirement = {
1758
- fromDto: (dto) => ({
1759
- id: RequirementId(dto.id),
1760
- type: dto.type,
1761
- details: dto.details
1762
- })
1763
- };
1764
- var RequirementStatusInfo = {
1765
- fromStatusesDto: (dto) => Object.entries(dto.statuses).map(
1766
- ([id, value]) => typeof value === "string" ? { id: RequirementId(id), status: value, action: null } : {
1767
- id: RequirementId(id),
1768
- status: value.status,
1769
- action: value.action ?? null,
1770
- kycLevel: value.kyc_level,
1771
- kycReset: value.kyc_reset
1772
- }
1773
- )
1774
- };
1775
-
1776
- // src/universal/api/frontline/requirements.ts
1777
- async function fetchOfferRequirements(api, offerId, clientCreds) {
1778
- const response = await api.send({
1779
- method: "GET",
1780
- url: `/v1/offers/${offerId}/requirements`,
1781
- attributes: Attributes.concat(
1782
- Attributes.protected(),
1783
- Attributes.clientCredentials(clientCreds)
1784
- )
1785
- });
1786
- return Object.fromEntries(
1787
- Object.entries(response.options).map(([optionId, list]) => [
1788
- optionId,
1789
- list.data.map(Requirement.fromDto)
1790
- ])
1791
- );
1792
- }
1793
- async function fetchRequirementStatuses(api, offerId) {
1794
- const response = await api.send({
1795
- method: "GET",
1796
- url: `/v1/offers/${offerId}/requirements/statuses`,
1797
- attributes: Attributes.protected()
1798
- });
1799
- return RequirementStatusInfo.fromStatusesDto(response);
1800
- }
1801
-
1802
- // src/universal/types/document-submission.ts
1803
- var DocumentSubmission = {
1804
- fromDto: (dto) => ({
1805
- status: dto.status,
1806
- formType: dto.form_type
1807
- })
1808
- };
1809
-
1810
- // src/universal/api/frontline/documents.ts
1811
- async function submitDocument(api, documentType, fields) {
1812
- const dto = await api.send({
1813
- method: "POST",
1814
- url: `/v1/documents/${documentType}/submission`,
1815
- body: fields,
1816
- attributes: Attributes.protected()
1817
- });
1818
- return DocumentSubmission.fromDto(dto);
1819
- }
1820
-
1821
- // src/universal/types/kyc.ts
1822
- var KycToken = {
1823
- fromDto: (dto) => ({
1824
- token: dto.token
1825
- })
1826
- };
1827
-
1828
- // src/universal/api/frontline/kyc.ts
1829
- async function createKycToken(api, levelName, reset) {
1830
- const dto = await api.send({
1831
- method: "POST",
1832
- url: "/v1/kyc-token",
1833
- body: {
1834
- ...levelName === void 0 ? {} : { level_name: levelName },
1835
- ...reset === void 0 ? {} : { reset }
1836
- },
1837
- attributes: Attributes.protected()
1838
- });
1839
- return KycToken.fromDto(dto);
1840
- }
1841
-
1842
- // src/universal/types/pii.ts
1843
- var Iso2CountryCode = (value) => value;
1844
- var PiiJurisdiction = {
1845
- fromDto: (dto) => ({
1846
- iso2: Iso2CountryCode(dto.iso_2),
1847
- name: dto.name
1848
- })
1849
- };
1850
- var PiiAddress = {
1851
- fromDto: (dto) => ({
1852
- street: dto.street,
1853
- city: dto.city,
1854
- state: dto.state,
1855
- postalCode: dto.postal_code,
1856
- country: dto.country
1857
- })
1858
- };
1859
- var Pii = {
1860
- fromDto: (dto) => ({
1861
- kind: dto.kind,
1862
- fullLegalName: dto.full_legal_name,
1863
- dateOfBirth: dto.date_of_birth,
1864
- jurisdiction: dto.jurisdiction ? PiiJurisdiction.fromDto(dto.jurisdiction) : null,
1865
- taxId: dto.tax_id,
1866
- permanentAddress: PiiAddress.fromDto(dto.permanent_address)
1867
- })
1868
- };
1869
-
1870
- // src/universal/api/frontline/pii.ts
1871
- async function fetchPii(api) {
1872
- const dto = await api.send({
1873
- method: "GET",
1874
- url: "/v1/pii",
1875
- attributes: Attributes.protected()
1876
- });
1877
- return Pii.fromDto(dto);
1878
- }
1879
-
1880
- // src/universal/core/requirements/requirements-namespace.ts
1881
- var RequirementsNamespaceImpl = class {
1882
- constructor(ctx) {
1883
- this.ctx = ctx;
1884
- this.log = internalLogger(ctx.logger, "REQUIREMENTS");
1885
- }
1886
- async forOffer(offerId) {
1887
- return this.log.wrap("forOffer", offerId, async () => {
1888
- await this.ctx.ensureUserAuthenticated();
1889
- return fetchOfferRequirements(
1890
- this.ctx.api,
1891
- offerId,
1892
- void 0
1893
- );
1894
- });
1895
- }
1896
- async statuses(offerId) {
1897
- return this.log.wrap("statuses", offerId, async () => {
1898
- await this.ctx.ensureUserAuthenticated();
1899
- return fetchRequirementStatuses(this.ctx.api, offerId);
1900
- });
1901
- }
1902
- async createKycToken(params) {
1903
- return this.log.wrap("createKycToken", params, async () => {
1904
- await this.ctx.ensureUserAuthenticated();
1905
- return createKycToken(
1906
- this.ctx.api,
1907
- params?.levelName,
1908
- params?.reset
1909
- );
1910
- });
1911
- }
1912
- async getPii() {
1913
- return this.log.wrap("getPii", void 0, async () => {
1914
- await this.ctx.ensureUserAuthenticated();
1915
- return fetchPii(this.ctx.api);
1916
- });
1917
- }
1918
- async submitDocument(params) {
1919
- return this.log.wrap("submitDocument", params, async () => {
1920
- await this.ctx.ensureUserAuthenticated();
1921
- return submitDocument(
1922
- this.ctx.api,
1923
- params.documentType,
1924
- params.fields
1925
- );
1926
- });
1927
- }
1928
- };
1929
-
1930
- // src/server/core/server-requirements-namespace.ts
1931
- var ServerRequirementsNamespaceImpl = class extends RequirementsNamespaceImpl {
1932
- constructor(serverCtx) {
1933
- super(serverCtx);
1934
- this.serverCtx = serverCtx;
1935
- }
1936
- async forOffer(offerId, clientCreds) {
1937
- return this.log.wrap("forOffer", { offerId, clientCreds }, async () => {
1938
- await this.serverCtx.ensureAuthenticated(clientCreds);
1939
- return fetchOfferRequirements(
1940
- this.serverCtx.api,
1941
- offerId,
1942
- clientCreds
1943
- );
1944
- });
1945
- }
1946
- };
1947
-
1948
- // src/universal/api/nabu/config.ts
1949
- var NABU_BASE_URL = "https://asset.coinlist.co";
1950
-
1951
- // src/universal/api/rpc/public-clients.ts
1952
- var import_viem3 = require("viem");
1953
-
1954
- // src/universal/api/rpc/frontline-transport.ts
1955
- var import_viem2 = require("viem");
1956
- function frontlineTransport(api, chain, logger = null) {
1957
- const log = internalLogger(logger, "RPC");
1958
- let nextId = 0;
1959
- return (0, import_viem2.custom)(
1960
- {
1961
- async request({ method, params }) {
1962
- const id = ++nextId;
1963
- return sendRpc({ api, log, chain, id, method, params });
1964
- }
1965
- },
1966
- // The `Sender` below already retries: `requestRetryMiddleware` makes three
1967
- // attempts at a 5xx and `renewSessionMiddleware` re-sends once after a 401.
1968
- // viem's own default is `retryCount: 3`, and it applies on top: an
1969
- // `HttpError` carries no numeric `code`, so `buildRequest` wraps it in
1970
- // `UnknownRpcError` (`code === -1`) and `shouldRetry` says yes. That reruns
1971
- // the whole pipeline four times - twelve requests for one `eth_call`, and
1972
- // with multicall batching one `eth_call` is a screen's worth of reads. The
1973
- // SDK's retry policy is the one that applies, so viem's is turned off.
1974
- { retryCount: 0 }
1975
- );
1976
- }
1977
- async function sendRpc({
1978
- api,
1979
- log,
1980
- chain,
1981
- id,
1982
- method,
1983
- params
1984
- }) {
1985
- const url = rpcPath(chain);
1986
- const startedAt = Date.now();
1987
- log.debug(() => ({
1988
- msg: "rpc call sent",
1989
- fields: { id, method, chain, params }
1990
- }));
1991
- const response = await sendEnvelope(api, url, {
1992
- jsonrpc: "2.0",
1993
- id,
1994
- method,
1995
- params
1996
- });
1997
- const elapsed = Date.now() - startedAt;
1998
- if (response.error) {
1999
- const error = new import_viem2.RpcRequestError({
2000
- body: { method, params },
2001
- error: response.error,
2002
- url
2003
- });
2004
- log.warning(
2005
- () => ({
2006
- msg: "rpc call rejected",
2007
- cause: { type: "rpc", reason: "node-rejected" },
2008
- fields: {
2009
- method,
2010
- chain,
2011
- duration_ms: elapsed,
2012
- "rpc.error_code": response.error?.code ?? null
2013
- }
2014
- }),
2015
- error
2016
- );
2017
- throw error;
2018
- }
2019
- log.info(() => ({
2020
- msg: "rpc call",
2021
- fields: { method, chain, duration_ms: elapsed }
2022
- }));
2023
- return response.result;
2024
- }
2025
- function rpcPath(chain) {
2026
- return `/v1/chains/${encodeURIComponent(chain)}/rpc`;
2027
- }
2028
- async function sendEnvelope(api, url, body) {
2029
- try {
2030
- return await api.send({
2031
- method: "POST",
2032
- url,
2033
- body,
2034
- attributes: Attributes.protected()
2035
- });
2036
- } catch (error) {
2037
- if (error instanceof HttpError && isJsonRpcError(error.response.body)) {
2038
- return error.response.body;
2039
- }
2040
- throw error;
2041
- }
2042
- }
2043
- function isJsonRpcError(body) {
2044
- if (typeof body !== "object" || body === null || !("error" in body)) {
2045
- return false;
2046
- }
2047
- const { error } = body;
2048
- return typeof error === "object" && error !== null && "code" in error && typeof error.code === "number";
2049
- }
2050
-
2051
- // src/universal/core/shared/blockchain/chain.ts
2052
- var import_chains = require("viem/chains");
2053
-
2054
- // src/universal/types/blockchain/ui.ts
2055
- var FormattedAmountAssetUi = (value) => value;
2056
-
2057
- // src/universal/core/shared/blockchain/chain.ts
2058
- var VIEM_CHAINS = {
2059
- ethereum_mainnet: import_chains.mainnet,
2060
- ethereum_sepolia: import_chains.sepolia,
2061
- base_mainnet: import_chains.base,
2062
- base_sepolia: import_chains.baseSepolia
2063
- };
2064
- function viemChain(chain) {
2065
- return VIEM_CHAINS[chain];
2066
- }
2067
- function chainFromId(chainId) {
2068
- const chains = Object.keys(VIEM_CHAINS);
2069
- const chain = chains.find((c) => String(VIEM_CHAINS[c].id) === chainId);
2070
- if (!chain) {
2071
- throw new ValidationError(`Unsupported EIP-155 chain id: "${chainId}"`);
2072
- }
2073
- return chain;
2074
- }
2075
-
2076
- // src/universal/api/rpc/public-clients.ts
2077
- function publicClients(api, config, logger = null) {
2078
- const cache = /* @__PURE__ */ new Map();
2079
- return (chain) => {
2080
- const cached = cache.get(chain);
2081
- if (cached) return cached;
2082
- const client = (0, import_viem3.createPublicClient)({
2083
- chain: viemChain(chain),
2084
- transport: transportFor(api, config?.[chain], chain, logger),
2085
- batch: { multicall: true }
2086
- });
2087
- cache.set(chain, client);
2088
- return client;
2089
- };
2090
- }
2091
- function transportFor(api, override, chain, logger) {
2092
- if (override === void 0) return frontlineTransport(api, chain, logger);
2093
- return typeof override === "string" ? (0, import_viem3.http)(override) : override;
2094
- }
2095
-
2096
- // src/universal/core/shared/blockchain/math.ts
2097
- var import_viem4 = require("viem");
2098
- function blockchainAmountFromRawOrThrow({
2099
- label,
2100
- raw,
2101
- decimals
2102
- }) {
2103
- const trimmed = raw.trim();
2104
- if (trimmed === "") {
2105
- throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
2106
- }
2107
- let value;
2108
- try {
2109
- value = BigInt(trimmed);
2110
- } catch {
2111
- throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
2112
- }
2113
- try {
2114
- return BlockchainAmount({ raw: assertUint256(value), decimals });
2115
- } catch {
2116
- throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
2117
- }
2118
- }
2119
-
2120
- // src/universal/types/providers/centrifuge/centrifuge.ts
2121
- var CentrifugeVaultStatus = {
2122
- fromDto: (dto) => ({
2123
- chain: EthereumChain(dto.chain),
2124
- symbol: AssetSymbol(dto.symbol),
2125
- vaultAddress: EvmContractAddress(dto.vault_address),
2126
- linked: dto.linked,
2127
- permissioned: dto.permissioned,
2128
- membershipValidUntil: dateOrNull(
2129
- dto.membership_valid_until,
2130
- "CentrifugeVaultStatus.membership_valid_until"
2131
- ),
2132
- halted: dto.halted,
2133
- priceUpdatedAt: dateOrNull(
2134
- dto.price_updated_at,
2135
- "CentrifugeVaultStatus.price_updated_at"
2136
- ),
2137
- orderability: parseOrderability(
2138
- dto.can_order,
2139
- dto.reasons,
2140
- "CentrifugeVaultStatus"
2141
- ),
2142
- asOf: requiredDate(dto.as_of, "CentrifugeVaultStatus.as_of")
2143
- })
2144
- };
2145
- var CentrifugeVaultBuyTransaction = {
2146
- fromDto: (dto) => {
2147
- const spendInputAmount = blockchainAmountFromRawOrThrow({
2148
- label: "spend_input_amount",
2149
- raw: dto.spend_input_amount,
2150
- decimals: AssetDecimals(dto.spend_input_decimals)
2151
- });
2152
- if (spendInputAmount.raw <= 0n) {
2153
- throw new ValidationError(
2154
- `spend_input_amount: must be greater than zero ("${dto.spend_input_amount}") - a deposit of nothing is not a request`
2155
- );
2156
- }
2157
- return {
2158
- ...parseTransactionCore(dto, "CentrifugeVaultBuyTransaction"),
2159
- spendInputAmount
2160
- };
2161
- }
2162
- };
2163
- var CentrifugeVaultClaimTransaction = {
2164
- fromDto: (dto) => ({
2165
- ...parseTransactionCore(dto, "CentrifugeVaultClaimTransaction"),
2166
- claimableShares: blockchainAmountFromRawOrThrow({
2167
- label: "claimable_shares",
2168
- raw: dto.claimable_shares,
2169
- decimals: AssetDecimals(dto.share_decimals)
2170
- })
2171
- })
2172
- };
2173
- var CentrifugeVaultPosition = {
2174
- fromDto: (dto) => {
2175
- const assetDecimals = AssetDecimals(dto.asset_decimals);
2176
- const shareDecimals = AssetDecimals(dto.share_decimals);
2177
- const asset = (label, raw) => blockchainAmountFromRawOrThrow({ label, raw, decimals: assetDecimals });
2178
- const shares = (label, raw) => blockchainAmountFromRawOrThrow({ label, raw, decimals: shareDecimals });
2179
- return {
2180
- chain: EthereumChain(dto.chain),
2181
- symbol: AssetSymbol(dto.symbol),
2182
- walletAddress: EvmWalletAddress(dto.wallet_address),
2183
- status: dto.status,
2184
- requested: asset("requested", dto.requested),
2185
- pending: asset("pending", dto.pending),
2186
- filledAssets: asset("filled_assets", dto.filled_assets),
2187
- earnedShares: shares("earned_shares", dto.earned_shares),
2188
- claimedShares: shares("claimed_shares", dto.claimed_shares),
2189
- claimableShares: shares("claimable_shares", dto.claimable_shares),
2190
- shareBalance: shares("share_balance", dto.share_balance),
2191
- averagePrice: decimalOrNull(dto.average_price),
2192
- frozen: dto.frozen,
2193
- asOf: requiredDate(dto.as_of, "CentrifugeVaultPosition.as_of")
2194
- };
2195
- }
2196
- };
2197
- var CentrifugeVaultRedeemPosition = {
2198
- fromDto: (dto) => ({
2199
- chain: EthereumChain(dto.chain),
2200
- symbol: AssetSymbol(dto.symbol),
2201
- walletAddress: EvmWalletAddress(dto.wallet_address),
2202
- status: dto.status,
2203
- pending: blockchainAmountFromRawOrThrow({
2204
- label: "pending",
2205
- raw: dto.pending,
2206
- decimals: AssetDecimals(dto.share_decimals)
2207
- }),
2208
- claimableAssets: blockchainAmountFromRawOrThrow({
2209
- label: "claimable_assets",
2210
- raw: dto.claimable_assets,
2211
- decimals: AssetDecimals(dto.asset_decimals)
2212
- }),
2213
- frozen: dto.frozen,
2214
- asOf: requiredDate(dto.as_of, "CentrifugeVaultRedeemPosition.as_of")
2215
- })
2216
- };
2217
- var CentrifugeVaultClaimProceedsTransaction = {
2218
- fromDto: (dto) => ({
2219
- ...parseTransactionCore(dto, "CentrifugeVaultClaimProceedsTransaction"),
2220
- claimableAssets: blockchainAmountFromRawOrThrow({
2221
- label: "claimable_assets",
2222
- raw: dto.claimable_assets,
2223
- decimals: AssetDecimals(dto.asset_decimals)
2224
- })
2225
- })
2226
- };
2227
- function parseOrderability(canOrder, reasons, model) {
2228
- const [first, ...rest] = reasons;
2229
- if (canOrder) {
2230
- if (first !== void 0) {
2231
- throw new ValidationError(
2232
- `${model}.reasons: expected none when can_order is true, got ${JSON.stringify(reasons)}`
2233
- );
2234
- }
2235
- return { type: "orderable" };
2236
- }
2237
- if (first === void 0) {
2238
- throw new ValidationError(
2239
- `${model}.reasons: expected at least one when can_order is false`
2240
- );
2241
- }
2242
- return { type: "blocked", reasons: [first, ...rest] };
2243
- }
2244
- function parseTransactionCore(dto, model) {
2245
- return {
2246
- tx: {
2247
- to: EvmContractAddress(dto.to),
2248
- data: HexEncodedTransactionData(dto.data)
2249
- },
2250
- expiresAt: dateOrNull(dto.expires_at, `${model}.expires_at`)
2251
- };
2252
- }
2253
-
2254
- // src/universal/api/frontline/providers/centrifuge/centrifuge.ts
2255
- async function getCentrifugeVaultStatus(api, params) {
2256
- const dto = await api.send({
2257
- method: "GET",
2258
- url: "/v1/centrifuge/vault/status",
2259
- queryParams: {
2260
- symbol: params.symbol,
2261
- chain: params.chain
2262
- },
2263
- attributes: Attributes.protected()
2264
- });
2265
- return CentrifugeVaultStatus.fromDto(dto);
2266
- }
2267
- async function buildCentrifugeVaultBuy(api, params) {
2268
- const dto = await api.send({
2269
- method: "POST",
2270
- url: "/v1/centrifuge/vault/invest",
2271
- body: {
2272
- ...walletFields(params),
2273
- amount: params.amount.raw.toString()
2274
- },
2275
- attributes: Attributes.protected()
2276
- });
2277
- if (dto.spend_input_decimals !== params.amount.decimals) {
2278
- throw new ValidationError(
2279
- `spend_input_decimals: the request was priced in ${dto.spend_input_decimals} decimals but the deposit was sized in ${params.amount.decimals}`
2280
- );
2281
- }
2282
- return CentrifugeVaultBuyTransaction.fromDto(dto);
2283
- }
2284
- async function getCentrifugeVaultPosition(api, params) {
2285
- const dto = await api.send({
2286
- method: "GET",
2287
- url: "/v1/centrifuge/vault/position",
2288
- queryParams: walletFields(params),
2289
- attributes: Attributes.protected()
2290
- });
2291
- return CentrifugeVaultPosition.fromDto(dto);
2292
- }
2293
- async function getCentrifugeVaultRedeemPosition(api, params) {
2294
- const dto = await api.send({
2295
- method: "GET",
2296
- url: "/v1/centrifuge/vault/redeem-position",
2297
- queryParams: walletFields(params),
2298
- attributes: Attributes.protected()
2299
- });
2300
- return CentrifugeVaultRedeemPosition.fromDto(dto);
2301
- }
2302
- async function createCentrifugeVaultClaim(api, params) {
2303
- const dto = await api.send({
2304
- method: "POST",
2305
- url: "/v1/centrifuge/vault/claim",
2306
- body: walletFields(params),
2307
- attributes: Attributes.protected()
2308
- });
2309
- return CentrifugeVaultClaimTransaction.fromDto(dto);
2310
- }
2311
- async function createCentrifugeVaultClaimProceeds(api, params) {
2312
- const dto = await api.send({
2313
- method: "POST",
2314
- url: "/v1/centrifuge/vault/claim-proceeds",
2315
- body: walletFields(params),
2316
- attributes: Attributes.protected()
2317
- });
2318
- return CentrifugeVaultClaimProceedsTransaction.fromDto(dto);
2319
- }
2320
- function walletFields(params) {
2321
- return {
2322
- symbol: params.symbol,
2323
- chain: params.chain,
2324
- wallet_address: params.walletAddress
2325
- };
2326
- }
2327
-
2328
- // src/universal/core/checkout/centrifuge/centrifuge-namespace.ts
2329
- var CentrifugeNamespaceImpl = class {
2330
- constructor(ctx) {
2331
- this.ctx = ctx;
2332
- this.log = internalLogger(ctx.logger, "CENTRIFUGE");
2333
- }
2334
- async getVaultStatus(params) {
2335
- return this.log.wrap("getVaultStatus", params, async () => {
2336
- await this.ctx.ensureUserAuthenticated();
2337
- return getCentrifugeVaultStatus(this.ctx.api, params);
2338
- });
2339
- }
2340
- async getPosition(params) {
2341
- return this.log.wrap("getPosition", params, async () => {
2342
- await this.ctx.ensureUserAuthenticated();
2343
- return getCentrifugeVaultPosition(this.ctx.api, params);
2344
- });
2345
- }
2346
- async getRedeemPosition(params) {
2347
- return this.log.wrap("getRedeemPosition", params, async () => {
2348
- await this.ctx.ensureUserAuthenticated();
2349
- return getCentrifugeVaultRedeemPosition(this.ctx.api, params);
2350
- });
2351
- }
2352
- async createClaim(params) {
2353
- return this.log.wrap("createClaim", params, async () => {
2354
- await this.ctx.ensureUserAuthenticated();
2355
- return createCentrifugeVaultClaim(this.ctx.api, params);
2356
- });
2357
- }
2358
- async createClaimProceeds(params) {
2359
- return this.log.wrap("createClaimProceeds", params, async () => {
2360
- await this.ctx.ensureUserAuthenticated();
2361
- return createCentrifugeVaultClaimProceeds(this.ctx.api, params);
2362
- });
2363
- }
2364
- async buildBuyTransaction(params) {
2365
- return this.log.wrap("buildBuyTransaction", params, async () => {
2366
- await this.ctx.ensureUserAuthenticated();
2367
- return buildCentrifugeVaultBuy(this.ctx.api, params);
2368
- });
2369
- }
2370
- };
2371
-
2372
- // src/universal/types/providers/coin-list/token-sale.ts
2373
- var ParticipationId = (value) => value;
2374
- var Blockchain = (value) => value;
2375
- var WalletAddress = (value) => value;
2376
- var ParticipationsPaginationParams = {
2377
- toQueryParams: (params) => {
2378
- const queryParams = PaginationParams.toQueryParams(params);
2379
- if (params.offerId) {
2380
- queryParams["filters[0][field]"] = "offer_id";
2381
- queryParams["filters[0][op]"] = "==";
2382
- queryParams["filters[0][value]"] = params.offerId;
2383
- }
2384
- return queryParams;
2385
- }
2386
- };
2387
- var Participation = {
2388
- /** Maps API DTO shape into the SDK participation domain model. */
2389
- fromDto: (dto) => {
2390
- const walletAddress = notBlankStringOrNull(dto.wallet_address);
2391
- return {
2392
- id: ParticipationId(dto.id),
2393
- offerId: OfferId(dto.offer_id),
2394
- offerOptionId: OfferOptionId(dto.offer_option_id),
2395
- status: dto.status,
2396
- amount: dto.amount,
2397
- displayAmount: dto.amount_string,
2398
- asset: Asset.fromDto(dto.asset),
2399
- chain: Blockchain(dto.chain),
2400
- insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
2401
- updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
2402
- walletAddress: walletAddress ? WalletAddress(walletAddress) : null
2403
- };
2404
- }
2405
- };
2406
- var CreateParticipationParams = {
2407
- /** Maps participation creation params into API DTO payload. */
2408
- toDto: (params) => ({
2409
- offer_id: params.offerId,
2410
- offer_option_id: params.offerOptionId,
2411
- chain: params.chain,
2412
- wallet_address: params.walletAddress,
2413
- amount: params.amount,
2414
- asset_id: params.assetId,
2415
- approval_transaction_hash: params.approvalTransactionHash
2416
- })
2417
- };
2418
-
2419
- // src/universal/api/frontline/providers/coin-list/token-sale.ts
2420
- async function fetchParticipations(api, offerId) {
2421
- return fetchAllPages(
2422
- (params) => fetchParticipationsPage(api, params),
2423
- { offerId }
2424
- );
2425
- }
2426
- async function fetchParticipationsPage(api, params) {
2427
- const pageDto = await api.send({
2428
- method: "GET",
2429
- url: "/v1/participations",
2430
- queryParams: ParticipationsPaginationParams.toQueryParams(params),
2431
- attributes: Attributes.protected()
2432
- });
2433
- return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
2434
- }
2435
- async function fetchParticipation(api, id) {
2436
- const dto = await api.send({
2437
- method: "GET",
2438
- url: `/v1/participations/${id}`,
2439
- attributes: Attributes.protected()
2440
- });
2441
- return Participation.fromDto(dto);
2442
- }
2443
- async function createParticipation(api, params) {
2444
- const dto = await api.send({
2445
- method: "POST",
2446
- url: "/v1/participations",
2447
- body: CreateParticipationParams.toDto(params),
2448
- attributes: Attributes.protected()
2449
- });
2450
- return Participation.fromDto(dto);
2451
- }
2452
-
2453
- // src/universal/core/checkout/coin-list/token-sale-namespace.ts
2454
- var CoinListTokenSaleNamespaceImpl = class {
2455
- constructor(ctx) {
2456
- this.ctx = ctx;
2457
- this.log = internalLogger(ctx.logger, "TOKEN_SALE");
2458
- }
2459
- async list(offerId) {
2460
- return this.log.wrap("list", offerId, async () => {
2461
- await this.ctx.ensureUserAuthenticated();
2462
- return fetchParticipations(this.ctx.api, offerId);
2463
- });
2464
- }
2465
- async listPage(params) {
2466
- return this.log.wrap("listPage", params, async () => {
2467
- await this.ctx.ensureUserAuthenticated();
2468
- return fetchParticipationsPage(this.ctx.api, params);
2469
- });
2470
- }
2471
- async get(id) {
2472
- return this.log.wrap("get", id, async () => {
2473
- await this.ctx.ensureUserAuthenticated();
2474
- return fetchParticipation(this.ctx.api, id);
2475
- });
2476
- }
2477
- async createParticipation(params) {
2478
- return this.log.wrap("createParticipation", params, async () => {
2479
- await this.ctx.ensureUserAuthenticated();
2480
- return createParticipation(this.ctx.api, params);
2481
- });
2482
- }
2483
- };
2484
-
2485
- // src/universal/core/shared/blockchain/formatters.ts
2486
- var import_viem5 = require("viem");
2487
- function formatRawAmount(amount) {
2488
- return (0, import_viem5.formatUnits)(amount.raw, amount.decimals);
2489
- }
2490
- var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
2491
- var SHARE_MAX_FRACTION_DIGITS = AssetDecimals(6);
2492
- var SHARE_MIN_FRACTION_DIGITS = AssetDecimals(2);
2493
- var USD_FRACTION_DIGITS = AssetDecimals(2);
2494
-
2495
- // src/universal/types/providers/ondo/ondo.ts
2496
- var OndoTradingStatus = {
2497
- fromDto: (dto) => {
2498
- if (!dto.tradable) return { type: "not-tradable", side: dto.side };
2499
- return {
2500
- type: "tradable",
2501
- side: dto.side,
2502
- grossMaxTokens: decimalOrNull(dto.gross_max_tokens),
2503
- grossMaxNotionalValue: decimalOrNull(dto.gross_max_notional_value),
2504
- grossMaxActiveNotionalValue: decimalOrNull(
2505
- dto.gross_max_active_notional_value
2506
- )
2507
- };
2508
- }
2509
- };
2510
- var OndoQuote = {
2511
- fromDto: (dto) => {
2512
- const assetDecimals = AssetDecimals(dto.asset_decimals);
2513
- return {
2514
- chain: chainFromId(dto.chain_id),
2515
- ticker: Ticker(dto.ticker),
2516
- assetAddress: EvmContractAddress(dto.asset_address),
2517
- asset: {
2518
- name: dto.ticker,
2519
- symbol: AssetSymbol(dto.symbol),
2520
- decimals: assetDecimals
2521
- },
2522
- side: dto.side,
2523
- tokenBaseUnits: blockchainAmountFromRawOrThrow({
2524
- label: "tokenBaseUnits",
2525
- raw: dto.token_base_units,
2526
- decimals: assetDecimals
2527
- }),
2528
- price: DecimalString(dto.price)
2529
- };
2530
- }
2531
- };
2532
- var OndoBuyTransaction = {
2533
- fromDto: (dto) => {
2534
- const spendDecimals = AssetDecimals(dto.spend_input_decimals);
2535
- const outputDecimals = AssetDecimals(dto.receive_output_decimals);
2536
- return {
2537
- ...parseSwapCore(dto, spendDecimals),
2538
- side: "buy",
2539
- fee: blockchainAmountFromRawOrThrow({
2540
- label: "fee",
2541
- raw: dto.fee,
2542
- decimals: spendDecimals
2543
- }),
2544
- notionalValue: blockchainAmountFromRawOrThrow({
2545
- label: "notional_value",
2546
- raw: dto.notional_value,
2547
- decimals: spendDecimals
2548
- }),
2549
- receiveOutputAmount: parsePositiveAmount({
2550
- label: "receive_output_amount",
2551
- raw: dto.receive_output_amount,
2552
- decimals: outputDecimals,
2553
- // A transaction that yields nothing is not one to sign - the user
2554
- // would pay the deposit and receive no asset - and frontline refuses
2555
- // to emit one. A zero here is a changed encoding, not a small order.
2556
- // Rejecting it at the boundary is also what lets `computeOndoBuyPrice`
2557
- // divide by it without a fallible result: the failure surfaces as the
2558
- // data hook's ERROR state rather than as a division during render.
2559
- reason: "a buy that yields nothing is not fillable"
2560
- })
2561
- };
2562
- }
2563
- };
2564
- var OndoSellTransaction = {
2565
- fromDto: (dto) => {
2566
- const spendDecimals = AssetDecimals(dto.spend_input_decimals);
2567
- const outputDecimals = AssetDecimals(dto.receive_output_decimals);
2568
- const expectedQuantity = parsePositiveAmount({
2569
- label: "expected_quantity",
2570
- raw: dto.expected_quantity,
2571
- decimals: outputDecimals,
2572
- reason: "a sale that yields nothing is not fillable"
2573
- });
2574
- return {
2575
- ...parseSwapCore(dto, spendDecimals),
2576
- side: "sell",
2577
- expected: {
2578
- quantity: expectedQuantity,
2579
- fee: blockchainAmountFromRawOrThrow({
2580
- label: "expected_fee",
2581
- raw: dto.expected_fee,
2582
- decimals: outputDecimals
2583
- })
2584
- },
2585
- minimum: {
2586
- quantity: parseMinimumQuantity(
2587
- dto.minimum_quantity,
2588
- outputDecimals,
2589
- expectedQuantity
2590
- ),
2591
- fee: blockchainAmountFromRawOrThrow({
2592
- label: "minimum_fee",
2593
- raw: dto.minimum_fee,
2594
- decimals: outputDecimals
2595
- })
2596
- }
2597
- };
2598
- }
2599
- };
2600
- function parseSwapCore(dto, spendDecimals) {
2601
- return {
2602
- tx: {
2603
- to: EvmContractAddress(dto.to),
2604
- data: HexEncodedTransactionData(dto.data)
2605
- },
2606
- expiresAt: parseExpiresAt(dto.expires_at),
2607
- spendInputAmount: parsePositiveAmount({
2608
- label: "spend_input_amount",
2609
- raw: dto.spend_input_amount,
2610
- decimals: spendDecimals,
2611
- // A transaction that takes nothing from the wallet is not one to sign:
2612
- // it would settle one leg of a trade and skip the other. Frontline
2613
- // refuses an `amount` of zero whichever way the trade runs, so this is a
2614
- // changed encoding rather than a small order.
2615
- //
2616
- // Guarded on both sides rather than on the sale alone, because which
2617
- // amount becomes the divisor in the price flips with the direction: a
2618
- // guard placed by that would be a rule about the arithmetic rather than
2619
- // about the trade.
2620
- reason: "a swap that spends nothing is not fillable"
2621
- })
2622
- };
2623
- }
2624
- function parseMinimumQuantity(raw, decimals, expectedQuantity) {
2625
- const amount = parsePositiveAmount({
2626
- label: "minimum_quantity",
2627
- raw,
2628
- decimals,
2629
- reason: "a floor of zero guarantees nothing"
2630
- });
2631
- if (amount.raw > expectedQuantity.raw) {
2632
- throw new ValidationError(
2633
- `minimum_quantity: must not exceed expected_quantity ("${raw}" > "${expectedQuantity.raw}")`
2634
- );
2635
- }
2636
- return amount;
2637
- }
2638
- function parsePositiveAmount({
2639
- label,
2640
- raw,
2641
- decimals,
2642
- reason
2643
- }) {
2644
- const amount = blockchainAmountFromRawOrThrow({ label, raw, decimals });
2645
- if (amount.raw <= 0n) {
2646
- throw new ValidationError(
2647
- `${label}: must be greater than zero ("${raw}") - ${reason}`
2648
- );
2649
- }
2650
- return amount;
2651
- }
2652
- function parseExpiresAt(value) {
2653
- const date = new Date(value);
2654
- if (Number.isNaN(date.getTime())) {
2655
- throw new ValidationError(`expires_at: not a date ("${value}")`);
2656
- }
2657
- return date;
2658
- }
2659
-
2660
- // src/universal/api/frontline/providers/ondo/ondo.ts
2661
- async function getOndoTradingStatus(api, params) {
2662
- const dto = await api.send({
2663
- method: "GET",
2664
- url: "/v1/ondo/swap/trading-status",
2665
- queryParams: { symbol: params.symbol, side: params.side },
2666
- attributes: Attributes.protected()
2667
- });
2668
- return OndoTradingStatus.fromDto(dto);
2669
- }
2670
- async function getOndoQuote(api, params) {
2671
- const dto = await api.send({
2672
- method: "GET",
2673
- url: "/v1/ondo/swap/quote",
2674
- queryParams: {
2675
- symbol: params.symbol,
2676
- side: params.side,
2677
- duration: params.duration,
2678
- ...sizeParam(params)
2679
- },
2680
- attributes: Attributes.protected()
2681
- });
2682
- return OndoQuote.fromDto(dto);
2683
- }
2684
- async function buildOndoBuy(api, params) {
2685
- const dto = await api.send({
2686
- method: "POST",
2687
- url: "/v1/ondo/swap/buy",
2688
- body: swapBody(params),
2689
- attributes: Attributes.protected()
2690
- });
2691
- assertSpendScaleAgrees({
2692
- published: dto.spend_input_decimals,
2693
- sized: params.amount,
2694
- trade: "purchase"
2695
- });
2696
- return OndoBuyTransaction.fromDto(dto);
2697
- }
2698
- async function buildOndoSell(api, params) {
2699
- const dto = await api.send({
2700
- method: "POST",
2701
- url: "/v1/ondo/swap/sell",
2702
- body: swapBody(params),
2703
- attributes: Attributes.protected()
2704
- });
2705
- assertSpendScaleAgrees({
2706
- published: dto.spend_input_decimals,
2707
- sized: params.amount,
2708
- trade: "sale",
2709
- // The two answers come from two chains, so on a testnet they can disagree
2710
- // for a reason that is neither the caller's nor a corrupt response. Say so,
2711
- // or a QA run reads as a puzzle rather than a diagnosis.
2712
- note: "the quote resolves the asset on Ethereum mainnet while the swap executes on the chain requested, so these disagree until frontline serves a chain-scoped quote"
2713
- });
2714
- return OndoSellTransaction.fromDto(dto);
2715
- }
2716
- function swapBody(params) {
2717
- return {
2718
- symbol: params.symbol,
2719
- chain: params.chain,
2720
- wallet_address: params.walletAddress,
2721
- amount: params.amount.raw.toString()
2722
- };
2723
- }
2724
- function assertSpendScaleAgrees({
2725
- published,
2726
- sized,
2727
- trade,
2728
- note
2729
- }) {
2730
- if (published === sized.decimals) return;
2731
- const because = note === void 0 ? "" : ` - ${note}`;
2732
- throw new ValidationError(
2733
- `spend_input_decimals: the ${trade} was priced in ${published} decimals but the order was sized in ${sized.decimals}${because}`
2734
- );
2735
- }
2736
- function sizeParam(params) {
2737
- const tokenAmount = "tokenAmount" in params ? params.tokenAmount : void 0;
2738
- const notionalValue = "notionalValue" in params ? params.notionalValue : void 0;
2739
- if (tokenAmount !== void 0) {
2740
- if (notionalValue !== void 0) {
2741
- throw new ValidationError(
2742
- "An Ondo quote takes tokenAmount or notionalValue, not both"
2743
- );
2744
- }
2745
- return { token_amount: formatRawAmount(tokenAmount) };
2746
- }
2747
- if (notionalValue === void 0) {
2748
- throw new ValidationError(
2749
- "An Ondo quote must be sized by tokenAmount or notionalValue"
2750
- );
2751
- }
2752
- return { notional_value: notionalValue };
2753
- }
2754
-
2755
- // src/universal/core/checkout/ondo/ondo-namespace.ts
2756
- var OndoNamespaceImpl = class {
2757
- constructor(ctx) {
2758
- this.ctx = ctx;
2759
- this.log = internalLogger(ctx.logger, "ONDO");
2760
- }
2761
- async getTradingStatus(params) {
2762
- return this.log.wrap("getTradingStatus", params, async () => {
2763
- await this.ctx.ensureUserAuthenticated();
2764
- return getOndoTradingStatus(this.ctx.api, params);
2765
- });
2766
- }
2767
- async getQuote(params) {
2768
- return this.log.wrap("getQuote", params, async () => {
2769
- await this.ctx.ensureUserAuthenticated();
2770
- return getOndoQuote(this.ctx.api, params);
2771
- });
2772
- }
2773
- async buildBuyTransaction(params) {
2774
- return this.log.wrap("buildBuyTransaction", params, async () => {
2775
- await this.ctx.ensureUserAuthenticated();
2776
- return buildOndoBuy(this.ctx.api, params);
2777
- });
2778
- }
2779
- async buildSellTransaction(params) {
2780
- return this.log.wrap("buildSellTransaction", params, async () => {
2781
- await this.ctx.ensureUserAuthenticated();
2782
- return buildOndoSell(this.ctx.api, params);
2783
- });
2784
- }
2785
- };
2786
-
2787
- // src/universal/types/providers/superstate/swap.ts
2788
- var SwapPreview = {
2789
- /** Maps the contract's `Preview { input, fee, output }` struct. */
2790
- fromContract: (preview) => ({
2791
- inputAmount: parseUint256(preview.input, "SwapPreview.input"),
2792
- fee: parseUint256(preview.fee, "SwapPreview.fee"),
2793
- outputAmount: parseUint256(preview.output, "SwapPreview.output")
2794
- })
2795
- };
2796
- var PauseFlags = (value) => value;
2797
- var SwapStatus = {
2798
- /**
2799
- * Maps the contract's `Status { uint32 flags; State state }` struct, where
2800
- * `State` is `0 = Active | 1 = Paused | 2 = Stopped`.
2801
- *
2802
- * `flags` is carried onto the `paused` arm only. On the other two the
2803
- * contract sets it to a self-identifying marker rather than to information -
2804
- * so repeating it would invite a caller to read meaning into a constant.
2805
- *
2806
- * @throws ValidationError on a `state` outside the enum. A contract that has
2807
- * grown a fourth state is one the SDK does not model, and guessing `active`
2808
- * would let a halted swap read as a live one.
2809
- */
2810
- fromContract: (status) => {
2811
- switch (status.state) {
2812
- case 0:
2813
- return { state: "active" };
2814
- case 1:
2815
- return { state: "paused", pausedLevels: PauseFlags(status.flags) };
2816
- case 2:
2817
- return { state: "stopped" };
2818
- default:
2819
- throw new ValidationError(
2820
- `SwapStatus.state: unknown contract state (${status.state})`
2821
- );
2822
- }
2823
- }
2824
- };
2825
- var AllowWalletResponse = {
2826
- fromDto: (dto) => {
2827
- switch (dto.action) {
2828
- case "broadcast_transaction":
2829
- return {
2830
- action: "broadcast_transaction",
2831
- to: EvmContractAddress(dto.to),
2832
- data: HexEncodedTransactionData(dto.data)
2833
- };
2834
- case "none":
2835
- return {
2836
- action: "none",
2837
- alreadyAllowed: dto.already_allowed
2838
- };
2839
- default: {
2840
- const _exhaustive = dto;
2841
- return _exhaustive;
2842
- }
2843
- }
2844
- }
2845
- };
2846
-
2847
- // src/universal/api/frontline/providers/superstate/swap.ts
2848
- async function allowWallet(api, params) {
2849
- const dto = await api.send({
2850
- method: "POST",
2851
- url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,
2852
- body: {
2853
- wallet_address: params.walletAddress,
2854
- chain: params.chain,
2855
- signature: params.signature
2856
- },
2857
- attributes: Attributes.protected()
2858
- });
2859
- return AllowWalletResponse.fromDto(dto);
2860
- }
2861
-
2862
- // src/universal/core/checkout/superstate/blockchain/abi.ts
2863
- var SUPERSTATE_SWAP_ABI = [
2864
- {
2865
- type: "function",
2866
- name: "KIND",
2867
- inputs: [],
2868
- outputs: [
2869
- {
2870
- name: "",
2871
- type: "uint16",
2872
- internalType: "uint16"
2873
- }
2874
- ],
2875
- stateMutability: "view"
2876
- },
2877
- {
2878
- type: "function",
2879
- name: "ONE_HUNDRED_P",
2880
- inputs: [],
2881
- outputs: [
2882
- {
2883
- name: "",
2884
- type: "uint256",
2885
- internalType: "uint256"
2886
- }
2887
- ],
2888
- stateMutability: "view"
2889
- },
2890
- {
2891
- type: "function",
2892
- name: "SWAP_LEVEL",
2893
- inputs: [],
2894
- outputs: [
2895
- {
2896
- name: "",
2897
- type: "uint32",
2898
- internalType: "uint32"
2899
- }
2900
- ],
2901
- stateMutability: "view"
2902
- },
2903
- {
2904
- type: "function",
2905
- name: "VERSION",
2906
- inputs: [],
2907
- outputs: [
2908
- {
2909
- name: "",
2910
- type: "uint16",
2911
- internalType: "uint16"
2912
- }
2913
- ],
2914
- stateMutability: "view"
2915
- },
2916
- {
2917
- type: "function",
2918
- name: "authorized",
2919
- inputs: [
2920
- {
2921
- name: "user",
2922
- type: "address",
2923
- internalType: "address"
2924
- }
2925
- ],
2926
- outputs: [
2927
- {
2928
- name: "",
2929
- type: "bool",
2930
- internalType: "bool"
2931
- }
2932
- ],
2933
- stateMutability: "view"
2934
- },
2935
- {
2936
- type: "function",
2937
- name: "bpp",
2938
- inputs: [
2939
- {
2940
- name: "amount",
2941
- type: "uint256",
2942
- internalType: "uint256"
2943
- }
2944
- ],
2945
- outputs: [
2946
- {
2947
- name: "",
2948
- type: "uint256",
2949
- internalType: "uint256"
2950
- }
2951
- ],
2952
- stateMutability: "view"
2953
- },
2954
- {
2955
- type: "function",
2956
- name: "bps",
2957
- inputs: [],
2958
- outputs: [
2959
- {
2960
- name: "",
2961
- type: "uint256",
2962
- internalType: "uint256"
2963
- }
2964
- ],
2965
- stateMutability: "view"
2966
- },
2967
- {
2968
- type: "function",
2969
- name: "cancelOwnershipHandover",
2970
- inputs: [],
2971
- outputs: [],
2972
- stateMutability: "payable"
2973
- },
2974
- {
2975
- type: "function",
2976
- name: "completeOwnershipHandover",
2977
- inputs: [
2978
- {
2979
- name: "pendingOwner",
2980
- type: "address",
2981
- internalType: "address"
2982
- }
2983
- ],
2984
- outputs: [],
2985
- stateMutability: "payable"
2986
- },
2987
- {
2988
- type: "function",
2989
- name: "fee",
2990
- inputs: [
2991
- {
2992
- name: "amount",
2993
- type: "uint256",
2994
- internalType: "uint256"
2995
- }
2996
- ],
2997
- outputs: [
2998
- {
2999
- name: "",
3000
- type: "uint256",
3001
- internalType: "uint256"
3002
- },
3003
- {
3004
- name: "",
3005
- type: "uint256",
3006
- internalType: "uint256"
3007
- }
3008
- ],
3009
- stateMutability: "view"
3010
- },
3011
- {
3012
- type: "function",
3013
- name: "id",
3014
- inputs: [],
3015
- outputs: [
3016
- {
3017
- name: "",
3018
- type: "bytes32",
3019
- internalType: "bytes32"
3020
- }
3021
- ],
3022
- stateMutability: "view"
3023
- },
3024
- {
3025
- type: "function",
3026
- name: "inputTokens",
3027
- inputs: [
3028
- {
3029
- name: "",
3030
- type: "address",
3031
- internalType: "address"
3032
- }
3033
- ],
3034
- outputs: [
3035
- {
3036
- name: "",
3037
- type: "bool",
3038
- internalType: "bool"
3039
- }
3040
- ],
3041
- stateMutability: "view"
3042
- },
3043
- {
3044
- type: "function",
3045
- name: "outputToken",
3046
- inputs: [],
3047
- outputs: [
3048
- {
3049
- name: "",
3050
- type: "address",
3051
- internalType: "address"
3052
- }
3053
- ],
3054
- stateMutability: "view"
3055
- },
3056
- {
3057
- type: "function",
3058
- name: "outputTokenBalance",
3059
- inputs: [],
3060
- outputs: [
3061
- {
3062
- name: "",
3063
- type: "uint256",
3064
- internalType: "uint256"
3065
- }
3066
- ],
3067
- stateMutability: "view"
3068
- },
3069
- {
3070
- type: "function",
3071
- name: "owner",
3072
- inputs: [],
3073
- outputs: [
3074
- {
3075
- name: "result",
3076
- type: "address",
3077
- internalType: "address"
3078
- }
3079
- ],
3080
- stateMutability: "view"
3081
- },
3082
- {
3083
- type: "function",
3084
- name: "ownershipHandoverExpiresAt",
3085
- inputs: [
3086
- {
3087
- name: "pendingOwner",
3088
- type: "address",
3089
- internalType: "address"
3090
- }
3091
- ],
3092
- outputs: [
3093
- {
3094
- name: "result",
3095
- type: "uint256",
3096
- internalType: "uint256"
3097
- }
3098
- ],
3099
- stateMutability: "view"
3100
- },
3101
- {
3102
- type: "function",
3103
- name: "pause",
3104
- inputs: [
3105
- {
3106
- name: "level",
3107
- type: "uint32",
3108
- internalType: "uint32"
3109
- }
3110
- ],
3111
- outputs: [
3112
- {
3113
- name: "",
3114
- type: "bool",
3115
- internalType: "bool"
3116
- }
3117
- ],
3118
- stateMutability: "nonpayable"
3119
- },
3120
- {
3121
- type: "function",
3122
- name: "paused",
3123
- inputs: [],
3124
- outputs: [
3125
- {
3126
- name: "",
3127
- type: "uint32",
3128
- internalType: "uint32"
3129
- }
3130
- ],
3131
- stateMutability: "view"
3132
- },
3133
- {
3134
- type: "function",
3135
- name: "preview",
3136
- inputs: [
3137
- {
3138
- name: "token",
3139
- type: "address",
3140
- internalType: "address"
3141
- },
3142
- {
3143
- name: "amount",
3144
- type: "uint256",
3145
- internalType: "uint256"
3146
- }
3147
- ],
3148
- outputs: [
3149
- {
3150
- name: "",
3151
- type: "tuple",
3152
- internalType: "struct Preview",
3153
- components: [
3154
- {
3155
- name: "input",
3156
- type: "uint256",
3157
- internalType: "uint256"
3158
- },
3159
- {
3160
- name: "fee",
3161
- type: "uint256",
3162
- internalType: "uint256"
3163
- },
3164
- {
3165
- name: "output",
3166
- type: "uint256",
3167
- internalType: "uint256"
3168
- }
3169
- ]
3170
- }
3171
- ],
3172
- stateMutability: "view"
3173
- },
3174
- {
3175
- type: "function",
3176
- name: "renounceOwnership",
3177
- inputs: [],
3178
- outputs: [],
3179
- stateMutability: "payable"
3180
- },
3181
- {
3182
- type: "function",
3183
- name: "requestOwnershipHandover",
3184
- inputs: [],
3185
- outputs: [],
3186
- stateMutability: "payable"
3187
- },
3188
- {
3189
- type: "function",
3190
- name: "setBps",
3191
- inputs: [
3192
- {
3193
- name: "points",
3194
- type: "uint256",
3195
- internalType: "uint256"
3196
- }
3197
- ],
3198
- outputs: [
3199
- {
3200
- name: "",
3201
- type: "bool",
3202
- internalType: "bool"
3203
- }
3204
- ],
3205
- stateMutability: "nonpayable"
3206
- },
3207
- {
3208
- type: "function",
3209
- name: "setInputToken",
3210
- inputs: [
3211
- {
3212
- name: "token",
3213
- type: "address",
3214
- internalType: "address"
3215
- },
3216
- {
3217
- name: "val",
3218
- type: "bool",
3219
- internalType: "bool"
3220
- }
3221
- ],
3222
- outputs: [
3223
- {
3224
- name: "",
3225
- type: "bool",
3226
- internalType: "bool"
3227
- }
3228
- ],
3229
- stateMutability: "nonpayable"
3230
- },
3231
- {
3232
- type: "function",
3233
- name: "status",
3234
- inputs: [],
3235
- outputs: [
3236
- {
3237
- name: "",
3238
- type: "tuple",
3239
- internalType: "struct Status",
3240
- components: [
3241
- {
3242
- name: "flags",
3243
- type: "uint32",
3244
- internalType: "uint32"
3245
- },
3246
- {
3247
- name: "state",
3248
- type: "uint8",
3249
- internalType: "enum State"
3250
- }
3251
- ]
3252
- }
3253
- ],
3254
- stateMutability: "view"
3255
- },
3256
- {
3257
- type: "function",
3258
- name: "stop",
3259
- inputs: [],
3260
- outputs: [
3261
- {
3262
- name: "",
3263
- type: "bool",
3264
- internalType: "bool"
3265
- }
3266
- ],
3267
- stateMutability: "nonpayable"
3268
- },
3269
- {
3270
- type: "function",
3271
- name: "stopped",
3272
- inputs: [],
3273
- outputs: [
3274
- {
3275
- name: "",
3276
- type: "bool",
3277
- internalType: "bool"
3278
- }
3279
- ],
3280
- stateMutability: "view"
3281
- },
3282
- {
3283
- type: "function",
3284
- name: "swap",
3285
- inputs: [
3286
- {
3287
- name: "token",
3288
- type: "address",
3289
- internalType: "address"
3290
- },
3291
- {
3292
- name: "amount",
3293
- type: "uint256",
3294
- internalType: "uint256"
3295
- },
3296
- {
3297
- name: "slip",
3298
- type: "uint256",
3299
- internalType: "uint256"
3300
- }
3301
- ],
3302
- outputs: [
3303
- {
3304
- name: "",
3305
- type: "uint256",
3306
- internalType: "uint256"
3307
- }
3308
- ],
3309
- stateMutability: "nonpayable"
3310
- },
3311
- {
3312
- type: "function",
3313
- name: "tokenBalance",
3314
- inputs: [
3315
- {
3316
- name: "token",
3317
- type: "address",
3318
- internalType: "address"
3319
- }
3320
- ],
3321
- outputs: [
3322
- {
3323
- name: "",
3324
- type: "uint256",
3325
- internalType: "uint256"
3326
- }
3327
- ],
3328
- stateMutability: "view"
3329
- },
3330
- {
3331
- type: "function",
3332
- name: "totals",
3333
- inputs: [
3334
- {
3335
- name: "user",
3336
- type: "address",
3337
- internalType: "address"
3338
- },
3339
- {
3340
- name: "token",
3341
- type: "address",
3342
- internalType: "address"
3343
- }
3344
- ],
3345
- outputs: [
3346
- {
3347
- name: "",
3348
- type: "tuple",
3349
- internalType: "struct SwapTotal",
3350
- components: [
3351
- {
3352
- name: "inputSum",
3353
- type: "uint256",
3354
- internalType: "uint256"
3355
- },
3356
- {
3357
- name: "feeSum",
3358
- type: "uint256",
3359
- internalType: "uint256"
3360
- },
3361
- {
3362
- name: "outputSum",
3363
- type: "uint256",
3364
- internalType: "uint256"
3365
- },
3366
- {
3367
- name: "count",
3368
- type: "uint256",
3369
- internalType: "uint256"
3370
- }
3371
- ]
3372
- }
3373
- ],
3374
- stateMutability: "view"
3375
- },
3376
- {
3377
- type: "function",
3378
- name: "totals",
3379
- inputs: [
3380
- {
3381
- name: "token",
3382
- type: "address",
3383
- internalType: "address"
3384
- }
3385
- ],
3386
- outputs: [
3387
- {
3388
- name: "",
3389
- type: "tuple",
3390
- internalType: "struct SwapTotal",
3391
- components: [
3392
- {
3393
- name: "inputSum",
3394
- type: "uint256",
3395
- internalType: "uint256"
3396
- },
3397
- {
3398
- name: "feeSum",
3399
- type: "uint256",
3400
- internalType: "uint256"
3401
- },
3402
- {
3403
- name: "outputSum",
3404
- type: "uint256",
3405
- internalType: "uint256"
3406
- },
3407
- {
3408
- name: "count",
3409
- type: "uint256",
3410
- internalType: "uint256"
3411
- }
3412
- ]
3413
- }
3414
- ],
3415
- stateMutability: "view"
3416
- },
3417
- {
3418
- type: "function",
3419
- name: "transfer",
3420
- inputs: [
3421
- {
3422
- name: "to",
3423
- type: "address",
3424
- internalType: "address"
3425
- },
3426
- {
3427
- name: "amount",
3428
- type: "uint256",
3429
- internalType: "uint256"
3430
- }
3431
- ],
3432
- outputs: [
3433
- {
3434
- name: "",
3435
- type: "bool",
3436
- internalType: "bool"
3437
- }
3438
- ],
3439
- stateMutability: "nonpayable"
3440
- },
3441
- {
3442
- type: "function",
3443
- name: "transfer",
3444
- inputs: [
3445
- {
3446
- name: "to",
3447
- type: "address",
3448
- internalType: "address"
3449
- },
3450
- {
3451
- name: "token",
3452
- type: "address",
3453
- internalType: "address"
3454
- },
3455
- {
3456
- name: "amount",
3457
- type: "uint256",
3458
- internalType: "uint256"
3459
- }
3460
- ],
3461
- outputs: [
3462
- {
3463
- name: "",
3464
- type: "bool",
3465
- internalType: "bool"
3466
- }
3467
- ],
3468
- stateMutability: "nonpayable"
3469
- },
3470
- {
3471
- type: "function",
3472
- name: "transferOwnership",
3473
- inputs: [
3474
- {
3475
- name: "newOwner",
3476
- type: "address",
3477
- internalType: "address"
3478
- }
3479
- ],
3480
- outputs: [],
3481
- stateMutability: "payable"
3482
- },
3483
- {
3484
- type: "event",
3485
- name: "BpsUpdated",
3486
- inputs: [
3487
- {
3488
- name: "prev",
3489
- type: "uint256",
3490
- indexed: false,
3491
- internalType: "uint256"
3492
- },
3493
- {
3494
- name: "next",
3495
- type: "uint256",
3496
- indexed: false,
3497
- internalType: "uint256"
3498
- }
3499
- ],
3500
- anonymous: false
3501
- },
3502
- {
3503
- type: "event",
3504
- name: "InputTokenUpdated",
3505
- inputs: [
3506
- {
3507
- name: "token",
3508
- type: "address",
3509
- indexed: true,
3510
- internalType: "address"
3511
- },
3512
- {
3513
- name: "prev",
3514
- type: "bool",
3515
- indexed: false,
3516
- internalType: "bool"
3517
- },
3518
- {
3519
- name: "next",
3520
- type: "bool",
3521
- indexed: false,
3522
- internalType: "bool"
3523
- }
3524
- ],
3525
- anonymous: false
3526
- },
3527
- {
3528
- type: "event",
3529
- name: "OwnershipHandoverCanceled",
3530
- inputs: [
3531
- {
3532
- name: "pendingOwner",
3533
- type: "address",
3534
- indexed: true,
3535
- internalType: "address"
3536
- }
3537
- ],
3538
- anonymous: false
3539
- },
3540
- {
3541
- type: "event",
3542
- name: "OwnershipHandoverRequested",
3543
- inputs: [
3544
- {
3545
- name: "pendingOwner",
3546
- type: "address",
3547
- indexed: true,
3548
- internalType: "address"
3549
- }
3550
- ],
3551
- anonymous: false
3552
- },
3553
- {
3554
- type: "event",
3555
- name: "OwnershipTransferred",
3556
- inputs: [
3557
- {
3558
- name: "oldOwner",
3559
- type: "address",
3560
- indexed: true,
3561
- internalType: "address"
3562
- },
3563
- {
3564
- name: "newOwner",
3565
- type: "address",
3566
- indexed: true,
3567
- internalType: "address"
3568
- }
3569
- ],
3570
- anonymous: false
3571
- },
3572
- {
3573
- type: "event",
3574
- name: "Paused",
3575
- inputs: [
3576
- {
3577
- name: "previous",
3578
- type: "uint32",
3579
- indexed: false,
3580
- internalType: "uint32"
3581
- },
3582
- {
3583
- name: "next",
3584
- type: "uint32",
3585
- indexed: false,
3586
- internalType: "uint32"
3587
- }
3588
- ],
3589
- anonymous: false
3590
- },
3591
- {
3592
- type: "event",
3593
- name: "Stopped",
3594
- inputs: [],
3595
- anonymous: false
3596
- },
3597
- {
3598
- type: "event",
3599
- name: "Swapped",
3600
- inputs: [
3601
- {
3602
- name: "user",
3603
- type: "address",
3604
- indexed: true,
3605
- internalType: "address"
3606
- },
3607
- {
3608
- name: "inputToken",
3609
- type: "address",
3610
- indexed: true,
3611
- internalType: "address"
3612
- },
3613
- {
3614
- name: "outputToken",
3615
- type: "address",
3616
- indexed: true,
3617
- internalType: "address"
3618
- },
3619
- {
3620
- name: "inputAmount",
3621
- type: "uint256",
3622
- indexed: false,
3623
- internalType: "uint256"
3624
- },
3625
- {
3626
- name: "fee",
3627
- type: "uint256",
3628
- indexed: false,
3629
- internalType: "uint256"
3630
- },
3631
- {
3632
- name: "outputAmount",
3633
- type: "uint256",
3634
- indexed: false,
3635
- internalType: "uint256"
3636
- }
3637
- ],
3638
- anonymous: false
3639
- },
3640
- {
3641
- type: "event",
3642
- name: "Transferred",
3643
- inputs: [
3644
- {
3645
- name: "to",
3646
- type: "address",
3647
- indexed: true,
3648
- internalType: "address"
3649
- },
3650
- {
3651
- name: "token",
3652
- type: "address",
3653
- indexed: true,
3654
- internalType: "address"
3655
- },
3656
- {
3657
- name: "amount",
3658
- type: "uint256",
3659
- indexed: false,
3660
- internalType: "uint256"
3661
- }
3662
- ],
3663
- anonymous: false
3664
- },
3665
- {
3666
- type: "error",
3667
- name: "AlreadyInitialized",
3668
- inputs: []
3669
- },
3670
- {
3671
- type: "error",
3672
- name: "InsufficientAmount",
3673
- inputs: []
3674
- },
3675
- {
3676
- type: "error",
3677
- name: "InvalidAddress",
3678
- inputs: []
3679
- },
3680
- {
3681
- type: "error",
3682
- name: "InvalidAmount",
3683
- inputs: []
3684
- },
3685
- {
3686
- type: "error",
3687
- name: "IsPaused",
3688
- inputs: [
3689
- {
3690
- name: "level",
3691
- type: "uint32",
3692
- internalType: "uint32"
3693
- }
3694
- ]
3695
- },
3696
- {
3697
- type: "error",
3698
- name: "IsStopped",
3699
- inputs: []
3700
- },
3701
- {
3702
- type: "error",
3703
- name: "NewOwnerIsZeroAddress",
3704
- inputs: []
3705
- },
3706
- {
3707
- type: "error",
3708
- name: "NoHandoverRequest",
3709
- inputs: []
3710
- },
3711
- {
3712
- type: "error",
3713
- name: "SwapFailed",
3714
- inputs: [
3715
- {
3716
- name: "user",
3717
- type: "address",
3718
- internalType: "address"
3719
- },
3720
- {
3721
- name: "token",
3722
- type: "address",
3723
- internalType: "address"
3724
- }
3725
- ]
3726
- },
3727
- {
3728
- type: "error",
3729
- name: "Unauthorized",
3730
- inputs: []
3731
- }
3732
- ];
3733
-
3734
- // src/universal/core/shared/blockchain/erc20/abi.ts
3735
- var ERC20_ABI = [
3736
- {
3737
- type: "function",
3738
- name: "allowance",
3739
- inputs: [
3740
- { name: "owner", type: "address" },
3741
- { name: "spender", type: "address" }
3742
- ],
3743
- outputs: [{ name: "", type: "uint256" }],
3744
- stateMutability: "view"
3745
- },
3746
- {
3747
- type: "function",
3748
- name: "approve",
3749
- inputs: [
3750
- { name: "spender", type: "address" },
3751
- { name: "amount", type: "uint256" }
3752
- ],
3753
- outputs: [{ name: "", type: "bool" }],
3754
- stateMutability: "nonpayable"
3755
- },
3756
- {
3757
- type: "function",
3758
- name: "balanceOf",
3759
- inputs: [{ name: "account", type: "address" }],
3760
- outputs: [{ name: "", type: "uint256" }],
3761
- stateMutability: "view"
3762
- },
3763
- {
3764
- type: "function",
3765
- name: "decimals",
3766
- inputs: [],
3767
- outputs: [{ name: "", type: "uint8" }],
3768
- stateMutability: "view"
3769
- },
3770
- {
3771
- type: "function",
3772
- name: "name",
3773
- inputs: [],
3774
- outputs: [{ name: "", type: "string" }],
3775
- stateMutability: "view"
3776
- },
3777
- {
3778
- type: "function",
3779
- name: "symbol",
3780
- inputs: [],
3781
- outputs: [{ name: "", type: "string" }],
3782
- stateMutability: "view"
3783
- },
3784
- {
3785
- type: "function",
3786
- name: "totalSupply",
3787
- inputs: [],
3788
- outputs: [{ name: "", type: "uint256" }],
3789
- stateMutability: "view"
3790
- },
3791
- {
3792
- type: "function",
3793
- name: "transfer",
3794
- inputs: [
3795
- { name: "recipient", type: "address" },
3796
- { name: "amount", type: "uint256" }
3797
- ],
3798
- outputs: [{ name: "", type: "bool" }],
3799
- stateMutability: "nonpayable"
3800
- },
3801
- {
3802
- type: "function",
3803
- name: "transferFrom",
3804
- inputs: [
3805
- { name: "sender", type: "address" },
3806
- { name: "recipient", type: "address" },
3807
- { name: "amount", type: "uint256" }
3808
- ],
3809
- outputs: [{ name: "", type: "bool" }],
3810
- stateMutability: "nonpayable"
3811
- },
3812
- {
3813
- type: "event",
3814
- name: "Approval",
3815
- inputs: [
3816
- { name: "owner", type: "address", indexed: true },
3817
- { name: "spender", type: "address", indexed: true },
3818
- { name: "value", type: "uint256", indexed: false }
3819
- ],
3820
- anonymous: false
3821
- },
3822
- {
3823
- type: "event",
3824
- name: "Transfer",
3825
- inputs: [
3826
- { name: "from", type: "address", indexed: true },
3827
- { name: "to", type: "address", indexed: true },
3828
- { name: "value", type: "uint256", indexed: false }
3829
- ],
3830
- anonymous: false
3831
- }
3832
- ];
3833
-
3834
- // src/universal/api/rpc/providers/superstate/swap.ts
3835
- async function getSwapAuthorization(clients, params) {
3836
- return clients(params.chain).readContract({
3837
- address: params.contractAddress,
3838
- abi: SUPERSTATE_SWAP_ABI,
3839
- functionName: "authorized",
3840
- args: [params.walletAddress]
3841
- });
3842
- }
3843
- async function getSwapPreview(clients, params) {
3844
- const preview = await clients(params.chain).readContract({
3845
- address: params.contractAddress,
3846
- abi: SUPERSTATE_SWAP_ABI,
3847
- functionName: "preview",
3848
- args: [params.inputToken, params.amount]
3849
- });
3850
- return SwapPreview.fromContract(preview);
3851
- }
3852
- async function getSwapStatus(clients, params) {
3853
- const status = await clients(params.chain).readContract({
3854
- address: params.contractAddress,
3855
- abi: SUPERSTATE_SWAP_ABI,
3856
- functionName: "status"
3857
- });
3858
- return SwapStatus.fromContract(status);
3859
- }
3860
- async function getSwapOutputToken(clients, params) {
3861
- const client = clients(params.chain);
3862
- const tokenAddress = await client.readContract({
3863
- address: params.contractAddress,
3864
- abi: SUPERSTATE_SWAP_ABI,
3865
- functionName: "outputToken"
3866
- });
3867
- const token = { address: EvmContractAddress(tokenAddress), abi: ERC20_ABI };
3868
- const [name, symbol, decimals] = await client.multicall({
3869
- contracts: [
3870
- { ...token, functionName: "name" },
3871
- { ...token, functionName: "symbol" },
3872
- { ...token, functionName: "decimals" }
3873
- ],
3874
- allowFailure: false
3875
- });
3876
- return {
3877
- name,
3878
- symbol: AssetSymbol(symbol),
3879
- decimals: AssetDecimals(decimals)
3880
- };
3881
- }
3882
-
3883
- // src/universal/core/checkout/superstate/swap-namespace.ts
3884
- var SuperstateSwapNamespaceImpl = class {
3885
- constructor(ctx) {
3886
- this.ctx = ctx;
3887
- this.log = internalLogger(ctx.logger, "SUPERSTATE");
3888
- }
3889
- async getAuthorization(params) {
3890
- return this.log.wrap(
3891
- "getAuthorization",
3892
- params,
3893
- async () => getSwapAuthorization(this.ctx.rpc, params)
3894
- );
3895
- }
3896
- async getPreview(params) {
3897
- return this.log.wrap(
3898
- "getPreview",
3899
- params,
3900
- async () => getSwapPreview(this.ctx.rpc, params)
3901
- );
3902
- }
3903
- async getStatus(params) {
3904
- return this.log.wrap(
3905
- "getStatus",
3906
- params,
3907
- async () => getSwapStatus(this.ctx.rpc, params)
3908
- );
3909
- }
3910
- async getOutputToken(params) {
3911
- return this.log.wrap(
3912
- "getOutputToken",
3913
- params,
3914
- async () => getSwapOutputToken(this.ctx.rpc, params)
3915
- );
3916
- }
3917
- async allowWallet(params) {
3918
- return this.log.wrap("allowWallet", params, async () => {
3919
- await this.ctx.ensureUserAuthenticated();
3920
- return allowWallet(this.ctx.api, params);
3921
- });
3922
- }
3923
- };
3924
-
3925
- // src/universal/api/rpc/erc20.ts
3926
- async function getTokenAllowance(clients, params) {
3927
- const allowance = await clients(params.chain).readContract({
3928
- address: params.tokenAddress,
3929
- abi: ERC20_ABI,
3930
- functionName: "allowance",
3931
- args: [params.owner, params.spender]
3932
- });
3933
- return parseUint256(allowance, "allowance");
3934
- }
3935
- async function getTokenBalance(clients, params) {
3936
- const balance = await clients(params.chain).readContract({
3937
- address: params.tokenAddress,
3938
- abi: ERC20_ABI,
3939
- functionName: "balanceOf",
3940
- args: [params.owner]
3941
- });
3942
- return parseUint256(balance, "balanceOf");
3943
- }
3944
-
3945
- // src/universal/core/shared/blockchain/erc20/erc20-namespace.ts
3946
- var Erc20NamespaceImpl = class {
3947
- constructor(ctx) {
3948
- this.ctx = ctx;
3949
- this.log = internalLogger(ctx.logger, "ERC20");
3950
- }
3951
- async getAllowance(params) {
3952
- return this.log.wrap(
3953
- "getAllowance",
3954
- params,
3955
- async () => getTokenAllowance(this.ctx.rpc, params)
3956
- );
3957
- }
3958
- async getBalance(params) {
3959
- return this.log.wrap(
3960
- "getBalance",
3961
- params,
3962
- async () => getTokenBalance(this.ctx.rpc, params)
3963
- );
3964
- }
3965
- };
3966
-
3967
- // src/universal/api/nabu/tokens.ts
3968
- var import_viem6 = require("viem");
3969
-
3970
- // src/universal/types/token-metadata.ts
3971
- var TokenLogoUrl = (value) => value;
3972
- var TokenLogo = {
3973
- /** `baseUrl` is the registry origin; registry URLs are root-relative. */
3974
- fromDto: (dto, baseUrl) => dto.kind === "VECTOR" ? { kind: "VECTOR", url: resolveLogoUrl(dto.url, baseUrl) } : {
3975
- kind: "RASTER",
3976
- original: logoImageFromDto(dto.original, baseUrl),
3977
- variants: dto.variants.map((v) => logoImageFromDto(v, baseUrl))
3978
- }
3979
- };
3980
- var TokenMetadata = {
3981
- /** `baseUrl` is the registry origin; registry logo URLs are root-relative. */
3982
- fromDto: (dto, baseUrl) => {
3983
- assertSupportedSchemaVersion(dto.schema_version);
3984
- return {
3985
- identifier: {
3986
- chain: EthereumChain(dto.chain),
3987
- address: EvmContractAddress(dto.address)
3988
- },
3989
- name: dto.name,
3990
- symbol: AssetSymbol(dto.symbol),
3991
- decimals: AssetDecimals(dto.decimals),
3992
- logo: TokenLogo.fromDto(dto.logo, baseUrl),
3993
- logoDark: dto.logo_dark === void 0 ? null : TokenLogo.fromDto(dto.logo_dark, baseUrl)
3994
- };
3995
- },
3996
- /**
3997
- * Maps the complete registry snapshot to every token it lists across the
3998
- * chains this SDK models, skipping native coins and chains outside
3999
- * {@link EthereumChain} (e.g. Solana) rather than failing on them — the
4000
- * registry may serve chains ahead of the SDK's type surface.
4001
- */
4002
- fromRegistryDto: (dto, baseUrl) => {
4003
- assertSupportedSchemaVersion(dto.schema_version);
4004
- return dto.chains.flatMap((chainDto) => {
4005
- let chain;
4006
- try {
4007
- chain = EthereumChain(chainDto.chain);
4008
- } catch {
4009
- return [];
4010
- }
4011
- return tokensOfChain(chain, chainDto.assets, baseUrl);
4012
- });
4013
- },
4014
- /**
4015
- * Maps a chain snapshot to the tokens it lists, skipping the chain's native
4016
- * coin (`kind: 'COIN'`, no contract address).
4017
- */
4018
- fromChainAssetsDto: (dto, baseUrl) => {
4019
- assertSupportedSchemaVersion(dto.schema_version);
4020
- return tokensOfChain(EthereumChain(dto.chain), dto.assets, baseUrl);
4021
- }
4022
- };
4023
- function tokensOfChain(chain, assets, baseUrl) {
4024
- return assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
4025
- identifier: {
4026
- chain,
4027
- // The filter above cannot narrow `address` for the type checker.
4028
- address: EvmContractAddress(asset.address)
4029
- },
4030
- name: asset.name,
4031
- symbol: AssetSymbol(asset.symbol),
4032
- decimals: AssetDecimals(asset.decimals),
4033
- logo: TokenLogo.fromDto(asset.logo, baseUrl),
4034
- logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
4035
- }));
4036
- }
4037
- function assertSupportedSchemaVersion(version) {
4038
- if (version !== 1) {
4039
- throw new ValidationError(
4040
- `Unsupported token registry schema_version: ${version}`
4041
- );
4042
- }
4043
- }
4044
- var logoImageFromDto = (dto, baseUrl) => ({
4045
- url: resolveLogoUrl(dto.url, baseUrl),
4046
- width: dto.width,
4047
- height: dto.height
4048
- });
4049
- var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
4050
- url.startsWith("http") ? url : `${baseUrl.replace(/\/$/, "")}${url}`
4051
- );
4052
-
4053
- // src/universal/api/nabu/tokens.ts
4054
- function createNabuApiClient(baseUrl, logger = null) {
4055
- return new HttpClient({ baseUrl }, {}, logger);
4056
- }
4057
- async function fetchTokenMetadata(client, token) {
4058
- const address = checksummed(token.address);
4059
- let response;
4060
- try {
4061
- response = await client.send({
4062
- method: "GET",
4063
- url: `/${token.chain}/token/${address}`
4064
- });
4065
- } catch (error) {
4066
- if (isRegistryHtmlFallback(error)) {
4067
- return null;
4068
- }
4069
- throw error;
4070
- }
4071
- if (response.status === 404) {
4072
- return null;
4073
- }
4074
- assertOk(response);
4075
- if (response.body === null) {
4076
- throw new ValidationError(
4077
- `Token registry returned an empty body for token "${address}" on "${token.chain}"`
4078
- );
4079
- }
4080
- return TokenMetadata.fromDto(response.body, client.config.baseUrl);
4081
- }
4082
- async function fetchTokensMetadata(client, chain) {
4083
- let response;
4084
- try {
4085
- response = await client.send({
4086
- method: "GET",
4087
- url: `/${chain}/assets.json`
4088
- });
4089
- } catch (error) {
4090
- if (isRegistryHtmlFallback(error)) {
4091
- throw new ValidationError(
4092
- `Token registry returned non-JSON for the "${chain}" snapshot`
4093
- );
4094
- }
4095
- throw error;
4096
- }
4097
- assertOk(response);
4098
- if (response.body === null) {
4099
- throw new ValidationError(
4100
- `Token registry returned an empty "${chain}" snapshot`
4101
- );
4102
- }
4103
- return TokenMetadata.fromChainAssetsDto(response.body, client.config.baseUrl);
4104
- }
4105
- async function fetchAllTokensMetadata(client) {
4106
- let response;
4107
- try {
4108
- response = await client.send({
4109
- method: "GET",
4110
- url: `/assets.json`
4111
- });
4112
- } catch (error) {
4113
- if (isRegistryHtmlFallback(error)) {
4114
- throw new ValidationError(
4115
- "Token registry returned non-JSON for the complete snapshot"
4116
- );
4117
- }
4118
- throw error;
4119
- }
4120
- assertOk(response);
4121
- if (response.body === null) {
4122
- throw new ValidationError(
4123
- "Token registry returned an empty complete snapshot"
4124
- );
4125
- }
4126
- return TokenMetadata.fromRegistryDto(response.body, client.config.baseUrl);
4127
- }
4128
- function isRegistryHtmlFallback(error) {
4129
- return error instanceof HttpError && error.response.status >= 200 && error.response.status < 300;
4130
- }
4131
- function assertOk(response) {
4132
- if (response.status < 200 || response.status >= 300) {
4133
- throw new HttpError(response);
4134
- }
4135
- }
4136
- function checksummed(address) {
4137
- try {
4138
- return (0, import_viem6.getAddress)(address);
4139
- } catch (_) {
4140
- throw new ValidationError(`Invalid EVM contract address: "${address}"`);
4141
- }
4142
- }
4143
-
4144
- // src/universal/core/tokens/tokens-namespace.ts
4145
- var TokensNamespaceImpl = class {
4146
- /**
4147
- * Takes the registry origin rather than a `UniversalNamespaceContext`: the
4148
- * registry is unauthenticated and on its own host, so the frontline sender
4149
- * and the auth check would both be dead weight here.
4150
- */
4151
- constructor(baseUrl, logger = null) {
4152
- this.api = createNabuApiClient(baseUrl, logger);
4153
- this.log = internalLogger(logger, "TOKENS");
4154
- }
4155
- get(token) {
4156
- return this.log.wrap(
4157
- "get",
4158
- token,
4159
- () => fetchTokenMetadata(this.api, token)
4160
- );
4161
- }
4162
- list(chain) {
4163
- return this.log.wrap(
4164
- "list",
4165
- chain,
4166
- () => chain === void 0 ? fetchAllTokensMetadata(this.api) : fetchTokensMetadata(this.api, chain)
4167
- );
4168
- }
4169
- };
4170
-
4171
- // src/universal/types/offer-option-address.ts
4172
- var OfferOptionAddressId = (value) => value;
4173
- var OfferOptionAddress = {
4174
- /** Maps the API DTO into the SDK offer-option-address domain model. */
4175
- fromDto: (dto) => ({
4176
- id: OfferOptionAddressId(dto.id),
4177
- offerOptionId: OfferOptionId(dto.offer_option_id),
4178
- address: EvmWalletAddress(dto.address),
4179
- protocol: dto.protocol,
4180
- createdAt: new Date(dto.created_at)
4181
- })
4182
- };
4183
- var ConnectExternalWalletParams = {
4184
- /** Maps connect-wallet params into the API DTO payload. */
4185
- toDto: (params) => ({
4186
- offer_option_id: params.offerOptionId,
4187
- wallet_address: params.walletAddress,
4188
- chain: params.chain,
4189
- signature: params.signature
4190
- })
4191
- };
4192
-
4193
- // src/universal/types/wallet-ownership-challenge.ts
4194
- var WalletOwnershipChallenge = {
4195
- /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
4196
- fromDto: (dto) => ({
4197
- message: dto.message,
4198
- expiresAt: new Date(dto.expires_at)
4199
- })
4200
- };
4201
- var CreateWalletOwnershipChallengeParams = {
4202
- /**
4203
- * Maps challenge-request params into the API DTO payload. The discriminated
4204
- * union guarantees SIWE fields are present exactly when `challengeType` is
4205
- * `siwe`, so the mapping narrows on the discriminant.
4206
- */
4207
- toDto: (params) => {
4208
- switch (params.challengeType) {
4209
- case "plain":
4210
- return {
4211
- wallet_address: params.walletAddress,
4212
- chain: params.chain,
4213
- challenge_type: "plain"
4214
- };
4215
- case "siwe":
4216
- return {
4217
- wallet_address: params.walletAddress,
4218
- chain: params.chain,
4219
- challenge_type: "siwe",
4220
- domain: params.domain,
4221
- uri: params.uri,
4222
- statement: params.statement
4223
- };
4224
- default: {
4225
- const _exhaustive = params;
4226
- return _exhaustive;
4227
- }
4228
- }
4229
- }
4230
- };
4231
-
4232
- // src/universal/api/frontline/wallet-connect.ts
4233
- async function createWalletOwnershipChallenge(api, params) {
4234
- const dto = await api.send({
4235
- method: "POST",
4236
- url: "/v1/wallet-ownership",
4237
- body: CreateWalletOwnershipChallengeParams.toDto(params),
4238
- attributes: Attributes.protected()
4239
- });
4240
- return WalletOwnershipChallenge.fromDto(dto);
4241
- }
4242
- async function connectExternalWallet(api, params) {
4243
- const dto = await api.send({
4244
- method: "POST",
4245
- url: `/v1/offers/${params.offerId}/addresses`,
4246
- body: ConnectExternalWalletParams.toDto(params),
4247
- attributes: Attributes.protected()
4248
- });
4249
- return OfferOptionAddress.fromDto(dto);
4250
- }
4251
- async function listOptionAddresses(api, offerId, offerOptionId) {
4252
- const { data } = await api.send({
4253
- method: "GET",
4254
- url: `/v1/offers/${offerId}/addresses`,
4255
- queryParams: { offer_option_id: offerOptionId },
4256
- attributes: Attributes.protected()
4257
- });
4258
- return data.map(OfferOptionAddress.fromDto);
4259
- }
4260
- async function removeOptionAddress(api, offerId, addressId) {
4261
- const dto = await api.send({
4262
- method: "DELETE",
4263
- url: `/v1/offers/${offerId}/addresses/${addressId}`,
4264
- attributes: Attributes.protected()
4265
- });
4266
- return OfferOptionAddress.fromDto(dto);
4267
- }
4268
-
4269
- // src/universal/core/wallets/wallets-namespace.ts
4270
- var WalletsNamespaceImpl = class {
4271
- constructor(ctx) {
4272
- this.ctx = ctx;
4273
- this.log = internalLogger(ctx.logger, "WALLETS");
4274
- }
4275
- async createOwnershipChallenge(params) {
4276
- return this.log.wrap("createOwnershipChallenge", params, async () => {
4277
- await this.ctx.ensureUserAuthenticated();
4278
- return createWalletOwnershipChallenge(
4279
- this.ctx.api,
4280
- params
4281
- );
4282
- });
4283
- }
4284
- async connectExternal(params) {
4285
- return this.log.wrap("connectExternal", params, async () => {
4286
- await this.ctx.ensureUserAuthenticated();
4287
- return connectExternalWallet(this.ctx.api, params);
4288
- });
4289
- }
4290
- async list(params) {
4291
- return this.log.wrap("list", params, async () => {
4292
- await this.ctx.ensureUserAuthenticated();
4293
- return listOptionAddresses(
4294
- this.ctx.api,
4295
- params.offerId,
4296
- params.offerOptionId
4297
- );
4298
- });
4299
- }
4300
- async remove(params) {
4301
- return this.log.wrap("remove", params, async () => {
4302
- await this.ctx.ensureUserAuthenticated();
4303
- return removeOptionAddress(
4304
- this.ctx.api,
4305
- params.offerId,
4306
- params.addressId
4307
- );
4308
- });
4309
- }
4310
- };
4311
-
4312
- // src/server/core/coinlist-server.ts
4313
- var ACCESS_TOKEN_EXPIRY_BUFFER = Seconds.of(60);
4314
- var CoinListServerImpl = class {
4315
- constructor(_config) {
4316
- const logger = _config.logger ?? null;
4317
- this.api = new ApiClient(
4318
- {
4319
- baseUrl: _config.baseUrl ?? PUBLIC_API_BASE_URL,
4320
- xApiVersion: API_VERSION
4321
- },
4322
- (trigger) => auth.tokenFor(trigger),
4323
- logger
4324
- );
4325
- const auth = new ServerAuthNamespaceImpl(this.api, {
4326
- ..._config,
4327
- accessTokenExpiryBufferSeconds: _config.accessTokenExpiryBufferSeconds ?? ACCESS_TOKEN_EXPIRY_BUFFER,
4328
- strict: _config.strict ?? false,
4329
- refreshes: processRefreshCoordinator,
4330
- ...systemTime
4331
- });
4332
- this.auth = auth;
4333
- const ctx = {
4334
- api: this.api,
4335
- rpc: publicClients(this.api, _config.rpc, _config.logger ?? null),
4336
- logger,
4337
- ensureUserAuthenticated: () => this.ensureAuthenticated(void 0),
4338
- ensureAuthenticated: (clientCreds) => this.ensureAuthenticated(clientCreds)
4339
- };
4340
- this.offers = new ServerOffersNamespaceImpl(ctx);
4341
- this.requirements = new ServerRequirementsNamespaceImpl(ctx);
4342
- this.wallets = new WalletsNamespaceImpl(ctx);
4343
- this.erc20 = new Erc20NamespaceImpl(ctx);
4344
- this.tokenSale = new CoinListTokenSaleNamespaceImpl(ctx);
4345
- this.superstate = new SuperstateSwapNamespaceImpl(ctx);
4346
- this.ondo = new OndoNamespaceImpl(ctx);
4347
- this.centrifuge = new CentrifugeNamespaceImpl(ctx);
4348
- this.tokens = new TokensNamespaceImpl(
4349
- _config.tokensBaseUrl ?? NABU_BASE_URL,
4350
- logger
4351
- );
4352
- }
4353
- /**
4354
- * An app-level token authenticates a request on its own; without one the
4355
- * caller needs a user session.
4356
- */
4357
- async ensureAuthenticated(clientCreds) {
4358
- if (clientCreds) return;
4359
- const token = await this.auth.getAccessToken();
4360
- if (token === null) {
4361
- throw new NotAuthenticatedError();
4362
- }
4363
- }
4364
- };
4365
- function createCoinListServer(config) {
4366
- return new CoinListServerImpl(config);
4367
- }
4368
-
4369
- // src/server/core/observability/pino-server-logger.ts
4370
- var import_pino = require("pino");
4371
-
4372
- // src/universal/core/shared/observability/pino-logger.ts
4373
- function toPinoRecord(event) {
4374
- try {
4375
- const record = {};
4376
- for (const key of ownKeys(event.fields)) {
4377
- record[key] = readProperty(event.fields, key, 0, /* @__PURE__ */ new WeakSet());
4378
- }
4379
- const cause = "cause" in event ? event.cause : void 0;
4380
- if (cause !== void 0) {
4381
- record.cause = sanitize(cause, 0, /* @__PURE__ */ new WeakSet());
4382
- }
4383
- return { ...record, scope: event.scope, ...event.bindings };
4384
- } catch (_) {
4385
- return { "log.render": "<unrenderable event>" };
4386
- }
4387
- }
4388
- var PINO_LEVEL = {
4389
- none: "silent",
4390
- error: "error",
4391
- warn: "warn",
4392
- info: "info",
4393
- debug: "debug"
4394
- };
4395
- var MAX_DEPTH = 8;
4396
- function sanitize(value, depth, seen) {
4397
- switch (typeof value) {
4398
- case "string":
4399
- case "boolean":
4400
- return value;
4401
- case "number":
4402
- return Number.isFinite(value) ? value : String(value);
4403
- case "bigint":
4404
- return value.toString();
4405
- case "undefined":
4406
- return "<undefined>";
4407
- case "function":
4408
- return "<function>";
4409
- case "symbol":
4410
- return value.toString();
4411
- case "object":
4412
- return value === null ? null : sanitizeObject(value, depth, seen);
4413
- default:
4414
- return "<unrenderable>";
4415
- }
4416
- }
4417
- function sanitizeObject(value, depth, seen) {
4418
- if (seen.has(value)) return "<circular>";
4419
- if (depth >= MAX_DEPTH) return "<max depth>";
4420
- if (value instanceof Error) return describeError(value);
4421
- if (value instanceof Date) return describeDate(value);
4422
- seen.add(value);
4423
- try {
4424
- if (Array.isArray(value)) {
4425
- return value.map(
4426
- (_item, index) => readProperty(value, String(index), depth, seen)
4427
- );
4428
- }
4429
- const out = {};
4430
- for (const key of ownKeys(value)) {
4431
- out[key] = readProperty(value, key, depth, seen);
4432
- }
4433
- return out;
4434
- } finally {
4435
- seen.delete(value);
4436
- }
4437
- }
4438
- function readProperty(owner, key, depth, seen) {
4439
- try {
4440
- return sanitize(owner[key], depth + 1, seen);
4441
- } catch (_) {
4442
- return "<unreadable>";
4443
- }
4444
- }
4445
- function ownKeys(value) {
4446
- try {
4447
- return Object.keys(value);
4448
- } catch (_) {
4449
- return [];
4450
- }
4451
- }
4452
- function describeError(error) {
4453
- return {
4454
- name: safeRead(() => error.name),
4455
- message: safeRead(() => error.message),
4456
- stack: safeRead(() => error.stack)
4457
- };
4458
- }
4459
- function describeDate(date) {
4460
- return safeRead(() => date.toISOString());
4461
- }
4462
- function safeRead(read) {
4463
- try {
4464
- const value = read();
4465
- return typeof value === "string" ? value : "<unreadable>";
4466
- } catch (_) {
4467
- return "<unreadable>";
4468
- }
4469
- }
4470
- var SDK_LOGGER_NAME = "@coinlist-co/react";
4471
- function loggerOverPino(sink, level) {
4472
- return {
4473
- level: () => level,
4474
- debug: (event) => emit(sink, "debug", event),
4475
- info: (event) => emit(sink, "info", event),
4476
- warn: (event) => emit(sink, "warn", event),
4477
- error: (event) => emit(sink, "error", event)
4478
- };
4479
- }
4480
- function emit(sink, method, event) {
4481
- try {
4482
- const value = event();
4483
- sink[method](toPinoRecord(value), value.msg);
4484
- } catch (error) {
4485
- reportRenderFailure(sink, error);
4486
- }
4487
- }
4488
- function reportRenderFailure(sink, error) {
4489
- try {
4490
- sink.error(
4491
- { "error.type": error instanceof Error ? error.name : typeof error },
4492
- "log event failed to render"
4493
- );
4494
- } catch (_) {
4495
- }
4496
- }
4497
-
4498
- // src/server/core/observability/pino-server-logger.ts
4499
- function pinoServerLogger(options) {
4500
- return loggerOverPino(
4501
- // `name` as a child binding rather than pino's `name` option: the option
4502
- // is honoured by pino's node build and silently dropped by its browser
4503
- // build, so a binding is the only spelling that identifies the SDK in
4504
- // both environments.
4505
- (0, import_pino.pino)({
4506
- level: PINO_LEVEL[options.level]
4507
- }).child({ name: SDK_LOGGER_NAME }),
4508
- options.level
4509
- );
4510
- }
4511
-
4512
- // src/server/core/server-auth-namespace.ts
4513
- function emptySessionStore() {
4514
- return { getSession: async () => null };
4515
- }
4516
- // Annotate the CommonJS export names for ESM import in node:
4517
- 0 && (module.exports = {
4518
- ServerOffersNamespaceImpl,
4519
- ServerRequirementsNamespaceImpl,
4520
- WritableSessionStoreRequiredError,
4521
- createCoinListServer,
4522
- emptySessionStore,
4523
- pinoServerLogger
4524
- });
4525
- //# sourceMappingURL=index.cjs.map