@coinlist-co/react 0.10.1 → 0.11.1-rc.209af8d

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 (38) hide show
  1. package/README.md +32 -0
  2. package/dist/chunk-3Z4PLLV7.js +2249 -0
  3. package/dist/chunk-3Z4PLLV7.js.map +1 -0
  4. package/dist/{chunk-AQVCOWOV.js → chunk-T4ANQVQA.js} +216 -317
  5. package/dist/chunk-T4ANQVQA.js.map +1 -0
  6. package/dist/chunk-YPFS2SAD.js +279 -0
  7. package/dist/chunk-YPFS2SAD.js.map +1 -0
  8. package/dist/client/index.cjs +11325 -3316
  9. package/dist/client/index.cjs.map +1 -1
  10. package/dist/client/index.d.cts +4243 -881
  11. package/dist/client/index.d.ts +4243 -881
  12. package/dist/client/index.js +9103 -2389
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/collections-B0nu_6q5.d.ts +116 -0
  15. package/dist/collections-DdLA4_GN.d.cts +116 -0
  16. package/dist/config-D0r6GyPL.d.cts +2638 -0
  17. package/dist/config-D0r6GyPL.d.ts +2638 -0
  18. package/dist/server/index.cjs +1631 -514
  19. package/dist/server/index.cjs.map +1 -1
  20. package/dist/server/index.d.cts +266 -162
  21. package/dist/server/index.d.ts +266 -162
  22. package/dist/server/index.js +235 -169
  23. package/dist/server/index.js.map +1 -1
  24. package/dist/shared/index.cjs +2235 -926
  25. package/dist/shared/index.cjs.map +1 -1
  26. package/dist/shared/index.d.cts +256 -132
  27. package/dist/shared/index.d.ts +256 -132
  28. package/dist/shared/index.js +102 -28
  29. package/package.json +12 -8
  30. package/dist/chunk-AQVCOWOV.js.map +0 -1
  31. package/dist/chunk-TBU3EBNM.js +0 -442
  32. package/dist/chunk-TBU3EBNM.js.map +0 -1
  33. package/dist/chunk-UOHD7US2.js +0 -855
  34. package/dist/chunk-UOHD7US2.js.map +0 -1
  35. package/dist/collections-Bv1Oxzu_.d.ts +0 -28
  36. package/dist/collections-DDyxbOPZ.d.cts +0 -28
  37. package/dist/requirement-oVZA1INj.d.cts +0 -1040
  38. package/dist/requirement-oVZA1INj.d.ts +0 -1040
@@ -20,8 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/server/index.ts
21
21
  var server_exports = {};
22
22
  __export(server_exports, {
23
+ ServerAuthNamespaceImpl: () => ServerAuthNamespaceImpl,
24
+ ServerOffersNamespaceImpl: () => ServerOffersNamespaceImpl,
25
+ ServerRequirementsNamespaceImpl: () => ServerRequirementsNamespaceImpl,
23
26
  WritableSessionStoreRequiredError: () => WritableSessionStoreRequiredError,
24
- createCoinListServer: () => createCoinListServer
27
+ createCoinListServer: () => createCoinListServer,
28
+ emptySessionStore: () => emptySessionStore,
29
+ pinoServerLogger: () => pinoServerLogger
25
30
  });
26
31
  module.exports = __toCommonJS(server_exports);
27
32
 
@@ -52,6 +57,8 @@ var retryAttempt = (attempt) => ({
52
57
  var renewAttempted = (value) => ({
53
58
  renewAttempted: value
54
59
  });
60
+ var requestId = (id) => ({ requestId: id });
61
+ var getRequestId = (attrs) => attrs?.requestId ?? null;
55
62
  var isProtected = (attrs) => attrs?.protected === true;
56
63
  var needUserAgent = (attrs) => attrs?.userAgent === true;
57
64
  var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
@@ -73,7 +80,9 @@ var Attributes = {
73
80
  renewAttempted,
74
81
  wasRenewAttempted,
75
82
  clientCredentials,
76
- getClientCredentials
83
+ getClientCredentials,
84
+ requestId,
85
+ getRequestId
77
86
  };
78
87
 
79
88
  // src/shared/api/http.ts
@@ -83,7 +92,24 @@ var HttpError = class extends Error {
83
92
  this.name = "HttpError";
84
93
  this.response = response;
85
94
  }
95
+ /**
96
+ * Correlates this failure with the `[HTTP]` log lines for the same request,
97
+ * which carry the method, the URL, the duration and every retry. `null` when
98
+ * the response did not come from an {@link HttpClient}.
99
+ *
100
+ * Worth quoting in a bug report: it is what makes a log excerpt readable.
101
+ */
102
+ get requestId() {
103
+ return this.response.requestId ?? null;
104
+ }
86
105
  };
106
+ function apiErrorCode(error) {
107
+ if (!(error instanceof HttpError)) return null;
108
+ const body = error.response.body;
109
+ if (typeof body !== "object" || body === null) return null;
110
+ const code = body.code;
111
+ return typeof code === "string" ? code : null;
112
+ }
87
113
  async function makeRequest(request) {
88
114
  const headers = {
89
115
  Accept: "application/json",
@@ -119,7 +145,16 @@ async function makeRequest(request) {
119
145
  };
120
146
  }
121
147
  const text = await response.text();
122
- const body = text ? JSON.parse(text) : null;
148
+ let body;
149
+ try {
150
+ body = text ? JSON.parse(text) : null;
151
+ } catch (_) {
152
+ throw new HttpError({
153
+ status: response.status,
154
+ headers: responseHeaders,
155
+ body: text
156
+ });
157
+ }
123
158
  return {
124
159
  status: response.status,
125
160
  body,
@@ -180,11 +215,185 @@ var HEADER_API_VERSION = "X-API-Version";
180
215
  var HEADER_IDEMPOTENCY_KEY = "Idempotency-Key";
181
216
  var API_VERSION = "2025-10-17";
182
217
 
218
+ // src/shared/types/errors.ts
219
+ var NotImplementedError = class extends Error {
220
+ constructor(message = "Not implemented yet") {
221
+ super(message);
222
+ this.name = "NotImplementedError";
223
+ }
224
+ };
225
+ var NotAuthenticatedError = class extends Error {
226
+ constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
227
+ super(message);
228
+ this.name = "NotAuthenticatedError";
229
+ }
230
+ };
231
+ var ValidationError = class extends Error {
232
+ constructor(message) {
233
+ super(message);
234
+ this.name = "ValidationError";
235
+ }
236
+ };
237
+ var InvariantError = class extends Error {
238
+ constructor(message) {
239
+ super(message);
240
+ this.name = "InvariantError";
241
+ }
242
+ };
243
+
244
+ // src/shared/core/observability/log-cause.ts
245
+ function classifyLogCause(error) {
246
+ if (error instanceof HttpError) {
247
+ return httpCause(error);
248
+ }
249
+ if (error instanceof ValidationError) {
250
+ return { type: "validation", message: error.message };
251
+ }
252
+ if (error instanceof InvariantError) {
253
+ return { type: "invariant", message: error.message };
254
+ }
255
+ if (error instanceof NotAuthenticatedError) {
256
+ return { type: "not-authenticated" };
257
+ }
258
+ if (error instanceof NotImplementedError) {
259
+ return { type: "not-implemented" };
260
+ }
261
+ return { type: "generic-error", name: errorName(error) };
262
+ }
263
+ function describeErrorUnredacted(error) {
264
+ if (error instanceof HttpError) {
265
+ return describeHttpErrorRedacted(error);
266
+ }
267
+ if (error instanceof Error) {
268
+ return `${error.name}: ${error.message}`;
269
+ }
270
+ return `thrown non-error: ${stringifyUnredacted(error)}`;
271
+ }
272
+ function stringifyUnredacted(value) {
273
+ if (value === void 0) return "";
274
+ try {
275
+ return JSON.stringify(
276
+ value,
277
+ (_key, item) => typeof item === "bigint" ? `${item}` : item
278
+ ) ?? String(value);
279
+ } catch (_) {
280
+ return "<unserializable>";
281
+ }
282
+ }
283
+ function describeHttpErrorRedacted(error) {
284
+ const code = apiErrorCode(error);
285
+ const status = error.response.status;
286
+ return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
287
+ }
288
+ function errorName(error) {
289
+ return error instanceof Error ? error.name : `non-error ${typeof error}`;
290
+ }
291
+ function httpCause(error) {
292
+ return {
293
+ type: "http",
294
+ requestId: error.requestId,
295
+ status: error.response.status,
296
+ code: apiErrorCode(error),
297
+ eventId: apiErrorEventId(error)
298
+ };
299
+ }
300
+ function apiErrorEventId(error) {
301
+ const body = error.response.body;
302
+ if (typeof body !== "object" || body === null) return null;
303
+ const eventId = body.event_id;
304
+ return typeof eventId === "string" ? eventId : null;
305
+ }
306
+
307
+ // src/shared/core/observability/internal-logger.ts
308
+ function internalLogger(logger, scope) {
309
+ return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
310
+ }
311
+ var LEVEL_RANK = {
312
+ none: 0,
313
+ error: 1,
314
+ warn: 2,
315
+ info: 3,
316
+ debug: 4
317
+ };
318
+ function scopedLogger(logger, scope, bindings) {
319
+ const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
320
+ const safe = (event) => ({
321
+ msg: event.msg,
322
+ scope,
323
+ bindings,
324
+ fields: event.fields ?? {},
325
+ ...event.cause === void 0 ? {} : { cause: event.cause }
326
+ });
327
+ const unredacted = (event) => ({
328
+ msg: event.msg,
329
+ scope,
330
+ bindings,
331
+ fields: event.fields ?? {}
332
+ });
333
+ const self = {
334
+ child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
335
+ debug: (event) => {
336
+ if (admits("debug")) logger.debug(() => unredacted(event()));
337
+ },
338
+ info: (event) => {
339
+ if (admits("info")) logger.info(() => safe(event()));
340
+ },
341
+ warn: (event) => {
342
+ if (admits("warn")) logger.warn(() => safe(event()));
343
+ },
344
+ error: (event) => {
345
+ if (admits("error")) logger.error(() => safe(event()));
346
+ },
347
+ failure: (event, error) => {
348
+ if (admits("debug"))
349
+ logger.debug(() => unredacted(verbatim(event(), error)));
350
+ if (admits("error")) logger.error(() => safe(classified(event(), error)));
351
+ },
352
+ warning: (event, error) => {
353
+ if (admits("debug"))
354
+ logger.debug(() => unredacted(verbatim(event(), error)));
355
+ if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
356
+ },
357
+ wrap: async (op, params, run) => {
358
+ const opLog = self.child({ op });
359
+ opLog.debug(() => ({ msg: "call", fields: { params } }));
360
+ try {
361
+ return await run();
362
+ } catch (error) {
363
+ opLog.failure(() => ({ msg: "call failed" }), error);
364
+ throw error;
365
+ }
366
+ }
367
+ };
368
+ return self;
369
+ }
370
+ function verbatim(event, error) {
371
+ return {
372
+ msg: event.msg,
373
+ fields: { ...event.fields, error: describeErrorUnredacted(error) }
374
+ };
375
+ }
376
+ function classified(event, error) {
377
+ return { ...event, cause: event.cause ?? classifyLogCause(error) };
378
+ }
379
+ var noopInternalLogger = {
380
+ child: () => noopInternalLogger,
381
+ debug: () => void 0,
382
+ info: () => void 0,
383
+ warn: () => void 0,
384
+ error: () => void 0,
385
+ failure: () => void 0,
386
+ warning: () => void 0,
387
+ wrap: (_op, _params, run) => run()
388
+ };
389
+
183
390
  // src/shared/api/http-client.ts
184
391
  var HttpClient = class {
185
- constructor(config, middleware = {}) {
392
+ constructor(config, middleware = {}, logger = null, options = {}) {
186
393
  this.config = config;
187
394
  this.middleware = middleware;
395
+ this.log = internalLogger(logger, "HTTP");
396
+ this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
188
397
  }
189
398
  async send(request) {
190
399
  return this.runRequestWithAfterMiddleware(request);
@@ -215,12 +424,18 @@ var HttpClient = class {
215
424
  const url = this.resolveUrl(request.url);
216
425
  const headers = {
217
426
  ...request.headers ?? {},
218
- [HEADER_API_VERSION]: this.config.xApiVersion
427
+ ...this.config.xApiVersion !== void 0 ? { [HEADER_API_VERSION]: this.config.xApiVersion } : {}
219
428
  };
220
429
  return {
221
430
  ...request,
222
431
  url,
223
- headers
432
+ headers,
433
+ // Only when absent: a retry or a post-renewal re-send arrives with the
434
+ // first attempt's id already on it, and keeping it is the whole point.
435
+ attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
436
+ request.attributes ?? Attributes.empty,
437
+ Attributes.requestId(this.makeRequestId())
438
+ ) : request.attributes
224
439
  };
225
440
  }
226
441
  /**
@@ -244,10 +459,89 @@ var HttpClient = class {
244
459
  }
245
460
  return request;
246
461
  }
247
- executeRequest(request) {
248
- return makeRequest(request);
462
+ /**
463
+ * One physical attempt, logged as one line.
464
+ *
465
+ * A non-2xx is a `warn` rather than an `error` because the wire does not
466
+ * know whether it is a failure: the retry middleware may turn a 503 into a
467
+ * success, and the token registry reads a 404 as "not listed". The namespace
468
+ * above decides, and logs the `error` when it does.
469
+ */
470
+ async executeRequest(request) {
471
+ const requestId2 = Attributes.getRequestId(request.attributes);
472
+ const log = requestId2 === null ? this.log : this.log.child({ requestId: requestId2 });
473
+ const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
474
+ const startedAt = Date.now();
475
+ log.debug(() => ({
476
+ msg: "request sent",
477
+ fields: describeRequestUnredacted(request)
478
+ }));
479
+ try {
480
+ const response = await makeRequest(request);
481
+ const elapsed = Date.now() - startedAt;
482
+ const outcome = () => ({
483
+ msg: "request completed",
484
+ fields: {
485
+ ...identifyRequest(request),
486
+ "http.response.status_code": response.status,
487
+ duration_ms: elapsed,
488
+ attempt
489
+ }
490
+ });
491
+ if (response.status >= 200 && response.status < 300) {
492
+ log.info(outcome);
493
+ } else {
494
+ log.warn(outcome);
495
+ }
496
+ log.debug(() => ({
497
+ msg: "response received",
498
+ fields: { body: response.body }
499
+ }));
500
+ return requestId2 === null ? response : { ...response, requestId: requestId2 };
501
+ } catch (error) {
502
+ const elapsed = Date.now() - startedAt;
503
+ log.warning(
504
+ () => ({
505
+ msg: "request threw",
506
+ fields: {
507
+ ...identifyRequest(request),
508
+ duration_ms: elapsed,
509
+ attempt
510
+ }
511
+ }),
512
+ error
513
+ );
514
+ throw error;
515
+ }
249
516
  }
250
517
  };
518
+ function identifyRequest(request) {
519
+ const { host, path } = splitUrl(request.url);
520
+ return {
521
+ "http.request.method": request.method,
522
+ "server.address": host,
523
+ "url.path": path
524
+ };
525
+ }
526
+ function splitUrl(url) {
527
+ try {
528
+ const parsed = new URL(url);
529
+ return { host: parsed.host, path: parsed.pathname };
530
+ } catch (_) {
531
+ return { host: null, path: url };
532
+ }
533
+ }
534
+ function defaultMakeRequestId() {
535
+ return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
536
+ }
537
+ function describeRequestUnredacted(request) {
538
+ return {
539
+ "http.request.method": request.method,
540
+ "url.full": buildUrlWithQueryParams(request.url, request.queryParams),
541
+ headers: request.headers,
542
+ ...request.method === "POST" ? { body: request.body } : {}
543
+ };
544
+ }
251
545
 
252
546
  // src/shared/api/middleware/attach-session-middleware.ts
253
547
  function attachSessionMiddleware(fetchAccessToken) {
@@ -275,7 +569,7 @@ function attachSessionMiddleware(fetchAccessToken) {
275
569
  };
276
570
  }
277
571
 
278
- // src/shared/utils.ts
572
+ // src/shared/core/utils/crypto.ts
279
573
  function getUUIDv4() {
280
574
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
281
575
  return crypto.randomUUID();
@@ -378,18 +672,22 @@ function renewSessionMiddleware(fetchAccessToken) {
378
672
 
379
673
  // src/shared/api/authenticated-api-client.ts
380
674
  var AuthenticatedApiClient = class {
381
- constructor(config, fetchAccessToken, additionalBeforeRequest = []) {
382
- this.httpClient = new HttpClient(config, {
383
- beforeRequest: [
384
- attachSessionMiddleware(fetchAccessToken),
385
- ...additionalBeforeRequest,
386
- idempotencyKeyMiddleware
387
- ],
388
- afterRequest: [
389
- renewSessionMiddleware(fetchAccessToken),
390
- requestRetryMiddleware
391
- ]
392
- });
675
+ constructor(config, fetchAccessToken, additionalBeforeRequest = [], logger = null) {
676
+ this.httpClient = new HttpClient(
677
+ config,
678
+ {
679
+ beforeRequest: [
680
+ attachSessionMiddleware(fetchAccessToken),
681
+ ...additionalBeforeRequest,
682
+ idempotencyKeyMiddleware
683
+ ],
684
+ afterRequest: [
685
+ renewSessionMiddleware(fetchAccessToken),
686
+ requestRetryMiddleware
687
+ ]
688
+ },
689
+ logger
690
+ );
393
691
  }
394
692
  async send(request) {
395
693
  const response = await this.httpClient.send(request);
@@ -401,10 +699,15 @@ var AuthenticatedApiClient = class {
401
699
  }
402
700
  };
403
701
 
404
- // src/server/api/api.server.ts
405
- var Api = class {
406
- constructor(config, fetchAccessToken) {
407
- this.client = new AuthenticatedApiClient(config, fetchAccessToken);
702
+ // src/server/core/api/api-client.ts
703
+ var ApiClient = class {
704
+ constructor(config, fetchAccessToken, logger = null) {
705
+ this.client = new AuthenticatedApiClient(
706
+ config,
707
+ fetchAccessToken,
708
+ [],
709
+ logger
710
+ );
408
711
  }
409
712
  async send(request) {
410
713
  return this.client.send(request);
@@ -419,48 +722,168 @@ var WritableSessionStoreRequiredError = class extends Error {
419
722
  }
420
723
  };
421
724
 
422
- // src/shared/types/document-submission.ts
423
- var DocumentSubmission = {
424
- fromDto: (dto) => ({
425
- status: dto.status,
426
- formType: dto.form_type
427
- })
725
+ // src/shared/types/oauth-session.ts
726
+ var ClientCredentialsOAuth = (value) => value;
727
+ var OAuthRefreshToken = (value) => value;
728
+ var OAuthSession = {
729
+ fromDto: (dto) => {
730
+ const expiresAt = new Date(Date.now() + dto.expires_in * 1e3);
731
+ return {
732
+ accessToken: {
733
+ value: dto.access_token,
734
+ expiresAt
735
+ },
736
+ ...dto.refresh_token != null && dto.refresh_token !== "" ? { refreshToken: OAuthRefreshToken(dto.refresh_token) } : void 0
737
+ };
738
+ }
428
739
  };
429
740
 
430
- // src/shared/api/frontline/documents.ts
431
- async function submitDocument(api, documentType, fields) {
432
- const dto = await api.send({
433
- method: "POST",
434
- url: `/v1/documents/${documentType}/submission`,
435
- body: fields,
436
- attributes: Attributes.protected()
437
- });
438
- return DocumentSubmission.fromDto(dto);
741
+ // src/server/core/server-auth-namespace.ts
742
+ function emptySessionStore() {
743
+ return { getSession: async () => null };
439
744
  }
440
-
441
- // src/shared/types/kyc.ts
442
- var KycToken = {
443
- fromDto: (dto) => ({
444
- token: dto.token
445
- })
745
+ var ServerAuthNamespaceImpl = class {
746
+ constructor(api, config) {
747
+ this.api = api;
748
+ this.config = config;
749
+ this.log = internalLogger(config.logger ?? null, "AUTH");
750
+ }
751
+ async completeOAuth(params) {
752
+ return this.log.wrap("completeOAuth", void 0, async () => {
753
+ const setSession = this.writableSessionStore();
754
+ const sessionDto = await this.api.send({
755
+ method: "POST",
756
+ url: `/oauth/token`,
757
+ body: {
758
+ grant_type: "authorization_code",
759
+ code: params.code,
760
+ redirect_uri: this.config.redirectUri,
761
+ client_id: this.config.clientId,
762
+ client_secret: this.config.clientSecret,
763
+ code_verifier: params.codeVerifier
764
+ }
765
+ });
766
+ const session = OAuthSession.fromDto(sessionDto);
767
+ await setSession(session);
768
+ return session;
769
+ });
770
+ }
771
+ async getAccessToken() {
772
+ return this.log.wrap(
773
+ "getAccessToken",
774
+ void 0,
775
+ () => this.readAccessToken()
776
+ );
777
+ }
778
+ async readAccessToken() {
779
+ const sessionStore = this.config.sessionStore;
780
+ const session = await sessionStore.getSession();
781
+ if (session == null) return null;
782
+ const now = Date.now();
783
+ const expiresAt = session.accessToken.expiresAt.getTime();
784
+ const bufferMs = this.config.accessTokenExpiryBufferSeconds * 1e3;
785
+ if (expiresAt > now + bufferMs) {
786
+ return session.accessToken;
787
+ }
788
+ const setSession = sessionStore.setSession?.bind(sessionStore);
789
+ if (!setSession) {
790
+ this.log.child({ op: "getAccessToken" }).warn(() => ({
791
+ msg: "serving an expired token: the session store is read-only, so it cannot be refreshed"
792
+ }));
793
+ return session.accessToken;
794
+ }
795
+ return this.refreshSession(session.refreshToken, setSession);
796
+ }
797
+ async refreshSession(refreshToken, setSession) {
798
+ const log = this.log.child({ op: "refresh" });
799
+ if (!refreshToken) {
800
+ log.warn(() => ({
801
+ msg: "clearing the session: it carries no refresh token"
802
+ }));
803
+ await setSession(null);
804
+ return null;
805
+ }
806
+ try {
807
+ const sessionDto = await this.api.send({
808
+ method: "POST",
809
+ url: `/oauth/token`,
810
+ body: {
811
+ grant_type: "refresh_token",
812
+ refresh_token: refreshToken,
813
+ client_id: this.config.clientId,
814
+ client_secret: this.config.clientSecret
815
+ }
816
+ });
817
+ const newSession = OAuthSession.fromDto(sessionDto);
818
+ await setSession(newSession);
819
+ log.info(() => ({ msg: "session renewed" }));
820
+ return newSession.accessToken;
821
+ } catch (error) {
822
+ log.failure(
823
+ () => ({ msg: "refresh failed; clearing the session" }),
824
+ error
825
+ );
826
+ await setSession(null);
827
+ return null;
828
+ }
829
+ }
830
+ async clientCredentials() {
831
+ return this.log.wrap("clientCredentials", void 0, async () => {
832
+ const sessionDto = await this.api.send({
833
+ method: "POST",
834
+ url: `/oauth/token`,
835
+ body: {
836
+ grant_type: "client_credentials",
837
+ client_id: this.config.clientId,
838
+ client_secret: this.config.clientSecret
839
+ }
840
+ });
841
+ const session = OAuthSession.fromDto(sessionDto);
842
+ return ClientCredentialsOAuth(session.accessToken);
843
+ });
844
+ }
845
+ async logout() {
846
+ return this.log.wrap("logout", void 0, () => this.revokeAndClear());
847
+ }
848
+ async revokeAndClear() {
849
+ const setSession = this.writableSessionStore();
850
+ const session = await this.config.sessionStore.getSession();
851
+ if (session == null) return;
852
+ try {
853
+ await this.api.send({
854
+ method: "POST",
855
+ url: `/oauth/revoke`,
856
+ body: {
857
+ token: session.accessToken.value,
858
+ client_id: this.config.clientId,
859
+ client_secret: this.config.clientSecret
860
+ }
861
+ });
862
+ } catch (err) {
863
+ if (!(err instanceof HttpError) || this.config.strict) {
864
+ throw err;
865
+ }
866
+ this.log.child({ op: "logout" }).warn(() => ({
867
+ msg: "the token was not revoked upstream; the local session is cleared regardless"
868
+ }));
869
+ }
870
+ await setSession(null);
871
+ }
872
+ /**
873
+ * Returns the store's `setSession`, or throws — the guard every
874
+ * session-writing operation shares.
875
+ */
876
+ writableSessionStore() {
877
+ const sessionStore = this.config.sessionStore;
878
+ const setSession = sessionStore.setSession?.bind(sessionStore);
879
+ if (!setSession) {
880
+ throw new WritableSessionStoreRequiredError();
881
+ }
882
+ return setSession;
883
+ }
446
884
  };
447
885
 
448
- // src/shared/api/frontline/kyc.ts
449
- async function createKycToken(api, levelName, reset) {
450
- const dto = await api.send({
451
- method: "POST",
452
- url: "/v1/kyc-token",
453
- body: {
454
- ...levelName === void 0 ? {} : { level_name: levelName },
455
- ...reset === void 0 ? {} : { reset }
456
- },
457
- attributes: Attributes.protected()
458
- });
459
- return KycToken.fromDto(dto);
460
- }
461
-
462
886
  // src/shared/api/pagination.ts
463
- var Cursor = (value) => value;
464
887
  async function fetchAllPages(fetchPage, baseParams) {
465
888
  const items = [];
466
889
  let cursor = null;
@@ -475,79 +898,158 @@ async function fetchAllPages(fetchPage, baseParams) {
475
898
  } while (cursor);
476
899
  return items;
477
900
  }
478
- var PaginatedResponse = {
479
- fromDto: (dto, itemMapper) => ({
480
- data: dto.data.map(itemMapper),
481
- startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
482
- startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
483
- })
901
+
902
+ // src/shared/types/blockchain/core.ts
903
+ var ETHEREUM_CHAINS = {
904
+ ethereum_mainnet: true,
905
+ ethereum_sepolia: true
484
906
  };
485
- var PaginationParams = {
486
- toQueryParams: (params) => {
487
- const queryParams = {};
488
- if (params.after) {
489
- queryParams.starting_after = params.after;
490
- }
491
- if (params.before) {
492
- queryParams.starting_before = params.before;
493
- }
494
- if (params.limit) {
495
- queryParams.limit = params.limit;
496
- }
497
- return queryParams;
907
+ var EthereumChain = (value) => {
908
+ if (!Object.keys(ETHEREUM_CHAINS).includes(value)) {
909
+ throw new ValidationError(`Unsupported Ethereum chain: "${value}"`);
498
910
  }
911
+ return value;
499
912
  };
500
-
501
- // src/shared/types/offer.ts
502
- var OfferId = (value) => value;
503
- var OfferSlug = (value) => value;
504
- var Offer = {
505
- fromDto: (dto) => ({
506
- id: OfferId(dto.id),
507
- slug: OfferSlug(dto.slug),
508
- type: dto.type,
509
- tagline: dto.tagline,
510
- bannerUrl: dto.banner_url,
511
- logoUrl: dto.logo_url,
512
- startsAt: new Date(dto.starts_at),
513
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null
514
- })
913
+ var SOLANA_CHAINS = {
914
+ solana_mainnet: true,
915
+ solana_devnet: true
515
916
  };
516
-
517
- // src/shared/types/asset.ts
518
- var AssetId = (value) => value;
519
- var AssetCode = (value) => value;
520
- var Asset = {
521
- fromDto: (dto) => ({
522
- id: AssetId(dto.id),
523
- code: AssetCode(dto.code),
524
- name: dto.name,
525
- fractionalDigits: dto.fractional_digits
526
- })
917
+ var Chain = (value) => {
918
+ if (!Object.keys(ETHEREUM_CHAINS).includes(value) && !Object.keys(SOLANA_CHAINS).includes(value)) {
919
+ throw new ValidationError(`Unsupported chain: "${value}"`);
920
+ }
921
+ return value;
527
922
  };
528
-
529
- // src/shared/types/offer-detail.ts
530
- var OfferOptionId = (value) => value;
531
- var OfferOptionSlug = (value) => value;
923
+ var EvmWalletAddress = (value) => value;
924
+ var EvmContractAddress = (value) => value;
925
+ var HexEncodedTransactionData = (value) => value;
926
+ var MAX_ASSET_DECIMALS = 77;
927
+ var AssetDecimals = (value) => {
928
+ if (!Number.isInteger(value)) {
929
+ throw new ValidationError(`Asset decimals must be an integer: ${value}`);
930
+ }
931
+ if (value < 0 || value > MAX_ASSET_DECIMALS) {
932
+ throw new ValidationError(
933
+ `Asset decimals out of range [0, ${MAX_ASSET_DECIMALS}]: ${value}`
934
+ );
935
+ }
936
+ return value;
937
+ };
938
+ var STABLE_DECIMALS = AssetDecimals(6);
939
+ var DecimalString = (value) => value;
940
+ var MAX_UINT_256 = 2n ** 256n - 1n;
941
+ var assertUint256 = (value) => {
942
+ if (isUint256(value)) return value;
943
+ throw new InvariantError(`Value out of uint256 bounds: ${value}`);
944
+ };
945
+ var parseUint256 = (value, label) => {
946
+ if (isUint256(value)) return value;
947
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
948
+ };
949
+ var isUint256 = (value) => value >= 0n && value <= MAX_UINT_256;
950
+ var BlockchainAmount = Object.assign(
951
+ (value) => value,
952
+ {
953
+ add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
954
+ sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
955
+ }
956
+ );
957
+ function combineAmounts(a, b, op) {
958
+ if (a.decimals !== b.decimals) {
959
+ throw new InvariantError(
960
+ `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
961
+ );
962
+ }
963
+ const raw = op(a.raw, b.raw);
964
+ if (raw < 0n || raw > MAX_UINT_256) {
965
+ throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
966
+ }
967
+ return BlockchainAmount({ raw, decimals: a.decimals });
968
+ }
969
+ var AssetSymbol = (value) => value;
970
+
971
+ // src/shared/types/offer.ts
972
+ var OfferId = (value) => value;
973
+ var OfferSlug = (value) => value;
974
+ var Offer = {
975
+ fromDto: (dto) => {
976
+ if (!Array.isArray(dto.tokens)) {
977
+ throw new ValidationError(
978
+ `Offer.tokens: expected an array, got ${typeof dto.tokens}`
979
+ );
980
+ }
981
+ return {
982
+ id: OfferId(dto.id),
983
+ slug: OfferSlug(dto.slug),
984
+ type: dto.type,
985
+ tagline: dto.tagline,
986
+ bannerUrl: dto.banner_url,
987
+ logoUrl: dto.logo_url,
988
+ startsAt: new Date(dto.starts_at),
989
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
990
+ tokens: dto.tokens.map(OfferToken.fromDto)
991
+ };
992
+ }
993
+ };
994
+ var OfferToken = {
995
+ fromDto: (dto) => ({
996
+ role: dto.role,
997
+ chain: Chain(dto.chain),
998
+ address: EvmContractAddress(dto.address)
999
+ })
1000
+ };
1001
+
1002
+ // src/shared/types/asset.ts
1003
+ var AssetId = (value) => value;
1004
+ var AssetCode = (value) => value;
1005
+ var Asset = {
1006
+ fromDto: (dto) => ({
1007
+ id: AssetId(dto.id),
1008
+ code: AssetCode(dto.code),
1009
+ name: dto.name,
1010
+ fractionalDigits: dto.fractional_digits
1011
+ })
1012
+ };
1013
+
1014
+ // src/shared/types/offer-detail.ts
1015
+ var OfferOptionId = (value) => value;
1016
+ var OfferOptionSlug = (value) => value;
532
1017
  var OfferDetail = {
533
1018
  fromDto: (dto) => {
534
1019
  if (!Array.isArray(dto.funding_assets)) {
535
- throw new Error(`funding_assets must be an array`);
1020
+ throw new ValidationError(
1021
+ `OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
1022
+ );
536
1023
  }
537
1024
  if (!Array.isArray(dto.options)) {
538
- throw new Error(`options must be an array`);
1025
+ throw new ValidationError(
1026
+ `OfferDetail.options: expected an array, got ${typeof dto.options}`
1027
+ );
539
1028
  }
540
1029
  if (!Array.isArray(dto.terms)) {
541
- throw new Error(`terms must be an array`);
1030
+ throw new ValidationError(
1031
+ `OfferDetail.terms: expected an array, got ${typeof dto.terms}`
1032
+ );
542
1033
  }
543
1034
  if (!Array.isArray(dto.links)) {
544
- throw new Error(`links must be an array`);
1035
+ throw new ValidationError(
1036
+ `OfferDetail.links: expected an array, got ${typeof dto.links}`
1037
+ );
545
1038
  }
546
1039
  if (!Array.isArray(dto.faqs)) {
547
- throw new Error(`faqs must be an array`);
1040
+ throw new ValidationError(
1041
+ `OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
1042
+ );
548
1043
  }
549
1044
  if (!Array.isArray(dto.milestones)) {
550
- throw new Error(`milestones must be an array`);
1045
+ throw new ValidationError(
1046
+ `OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
1047
+ );
1048
+ }
1049
+ if (!Array.isArray(dto.tokens)) {
1050
+ throw new ValidationError(
1051
+ `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
1052
+ );
551
1053
  }
552
1054
  return {
553
1055
  id: OfferId(dto.id),
@@ -556,6 +1058,7 @@ var OfferDetail = {
556
1058
  name: dto.name,
557
1059
  asset: Asset.fromDto(dto.asset),
558
1060
  fundingAssets: dto.funding_assets.map(Asset.fromDto),
1061
+ tokens: dto.tokens.map(OfferToken.fromDto),
559
1062
  about: notBlankStringOrNull(dto.about),
560
1063
  tagline: dto.tagline,
561
1064
  bannerUrl: dto.banner_url,
@@ -609,6 +1112,31 @@ var Milestone = {
609
1112
  })
610
1113
  };
611
1114
 
1115
+ // src/shared/types/pagination.ts
1116
+ var Cursor = (value) => value;
1117
+ var PaginatedResponse = {
1118
+ fromDto: (dto, itemMapper) => ({
1119
+ data: dto.data.map(itemMapper),
1120
+ startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
1121
+ startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
1122
+ })
1123
+ };
1124
+ var PaginationParams = {
1125
+ toQueryParams: (params) => {
1126
+ const queryParams = {};
1127
+ if (params.after) {
1128
+ queryParams.starting_after = params.after;
1129
+ }
1130
+ if (params.before) {
1131
+ queryParams.starting_before = params.before;
1132
+ }
1133
+ if (params.limit) {
1134
+ queryParams.limit = params.limit;
1135
+ }
1136
+ return queryParams;
1137
+ }
1138
+ };
1139
+
612
1140
  // src/shared/api/frontline/offers.ts
613
1141
  async function fetchOffers(api, clientCreds) {
614
1142
  return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));
@@ -638,44 +1166,32 @@ async function fetchOfferDetails(api, id, clientCreds) {
638
1166
  return OfferDetail.fromDto(dto);
639
1167
  }
640
1168
 
641
- // src/shared/types/pii.ts
642
- var Iso2CountryCode = (value) => value;
643
- var PiiJurisdiction = {
644
- fromDto: (dto) => ({
645
- iso2: Iso2CountryCode(dto.iso_2),
646
- name: dto.name
647
- })
648
- };
649
- var PiiAddress = {
650
- fromDto: (dto) => ({
651
- street: dto.street,
652
- city: dto.city,
653
- state: dto.state,
654
- postalCode: dto.postal_code,
655
- country: dto.country
656
- })
657
- };
658
- var Pii = {
659
- fromDto: (dto) => ({
660
- kind: dto.kind,
661
- fullLegalName: dto.full_legal_name,
662
- dateOfBirth: dto.date_of_birth,
663
- jurisdiction: dto.jurisdiction ? PiiJurisdiction.fromDto(dto.jurisdiction) : null,
664
- taxId: dto.tax_id,
665
- permanentAddress: PiiAddress.fromDto(dto.permanent_address)
666
- })
1169
+ // src/server/core/server-offers-namespace.ts
1170
+ var ServerOffersNamespaceImpl = class {
1171
+ constructor(ctx) {
1172
+ this.ctx = ctx;
1173
+ this.log = internalLogger(ctx.logger, "OFFERS");
1174
+ }
1175
+ async list(clientCreds) {
1176
+ return this.log.wrap("list", clientCreds, async () => {
1177
+ await this.ctx.ensureAuthenticated(clientCreds);
1178
+ return fetchOffers(this.ctx.api, clientCreds);
1179
+ });
1180
+ }
1181
+ async listPage(params, clientCreds) {
1182
+ return this.log.wrap("listPage", { params, clientCreds }, async () => {
1183
+ await this.ctx.ensureAuthenticated(clientCreds);
1184
+ return fetchOffersPage(this.ctx.api, params, clientCreds);
1185
+ });
1186
+ }
1187
+ async get(id, clientCreds) {
1188
+ return this.log.wrap("get", { id, clientCreds }, async () => {
1189
+ await this.ctx.ensureAuthenticated(clientCreds);
1190
+ return fetchOfferDetails(this.ctx.api, id, clientCreds);
1191
+ });
1192
+ }
667
1193
  };
668
1194
 
669
- // src/shared/api/frontline/pii.ts
670
- async function fetchPii(api) {
671
- const dto = await api.send({
672
- method: "GET",
673
- url: "/v1/pii",
674
- attributes: Attributes.protected()
675
- });
676
- return Pii.fromDto(dto);
677
- }
678
-
679
1195
  // src/shared/types/requirement.ts
680
1196
  var RequirementId = (value) => value;
681
1197
  var Requirement = {
@@ -723,138 +1239,156 @@ async function fetchRequirementStatuses(api, offerId) {
723
1239
  return RequirementStatusInfo.fromStatusesDto(response);
724
1240
  }
725
1241
 
726
- // src/shared/types/blockchain/core.ts
727
- var EvmWalletAddress = (value) => value;
728
- var EvmContractAddress = (value) => value;
729
- var HexEncodedTransactionData = (value) => value;
730
- var AssetDecimals = (value) => value;
731
- var MAX_UINT_256 = 2n ** 256n - 1n;
732
- var assertUint256 = (value) => {
733
- if (value < 0n || value > MAX_UINT_256) {
734
- throw new Error(`Value out of uint256 bounds: ${value}`);
735
- }
736
- return value;
737
- };
738
- var BlockchainAmount = Object.assign(
739
- (value) => value,
740
- {
741
- add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
742
- sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
743
- }
744
- );
745
- function combineAmounts(a, b, op) {
746
- if (a.decimals !== b.decimals) {
747
- throw new Error(
748
- `Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
749
- );
750
- }
751
- const raw = op(a.raw, b.raw);
752
- if (raw < 0n || raw > MAX_UINT_256) {
753
- throw new Error(`BlockchainAmount out of uint256 bounds: ${raw}`);
754
- }
755
- return BlockchainAmount({ raw, decimals: a.decimals });
756
- }
757
- var AssetSymbol = (value) => value;
758
-
759
- // src/shared/types/offer-option-address.ts
760
- var OfferOptionAddressId = (value) => value;
761
- var OfferOptionAddress = {
762
- /** Maps the API DTO into the SDK offer-option-address domain model. */
1242
+ // src/shared/types/document-submission.ts
1243
+ var DocumentSubmission = {
763
1244
  fromDto: (dto) => ({
764
- id: OfferOptionAddressId(dto.id),
765
- offerOptionId: OfferOptionId(dto.offer_option_id),
766
- address: EvmWalletAddress(dto.address),
767
- protocol: dto.protocol,
768
- createdAt: new Date(dto.created_at)
769
- })
770
- };
771
- var ConnectExternalWalletParams = {
772
- /** Maps connect-wallet params into the API DTO payload. */
773
- toDto: (params) => ({
774
- offer_option_id: params.offerOptionId,
775
- wallet_address: params.walletAddress,
776
- chain: params.chain,
777
- signature: params.signature
1245
+ status: dto.status,
1246
+ formType: dto.form_type
778
1247
  })
779
1248
  };
780
1249
 
781
- // src/shared/types/wallet-ownership-challenge.ts
782
- var WalletOwnershipChallenge = {
783
- /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
1250
+ // src/shared/api/frontline/documents.ts
1251
+ async function submitDocument(api, documentType, fields) {
1252
+ const dto = await api.send({
1253
+ method: "POST",
1254
+ url: `/v1/documents/${documentType}/submission`,
1255
+ body: fields,
1256
+ attributes: Attributes.protected()
1257
+ });
1258
+ return DocumentSubmission.fromDto(dto);
1259
+ }
1260
+
1261
+ // src/shared/types/kyc.ts
1262
+ var KycToken = {
784
1263
  fromDto: (dto) => ({
785
- message: dto.message,
786
- expiresAt: new Date(dto.expires_at)
1264
+ token: dto.token
787
1265
  })
788
1266
  };
789
- var CreateWalletOwnershipChallengeParams = {
790
- /**
791
- * Maps challenge-request params into the API DTO payload. The discriminated
792
- * union guarantees SIWE fields are present exactly when `challengeType` is
793
- * `siwe`, so the mapping narrows on the discriminant.
794
- */
795
- toDto: (params) => {
796
- switch (params.challengeType) {
797
- case "plain":
798
- return {
799
- wallet_address: params.walletAddress,
800
- chain: params.chain,
801
- challenge_type: "plain"
802
- };
803
- case "siwe":
804
- return {
805
- wallet_address: params.walletAddress,
806
- chain: params.chain,
807
- challenge_type: "siwe",
808
- domain: params.domain,
809
- uri: params.uri,
810
- statement: params.statement
811
- };
812
- default: {
813
- const _exhaustive = params;
814
- return _exhaustive;
815
- }
816
- }
817
- }
818
- };
819
1267
 
820
- // src/shared/api/frontline/wallet-connect.ts
821
- async function createWalletOwnershipChallenge(api, params) {
1268
+ // src/shared/api/frontline/kyc.ts
1269
+ async function createKycToken(api, levelName, reset) {
822
1270
  const dto = await api.send({
823
1271
  method: "POST",
824
- url: "/v1/wallet-ownership",
825
- body: CreateWalletOwnershipChallengeParams.toDto(params),
1272
+ url: "/v1/kyc-token",
1273
+ body: {
1274
+ ...levelName === void 0 ? {} : { level_name: levelName },
1275
+ ...reset === void 0 ? {} : { reset }
1276
+ },
826
1277
  attributes: Attributes.protected()
827
1278
  });
828
- return WalletOwnershipChallenge.fromDto(dto);
1279
+ return KycToken.fromDto(dto);
829
1280
  }
830
- async function connectExternalWallet(api, offerId, params) {
1281
+
1282
+ // src/shared/types/pii.ts
1283
+ var Iso2CountryCode = (value) => value;
1284
+ var PiiJurisdiction = {
1285
+ fromDto: (dto) => ({
1286
+ iso2: Iso2CountryCode(dto.iso_2),
1287
+ name: dto.name
1288
+ })
1289
+ };
1290
+ var PiiAddress = {
1291
+ fromDto: (dto) => ({
1292
+ street: dto.street,
1293
+ city: dto.city,
1294
+ state: dto.state,
1295
+ postalCode: dto.postal_code,
1296
+ country: dto.country
1297
+ })
1298
+ };
1299
+ var Pii = {
1300
+ fromDto: (dto) => ({
1301
+ kind: dto.kind,
1302
+ fullLegalName: dto.full_legal_name,
1303
+ dateOfBirth: dto.date_of_birth,
1304
+ jurisdiction: dto.jurisdiction ? PiiJurisdiction.fromDto(dto.jurisdiction) : null,
1305
+ taxId: dto.tax_id,
1306
+ permanentAddress: PiiAddress.fromDto(dto.permanent_address)
1307
+ })
1308
+ };
1309
+
1310
+ // src/shared/api/frontline/pii.ts
1311
+ async function fetchPii(api) {
831
1312
  const dto = await api.send({
832
- method: "POST",
833
- url: `/v1/offers/${offerId}/addresses`,
834
- body: ConnectExternalWalletParams.toDto(params),
835
- attributes: Attributes.protected()
836
- });
837
- return OfferOptionAddress.fromDto(dto);
838
- }
839
- async function listOptionAddresses(api, offerId, offerOptionId) {
840
- const { data } = await api.send({
841
1313
  method: "GET",
842
- url: `/v1/offers/${offerId}/addresses`,
843
- queryParams: { offer_option_id: offerOptionId },
844
- attributes: Attributes.protected()
845
- });
846
- return data.map(OfferOptionAddress.fromDto);
847
- }
848
- async function removeOptionAddress(api, offerId, addressId) {
849
- const dto = await api.send({
850
- method: "DELETE",
851
- url: `/v1/offers/${offerId}/addresses/${addressId}`,
1314
+ url: "/v1/pii",
852
1315
  attributes: Attributes.protected()
853
1316
  });
854
- return OfferOptionAddress.fromDto(dto);
1317
+ return Pii.fromDto(dto);
855
1318
  }
856
1319
 
857
- // src/shared/types/swap.ts
1320
+ // src/shared/core/requirements/requirements-namespace.ts
1321
+ var RequirementsNamespaceImpl = class {
1322
+ constructor(ctx) {
1323
+ this.ctx = ctx;
1324
+ this.log = internalLogger(ctx.logger, "REQUIREMENTS");
1325
+ }
1326
+ async forOffer(offerId) {
1327
+ return this.log.wrap("forOffer", offerId, async () => {
1328
+ await this.ctx.ensureUserAuthenticated();
1329
+ return fetchOfferRequirements(
1330
+ this.ctx.api,
1331
+ offerId,
1332
+ void 0
1333
+ );
1334
+ });
1335
+ }
1336
+ async statuses(offerId) {
1337
+ return this.log.wrap("statuses", offerId, async () => {
1338
+ await this.ctx.ensureUserAuthenticated();
1339
+ return fetchRequirementStatuses(this.ctx.api, offerId);
1340
+ });
1341
+ }
1342
+ async createKycToken(params) {
1343
+ return this.log.wrap("createKycToken", params, async () => {
1344
+ await this.ctx.ensureUserAuthenticated();
1345
+ return createKycToken(
1346
+ this.ctx.api,
1347
+ params?.levelName,
1348
+ params?.reset
1349
+ );
1350
+ });
1351
+ }
1352
+ async getPii() {
1353
+ return this.log.wrap("getPii", void 0, async () => {
1354
+ await this.ctx.ensureUserAuthenticated();
1355
+ return fetchPii(this.ctx.api);
1356
+ });
1357
+ }
1358
+ async submitDocument(params) {
1359
+ return this.log.wrap("submitDocument", params, async () => {
1360
+ await this.ctx.ensureUserAuthenticated();
1361
+ return submitDocument(
1362
+ this.ctx.api,
1363
+ params.documentType,
1364
+ params.fields
1365
+ );
1366
+ });
1367
+ }
1368
+ };
1369
+
1370
+ // src/server/core/server-requirements-namespace.ts
1371
+ var ServerRequirementsNamespaceImpl = class extends RequirementsNamespaceImpl {
1372
+ constructor(serverCtx) {
1373
+ super(serverCtx);
1374
+ this.serverCtx = serverCtx;
1375
+ }
1376
+ async forOffer(offerId, clientCreds) {
1377
+ return this.log.wrap("forOffer", { offerId, clientCreds }, async () => {
1378
+ await this.serverCtx.ensureAuthenticated(clientCreds);
1379
+ return fetchOfferRequirements(
1380
+ this.serverCtx.api,
1381
+ offerId,
1382
+ clientCreds
1383
+ );
1384
+ });
1385
+ }
1386
+ };
1387
+
1388
+ // src/shared/api/nabu/config.ts
1389
+ var NABU_BASE_URL = "https://asset.coinlist.co";
1390
+
1391
+ // src/shared/types/providers/superstate/swap.ts
858
1392
  var SwapAuthorization = {
859
1393
  fromDto: (dto) => ({
860
1394
  authorized: dto.authorized
@@ -862,25 +1396,31 @@ var SwapAuthorization = {
862
1396
  };
863
1397
  var SwapPreview = {
864
1398
  fromDto: (dto) => ({
865
- inputAmount: assertUint256(BigInt(dto.pay_input_amount)),
866
- fee: assertUint256(BigInt(dto.fee)),
867
- outputAmount: assertUint256(BigInt(dto.receive_output_amount))
1399
+ inputAmount: parseUint256(
1400
+ BigInt(dto.pay_input_amount),
1401
+ "SwapPreview.pay_input_amount"
1402
+ ),
1403
+ fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
1404
+ outputAmount: parseUint256(
1405
+ BigInt(dto.receive_output_amount),
1406
+ "SwapPreview.receive_output_amount"
1407
+ )
868
1408
  })
869
1409
  };
870
1410
  var SwapStatus = {
871
1411
  fromDto: (dto) => ({
872
- stopped: assertUint256(BigInt(dto.stopped)),
873
- swapLevel: assertUint256(BigInt(dto.swap_level))
1412
+ stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
1413
+ swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
874
1414
  })
875
1415
  };
876
1416
  var TokenAllowance = {
877
1417
  fromDto: (dto) => ({
878
- allowance: assertUint256(BigInt(dto.allowance))
1418
+ allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
879
1419
  })
880
1420
  };
881
1421
  var TokenBalance = {
882
1422
  fromDto: (dto) => ({
883
- balance: assertUint256(BigInt(dto.balance))
1423
+ balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
884
1424
  })
885
1425
  };
886
1426
  var AllowWalletResponse = {
@@ -905,7 +1445,7 @@ var AllowWalletResponse = {
905
1445
  }
906
1446
  };
907
1447
 
908
- // src/shared/api/frontline/swap.ts
1448
+ // src/shared/api/frontline/providers/superstate/swap.ts
909
1449
  async function getSwapAuthorization(api, params) {
910
1450
  const dto = await api.send({
911
1451
  method: "GET",
@@ -1005,53 +1545,27 @@ function toErc20Asset(dto) {
1005
1545
  };
1006
1546
  }
1007
1547
 
1008
- // src/shared/core/erc20-namespace.ts
1548
+ // src/shared/core/blockchain/erc20/erc20-namespace.ts
1009
1549
  var Erc20NamespaceImpl = class {
1010
1550
  constructor(ctx) {
1011
1551
  this.ctx = ctx;
1552
+ this.log = internalLogger(ctx.logger, "ERC20");
1012
1553
  }
1013
- async getTokenAllowance(params) {
1014
- await this.ctx.ensureUserAuthenticated();
1015
- return getTokenAllowance(this.ctx.api, params);
1016
- }
1017
- async getTokenBalance(params) {
1018
- await this.ctx.ensureUserAuthenticated();
1019
- return getTokenBalance(this.ctx.api, params);
1020
- }
1021
- };
1022
-
1023
- // src/shared/core/swap-namespace.ts
1024
- var SwapNamespaceImpl = class {
1025
- constructor(ctx) {
1026
- this.ctx = ctx;
1027
- }
1028
- async getAuthorization(params) {
1029
- await this.ctx.ensureUserAuthenticated();
1030
- return getSwapAuthorization(this.ctx.api, params);
1031
- }
1032
- async getPreview(params) {
1033
- await this.ctx.ensureUserAuthenticated();
1034
- return getSwapPreview(this.ctx.api, params);
1035
- }
1036
- async getStatus(params) {
1037
- await this.ctx.ensureUserAuthenticated();
1038
- return getSwapStatus(this.ctx.api, params);
1039
- }
1040
- async getOutputToken(params) {
1041
- await this.ctx.ensureUserAuthenticated();
1042
- return getSwapOutputToken(this.ctx.api, params);
1043
- }
1044
- async requestWalletOwnershipChallenge(params) {
1045
- await this.ctx.ensureUserAuthenticated();
1046
- return createWalletOwnershipChallenge(this.ctx.api, params);
1554
+ async getAllowance(params) {
1555
+ return this.log.wrap("getAllowance", params, async () => {
1556
+ await this.ctx.ensureUserAuthenticated();
1557
+ return getTokenAllowance(this.ctx.api, params);
1558
+ });
1047
1559
  }
1048
- async allowWallet(params) {
1049
- await this.ctx.ensureUserAuthenticated();
1050
- return allowWallet(this.ctx.api, params);
1560
+ async getBalance(params) {
1561
+ return this.log.wrap("getBalance", params, async () => {
1562
+ await this.ctx.ensureUserAuthenticated();
1563
+ return getTokenBalance(this.ctx.api, params);
1564
+ });
1051
1565
  }
1052
1566
  };
1053
1567
 
1054
- // src/shared/types/participation.ts
1568
+ // src/shared/types/providers/coin-list/token-sale.ts
1055
1569
  var ParticipationId = (value) => value;
1056
1570
  var Blockchain = (value) => value;
1057
1571
  var WalletAddress = (value) => value;
@@ -1098,7 +1612,7 @@ var CreateParticipationParams = {
1098
1612
  })
1099
1613
  };
1100
1614
 
1101
- // src/shared/api/frontline/participations.ts
1615
+ // src/shared/api/frontline/providers/coin-list/token-sale.ts
1102
1616
  async function fetchParticipations(api, offerId) {
1103
1617
  return fetchAllPages(
1104
1618
  (params) => fetchParticipationsPage(api, params),
@@ -1132,261 +1646,864 @@ async function createParticipation(api, params) {
1132
1646
  return Participation.fromDto(dto);
1133
1647
  }
1134
1648
 
1135
- // src/shared/core/token-sale-namespace.ts
1136
- var TokenSaleNamespaceImpl = class {
1649
+ // src/shared/core/checkout/coin-list/token-sale-namespace.ts
1650
+ var CoinListTokenSaleNamespaceImpl = class {
1137
1651
  constructor(ctx) {
1138
1652
  this.ctx = ctx;
1653
+ this.log = internalLogger(ctx.logger, "TOKEN_SALE");
1139
1654
  }
1140
- async fetchParticipations(offerId) {
1141
- await this.ctx.ensureUserAuthenticated();
1142
- return fetchParticipations(this.ctx.api, offerId);
1655
+ async list(offerId) {
1656
+ return this.log.wrap("list", offerId, async () => {
1657
+ await this.ctx.ensureUserAuthenticated();
1658
+ return fetchParticipations(this.ctx.api, offerId);
1659
+ });
1143
1660
  }
1144
- async fetchParticipationsPage(params) {
1145
- await this.ctx.ensureUserAuthenticated();
1146
- return fetchParticipationsPage(this.ctx.api, params);
1661
+ async listPage(params) {
1662
+ return this.log.wrap("listPage", params, async () => {
1663
+ await this.ctx.ensureUserAuthenticated();
1664
+ return fetchParticipationsPage(this.ctx.api, params);
1665
+ });
1147
1666
  }
1148
- async fetchParticipation(id) {
1149
- await this.ctx.ensureUserAuthenticated();
1150
- return fetchParticipation(this.ctx.api, id);
1667
+ async get(id) {
1668
+ return this.log.wrap("get", id, async () => {
1669
+ await this.ctx.ensureUserAuthenticated();
1670
+ return fetchParticipation(this.ctx.api, id);
1671
+ });
1151
1672
  }
1152
1673
  async createParticipation(params) {
1153
- await this.ctx.ensureUserAuthenticated();
1154
- return createParticipation(this.ctx.api, params);
1674
+ return this.log.wrap("createParticipation", params, async () => {
1675
+ await this.ctx.ensureUserAuthenticated();
1676
+ return createParticipation(this.ctx.api, params);
1677
+ });
1155
1678
  }
1156
1679
  };
1157
1680
 
1158
- // src/shared/types/errors.ts
1159
- var NotAuthenticatedError = class extends Error {
1160
- constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
1161
- super(message);
1162
- this.name = "NotAuthenticatedError";
1163
- }
1681
+ // src/shared/core/blockchain/formatters.ts
1682
+ var import_viem = require("viem");
1683
+
1684
+ // src/shared/types/blockchain/ui.ts
1685
+ var FormattedAmountAssetUi = (value) => value;
1686
+
1687
+ // src/shared/core/blockchain/formatters.ts
1688
+ function formatRawAmount(amount) {
1689
+ return (0, import_viem.formatUnits)(amount.raw, amount.decimals);
1690
+ }
1691
+ var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
1692
+ var USD_FRACTION_DIGITS = AssetDecimals(2);
1693
+
1694
+ // src/shared/core/blockchain/chain.ts
1695
+ var CHAIN_IDS = {
1696
+ ethereum_mainnet: 1,
1697
+ ethereum_sepolia: 11155111
1164
1698
  };
1699
+ function chainFromId(chainId) {
1700
+ const chains = Object.keys(CHAIN_IDS);
1701
+ const chain = chains.find((c) => String(CHAIN_IDS[c]) === chainId);
1702
+ if (!chain) {
1703
+ throw new ValidationError(`Unsupported EIP-155 chain id: "${chainId}"`);
1704
+ }
1705
+ return chain;
1706
+ }
1165
1707
 
1166
- // src/shared/types/oauth-session.ts
1167
- var ClientCredentialsOAuth = (value) => value;
1168
- var OAuthRefreshToken = (value) => value;
1169
- var OAuthSession = {
1708
+ // src/shared/core/blockchain/math.ts
1709
+ var import_viem2 = require("viem");
1710
+ function blockchainAmountFromRawOrThrow({
1711
+ label,
1712
+ raw,
1713
+ decimals
1714
+ }) {
1715
+ const trimmed = raw.trim();
1716
+ if (trimmed === "") {
1717
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1718
+ }
1719
+ let value;
1720
+ try {
1721
+ value = BigInt(trimmed);
1722
+ } catch {
1723
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1724
+ }
1725
+ try {
1726
+ return BlockchainAmount({ raw: assertUint256(value), decimals });
1727
+ } catch {
1728
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
1729
+ }
1730
+ }
1731
+
1732
+ // src/shared/types/trading.ts
1733
+ var Ticker = (value) => value;
1734
+
1735
+ // src/shared/types/providers/ondo/ondo.ts
1736
+ var OndoTradingStatus = {
1170
1737
  fromDto: (dto) => {
1171
- const expiresAt = new Date(Date.now() + dto.expires_in * 1e3);
1738
+ if (!dto.tradable) return { type: "not-tradable", side: dto.side };
1172
1739
  return {
1173
- accessToken: {
1174
- value: dto.access_token,
1175
- expiresAt
1740
+ type: "tradable",
1741
+ side: dto.side,
1742
+ grossMaxTokens: decimalOrNull(dto.gross_max_tokens),
1743
+ grossMaxNotionalValue: decimalOrNull(dto.gross_max_notional_value),
1744
+ grossMaxActiveNotionalValue: decimalOrNull(
1745
+ dto.gross_max_active_notional_value
1746
+ )
1747
+ };
1748
+ }
1749
+ };
1750
+ var decimalOrNull = (value) => value === null ? null : DecimalString(value);
1751
+ var OndoQuote = {
1752
+ fromDto: (dto) => {
1753
+ const assetDecimals = AssetDecimals(dto.asset_decimals);
1754
+ return {
1755
+ chain: chainFromId(dto.chain_id),
1756
+ ticker: Ticker(dto.ticker),
1757
+ assetAddress: EvmContractAddress(dto.asset_address),
1758
+ asset: {
1759
+ name: dto.ticker,
1760
+ symbol: AssetSymbol(dto.symbol),
1761
+ decimals: assetDecimals
1176
1762
  },
1177
- ...dto.refresh_token != null && dto.refresh_token !== "" ? { refreshToken: OAuthRefreshToken(dto.refresh_token) } : void 0
1763
+ side: dto.side,
1764
+ tokenBaseUnits: blockchainAmountFromRawOrThrow({
1765
+ label: "tokenBaseUnits",
1766
+ raw: dto.token_base_units,
1767
+ decimals: assetDecimals
1768
+ }),
1769
+ price: DecimalString(dto.price)
1178
1770
  };
1179
1771
  }
1180
1772
  };
1181
-
1182
- // src/server/coinlist.server.ts
1183
- var ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS = 60;
1184
- var CoinListServerImpl = class {
1185
- constructor(_config) {
1186
- this._config = _config;
1187
- this.baseUrl = _config.baseUrl ?? PUBLIC_API_BASE_URL;
1188
- this.accessTokenExpiryBufferSeconds = _config.accessTokenExpiryBufferSeconds ?? ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS;
1189
- this.strict = _config.strict ?? false;
1190
- this.api = new Api(
1191
- {
1192
- baseUrl: this.baseUrl,
1193
- xApiVersion: API_VERSION
1773
+ var OndoSwapTransaction = {
1774
+ fromDto: (dto) => {
1775
+ const inputDecimals = AssetDecimals(dto.pay_input_decimals);
1776
+ const outputDecimals = AssetDecimals(dto.receive_output_decimals);
1777
+ return {
1778
+ tx: {
1779
+ to: EvmContractAddress(dto.to),
1780
+ data: HexEncodedTransactionData(dto.data)
1194
1781
  },
1195
- // When refresh=true the renewal middleware has received a 401 and wants a
1196
- // fresh token. A read-only store cannot persist a new session, so return
1197
- // null immediately — this tells the middleware to skip the retry rather
1198
- // than re-sending with the same expired token and wasting a round-trip.
1199
- (refresh) => refresh && !this._config.sessionStore.setSession ? Promise.resolve(null) : this.accessToken()
1200
- );
1201
- const ctx = {
1202
- api: this.api,
1203
- ensureUserAuthenticated: () => this.ensureUserAuthenticated()
1782
+ expiresAt: parseExpiresAt(dto.expires_at),
1783
+ payInputAmount: blockchainAmountFromRawOrThrow({
1784
+ label: "pay_input_amount",
1785
+ raw: dto.pay_input_amount,
1786
+ decimals: inputDecimals
1787
+ }),
1788
+ fee: blockchainAmountFromRawOrThrow({
1789
+ label: "fee",
1790
+ raw: dto.fee,
1791
+ decimals: inputDecimals
1792
+ }),
1793
+ notionalValue: blockchainAmountFromRawOrThrow({
1794
+ label: "notional_value",
1795
+ raw: dto.notional_value,
1796
+ decimals: inputDecimals
1797
+ }),
1798
+ receiveOutputAmount: parseReceiveOutputAmount(
1799
+ dto.receive_output_amount,
1800
+ outputDecimals
1801
+ )
1204
1802
  };
1205
- this.erc20 = new Erc20NamespaceImpl(ctx);
1206
- this.tokenSale = new TokenSaleNamespaceImpl(ctx);
1207
- this.swap = new SwapNamespaceImpl(ctx);
1208
1803
  }
1209
- async completeOAuth(code, codeVerifier) {
1210
- const sessionStore = this._config.sessionStore;
1211
- const setSession = sessionStore.setSession?.bind(sessionStore);
1212
- if (!setSession) {
1213
- throw new WritableSessionStoreRequiredError();
1804
+ };
1805
+ function parseReceiveOutputAmount(raw, decimals) {
1806
+ const amount = blockchainAmountFromRawOrThrow({
1807
+ label: "receive_output_amount",
1808
+ raw,
1809
+ decimals
1810
+ });
1811
+ if (amount.raw <= 0n) {
1812
+ throw new ValidationError(
1813
+ `receive_output_amount: must be greater than zero ("${raw}")`
1814
+ );
1815
+ }
1816
+ return amount;
1817
+ }
1818
+ function parseExpiresAt(value) {
1819
+ const date = new Date(value);
1820
+ if (Number.isNaN(date.getTime())) {
1821
+ throw new ValidationError(`expires_at: not a date ("${value}")`);
1822
+ }
1823
+ return date;
1824
+ }
1825
+
1826
+ // src/shared/api/frontline/providers/ondo/ondo.ts
1827
+ async function getOndoTradingStatus(api, params) {
1828
+ const dto = await api.send({
1829
+ method: "GET",
1830
+ url: "/v1/ondo/swap/trading-status",
1831
+ queryParams: { symbol: params.symbol, side: params.side },
1832
+ attributes: Attributes.protected()
1833
+ });
1834
+ return OndoTradingStatus.fromDto(dto);
1835
+ }
1836
+ async function getOndoQuote(api, params) {
1837
+ const dto = await api.send({
1838
+ method: "GET",
1839
+ url: "/v1/ondo/swap/quote",
1840
+ queryParams: {
1841
+ symbol: params.symbol,
1842
+ side: params.side,
1843
+ duration: params.duration,
1844
+ ...sizeParam(params)
1845
+ },
1846
+ attributes: Attributes.protected()
1847
+ });
1848
+ return OndoQuote.fromDto(dto);
1849
+ }
1850
+ async function buildOndoSwapTransaction(api, params) {
1851
+ const dto = await api.send({
1852
+ method: "POST",
1853
+ url: "/v1/ondo/swap/transaction",
1854
+ body: {
1855
+ symbol: params.symbol,
1856
+ chain: params.chain,
1857
+ wallet_address: params.walletAddress,
1858
+ amount: params.amount.raw.toString()
1859
+ },
1860
+ attributes: Attributes.protected()
1861
+ });
1862
+ assertFundingScaleAgrees(dto, params);
1863
+ return OndoSwapTransaction.fromDto(dto);
1864
+ }
1865
+ function assertFundingScaleAgrees(dto, params) {
1866
+ if (dto.pay_input_decimals !== params.amount.decimals) {
1867
+ throw new ValidationError(
1868
+ `pay_input_decimals: the swap was priced in ${dto.pay_input_decimals} decimals but the order was sized in ${params.amount.decimals}`
1869
+ );
1870
+ }
1871
+ }
1872
+ function sizeParam(params) {
1873
+ const tokenAmount = "tokenAmount" in params ? params.tokenAmount : void 0;
1874
+ const notionalValue = "notionalValue" in params ? params.notionalValue : void 0;
1875
+ if (tokenAmount !== void 0) {
1876
+ if (notionalValue !== void 0) {
1877
+ throw new ValidationError(
1878
+ "An Ondo quote takes tokenAmount or notionalValue, not both"
1879
+ );
1214
1880
  }
1215
- const sessionDto = await this.api.send({
1216
- method: "POST",
1217
- url: `/oauth/token`,
1218
- body: {
1219
- grant_type: "authorization_code",
1220
- code,
1221
- redirect_uri: this._config.redirectUri,
1222
- client_id: this._config.clientId,
1223
- client_secret: this._config.clientSecret,
1224
- code_verifier: codeVerifier
1225
- }
1881
+ return { token_amount: formatRawAmount(tokenAmount) };
1882
+ }
1883
+ if (notionalValue === void 0) {
1884
+ throw new ValidationError(
1885
+ "An Ondo quote must be sized by tokenAmount or notionalValue"
1886
+ );
1887
+ }
1888
+ return { notional_value: notionalValue };
1889
+ }
1890
+
1891
+ // src/shared/core/checkout/ondo/ondo-namespace.ts
1892
+ var OndoNamespaceImpl = class {
1893
+ constructor(ctx) {
1894
+ this.ctx = ctx;
1895
+ this.log = internalLogger(ctx.logger, "ONDO");
1896
+ }
1897
+ async getTradingStatus(params) {
1898
+ return this.log.wrap("getTradingStatus", params, async () => {
1899
+ await this.ctx.ensureUserAuthenticated();
1900
+ return getOndoTradingStatus(this.ctx.api, params);
1226
1901
  });
1227
- const session = OAuthSession.fromDto(sessionDto);
1228
- await setSession(session);
1229
- return session;
1230
- }
1231
- async clientCredentialsOAuth() {
1232
- const sessionDto = await this.api.send({
1233
- method: "POST",
1234
- url: `/oauth/token`,
1235
- body: {
1236
- grant_type: "client_credentials",
1237
- client_id: this._config.clientId,
1238
- client_secret: this._config.clientSecret
1239
- }
1902
+ }
1903
+ async getQuote(params) {
1904
+ return this.log.wrap("getQuote", params, async () => {
1905
+ await this.ctx.ensureUserAuthenticated();
1906
+ return getOndoQuote(this.ctx.api, params);
1240
1907
  });
1241
- const session = OAuthSession.fromDto(sessionDto);
1242
- return ClientCredentialsOAuth(session.accessToken);
1243
1908
  }
1244
- async accessToken() {
1245
- const sessionStore = this._config.sessionStore;
1246
- const session = await sessionStore.getSession();
1247
- if (session == null) return null;
1248
- const now = Date.now();
1249
- const expiresAt = session.accessToken.expiresAt.getTime();
1250
- const bufferMs = this.accessTokenExpiryBufferSeconds * 1e3;
1251
- if (expiresAt > now + bufferMs) {
1252
- return session.accessToken;
1253
- }
1254
- const setSession = sessionStore.setSession?.bind(sessionStore);
1255
- if (!setSession) {
1256
- return session.accessToken;
1257
- } else {
1258
- return this.refreshSession(session.refreshToken, setSession);
1259
- }
1909
+ async buildSwapTransaction(params) {
1910
+ return this.log.wrap("buildSwapTransaction", params, async () => {
1911
+ await this.ctx.ensureUserAuthenticated();
1912
+ return buildOndoSwapTransaction(this.ctx.api, params);
1913
+ });
1260
1914
  }
1261
- async refreshSession(refreshToken, setSession) {
1262
- if (!refreshToken) {
1263
- await setSession(null);
1264
- return null;
1265
- }
1266
- try {
1267
- const sessionDto = await this.api.send({
1268
- method: "POST",
1269
- url: `/oauth/token`,
1270
- body: {
1271
- grant_type: "refresh_token",
1272
- refresh_token: refreshToken,
1273
- client_id: this._config.clientId,
1274
- client_secret: this._config.clientSecret
1275
- }
1276
- });
1277
- const newSession = OAuthSession.fromDto(sessionDto);
1278
- await setSession(newSession);
1279
- return newSession.accessToken;
1280
- } catch {
1281
- await setSession(null);
1282
- return null;
1283
- }
1915
+ };
1916
+
1917
+ // src/shared/core/checkout/superstate/swap-namespace.ts
1918
+ var SuperstateSwapNamespaceImpl = class {
1919
+ constructor(ctx) {
1920
+ this.ctx = ctx;
1921
+ this.log = internalLogger(ctx.logger, "SUPERSTATE");
1284
1922
  }
1285
- async logout() {
1286
- const sessionStore = this._config.sessionStore;
1287
- const setSession = sessionStore.setSession?.bind(sessionStore);
1288
- if (!setSession) {
1289
- throw new WritableSessionStoreRequiredError();
1290
- }
1291
- const session = await sessionStore.getSession();
1292
- if (session != null) {
1293
- const tokenToRevoke = session.accessToken.value;
1923
+ async getAuthorization(params) {
1924
+ return this.log.wrap("getAuthorization", params, async () => {
1925
+ await this.ctx.ensureUserAuthenticated();
1926
+ return getSwapAuthorization(this.ctx.api, params);
1927
+ });
1928
+ }
1929
+ async getPreview(params) {
1930
+ return this.log.wrap("getPreview", params, async () => {
1931
+ await this.ctx.ensureUserAuthenticated();
1932
+ return getSwapPreview(this.ctx.api, params);
1933
+ });
1934
+ }
1935
+ async getStatus(params) {
1936
+ return this.log.wrap("getStatus", params, async () => {
1937
+ await this.ctx.ensureUserAuthenticated();
1938
+ return getSwapStatus(this.ctx.api, params);
1939
+ });
1940
+ }
1941
+ async getOutputToken(params) {
1942
+ return this.log.wrap("getOutputToken", params, async () => {
1943
+ await this.ctx.ensureUserAuthenticated();
1944
+ return getSwapOutputToken(this.ctx.api, params);
1945
+ });
1946
+ }
1947
+ async allowWallet(params) {
1948
+ return this.log.wrap("allowWallet", params, async () => {
1949
+ await this.ctx.ensureUserAuthenticated();
1950
+ return allowWallet(this.ctx.api, params);
1951
+ });
1952
+ }
1953
+ };
1954
+
1955
+ // src/shared/api/nabu/tokens.ts
1956
+ var import_viem3 = require("viem");
1957
+
1958
+ // src/shared/types/token-metadata.ts
1959
+ var TokenLogoUrl = (value) => value;
1960
+ var TokenLogo = {
1961
+ /** `baseUrl` is the registry origin; registry URLs are root-relative. */
1962
+ fromDto: (dto, baseUrl) => dto.kind === "VECTOR" ? { kind: "VECTOR", url: resolveLogoUrl(dto.url, baseUrl) } : {
1963
+ kind: "RASTER",
1964
+ original: logoImageFromDto(dto.original, baseUrl),
1965
+ variants: dto.variants.map((v) => logoImageFromDto(v, baseUrl))
1966
+ }
1967
+ };
1968
+ var TokenMetadata = {
1969
+ /** `baseUrl` is the registry origin; registry logo URLs are root-relative. */
1970
+ fromDto: (dto, baseUrl) => {
1971
+ assertSupportedSchemaVersion(dto.schema_version);
1972
+ return {
1973
+ identifier: {
1974
+ chain: EthereumChain(dto.chain),
1975
+ address: EvmContractAddress(dto.address)
1976
+ },
1977
+ name: dto.name,
1978
+ symbol: AssetSymbol(dto.symbol),
1979
+ decimals: AssetDecimals(dto.decimals),
1980
+ logo: TokenLogo.fromDto(dto.logo, baseUrl),
1981
+ logoDark: dto.logo_dark === void 0 ? null : TokenLogo.fromDto(dto.logo_dark, baseUrl)
1982
+ };
1983
+ },
1984
+ /**
1985
+ * Maps the complete registry snapshot to every token it lists across the
1986
+ * chains this SDK models, skipping native coins and chains outside
1987
+ * {@link EthereumChain} (e.g. Solana) rather than failing on them — the
1988
+ * registry may serve chains ahead of the SDK's type surface.
1989
+ */
1990
+ fromRegistryDto: (dto, baseUrl) => {
1991
+ assertSupportedSchemaVersion(dto.schema_version);
1992
+ return dto.chains.flatMap((chainDto) => {
1993
+ let chain;
1294
1994
  try {
1295
- await this.api.send({
1296
- method: "POST",
1297
- url: `/oauth/revoke`,
1298
- body: {
1299
- token: tokenToRevoke,
1300
- client_id: this._config.clientId,
1301
- client_secret: this._config.clientSecret
1302
- }
1303
- });
1304
- } catch (err) {
1305
- if (err instanceof HttpError) {
1306
- if (this.strict) {
1307
- throw err;
1308
- }
1309
- } else {
1310
- throw err;
1311
- }
1995
+ chain = EthereumChain(chainDto.chain);
1996
+ } catch {
1997
+ return [];
1312
1998
  }
1313
- await setSession(null);
1999
+ return tokensOfChain(chain, chainDto.assets, baseUrl);
2000
+ });
2001
+ },
2002
+ /**
2003
+ * Maps a chain snapshot to the tokens it lists, skipping the chain's native
2004
+ * coin (`kind: 'COIN'`, no contract address).
2005
+ */
2006
+ fromChainAssetsDto: (dto, baseUrl) => {
2007
+ assertSupportedSchemaVersion(dto.schema_version);
2008
+ return tokensOfChain(EthereumChain(dto.chain), dto.assets, baseUrl);
2009
+ }
2010
+ };
2011
+ function tokensOfChain(chain, assets, baseUrl) {
2012
+ return assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
2013
+ identifier: {
2014
+ chain,
2015
+ // The filter above cannot narrow `address` for the type checker.
2016
+ address: EvmContractAddress(asset.address)
2017
+ },
2018
+ name: asset.name,
2019
+ symbol: AssetSymbol(asset.symbol),
2020
+ decimals: AssetDecimals(asset.decimals),
2021
+ logo: TokenLogo.fromDto(asset.logo, baseUrl),
2022
+ logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
2023
+ }));
2024
+ }
2025
+ function assertSupportedSchemaVersion(version) {
2026
+ if (version !== 1) {
2027
+ throw new ValidationError(
2028
+ `Unsupported token registry schema_version: ${version}`
2029
+ );
2030
+ }
2031
+ }
2032
+ var logoImageFromDto = (dto, baseUrl) => ({
2033
+ url: resolveLogoUrl(dto.url, baseUrl),
2034
+ width: dto.width,
2035
+ height: dto.height
2036
+ });
2037
+ var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
2038
+ url.startsWith("http") ? url : `${baseUrl.replace(/\/$/, "")}${url}`
2039
+ );
2040
+
2041
+ // src/shared/api/nabu/tokens.ts
2042
+ function createNabuApiClient(baseUrl, logger = null) {
2043
+ return new HttpClient({ baseUrl }, {}, logger);
2044
+ }
2045
+ async function fetchTokenMetadata(client, token) {
2046
+ const address = checksummed(token.address);
2047
+ let response;
2048
+ try {
2049
+ response = await client.send({
2050
+ method: "GET",
2051
+ url: `/${token.chain}/token/${address}`
2052
+ });
2053
+ } catch (error) {
2054
+ if (isRegistryHtmlFallback(error)) {
2055
+ return null;
1314
2056
  }
2057
+ throw error;
1315
2058
  }
1316
- async fetchOffers(clientCreds) {
1317
- await this.ensureAuthenticated(clientCreds);
1318
- return fetchOffers(this.api, clientCreds);
2059
+ if (response.status === 404) {
2060
+ return null;
1319
2061
  }
1320
- async fetchOffersPage(params, clientCreds) {
1321
- await this.ensureAuthenticated(clientCreds);
1322
- return fetchOffersPage(this.api, params, clientCreds);
2062
+ assertOk(response);
2063
+ if (response.body === null) {
2064
+ throw new ValidationError(
2065
+ `Token registry returned an empty body for token "${address}" on "${token.chain}"`
2066
+ );
1323
2067
  }
1324
- async fetchOfferDetails(id, clientCreds) {
1325
- await this.ensureAuthenticated(clientCreds);
1326
- return fetchOfferDetails(this.api, id, clientCreds);
2068
+ return TokenMetadata.fromDto(response.body, client.config.baseUrl);
2069
+ }
2070
+ async function fetchTokensMetadata(client, chain) {
2071
+ let response;
2072
+ try {
2073
+ response = await client.send({
2074
+ method: "GET",
2075
+ url: `/${chain}/assets.json`
2076
+ });
2077
+ } catch (error) {
2078
+ if (isRegistryHtmlFallback(error)) {
2079
+ throw new ValidationError(
2080
+ `Token registry returned non-JSON for the "${chain}" snapshot`
2081
+ );
2082
+ }
2083
+ throw error;
1327
2084
  }
1328
- async createWalletOwnershipChallenge(params) {
1329
- await this.ensureUserAuthenticated();
1330
- return createWalletOwnershipChallenge(this.api, params);
2085
+ assertOk(response);
2086
+ if (response.body === null) {
2087
+ throw new ValidationError(
2088
+ `Token registry returned an empty "${chain}" snapshot`
2089
+ );
1331
2090
  }
1332
- async connectExternalWallet(offerId, params) {
1333
- await this.ensureUserAuthenticated();
1334
- return connectExternalWallet(this.api, offerId, params);
2091
+ return TokenMetadata.fromChainAssetsDto(response.body, client.config.baseUrl);
2092
+ }
2093
+ async function fetchAllTokensMetadata(client) {
2094
+ let response;
2095
+ try {
2096
+ response = await client.send({
2097
+ method: "GET",
2098
+ url: `/assets.json`
2099
+ });
2100
+ } catch (error) {
2101
+ if (isRegistryHtmlFallback(error)) {
2102
+ throw new ValidationError(
2103
+ "Token registry returned non-JSON for the complete snapshot"
2104
+ );
2105
+ }
2106
+ throw error;
1335
2107
  }
1336
- async listOptionAddresses(offerId, offerOptionId) {
1337
- await this.ensureUserAuthenticated();
1338
- return listOptionAddresses(
1339
- this.api,
1340
- offerId,
1341
- offerOptionId
2108
+ assertOk(response);
2109
+ if (response.body === null) {
2110
+ throw new ValidationError(
2111
+ "Token registry returned an empty complete snapshot"
1342
2112
  );
1343
2113
  }
1344
- async removeOptionAddress(offerId, addressId) {
1345
- await this.ensureUserAuthenticated();
1346
- return removeOptionAddress(this.api, offerId, addressId);
2114
+ return TokenMetadata.fromRegistryDto(response.body, client.config.baseUrl);
2115
+ }
2116
+ function isRegistryHtmlFallback(error) {
2117
+ return error instanceof HttpError && error.response.status >= 200 && error.response.status < 300;
2118
+ }
2119
+ function assertOk(response) {
2120
+ if (response.status < 200 || response.status >= 300) {
2121
+ throw new HttpError(response);
2122
+ }
2123
+ }
2124
+ function checksummed(address) {
2125
+ try {
2126
+ return (0, import_viem3.getAddress)(address);
2127
+ } catch (_) {
2128
+ throw new ValidationError(`Invalid EVM contract address: "${address}"`);
1347
2129
  }
1348
- async fetchOfferRequirements(offerId, clientCreds) {
1349
- await this.ensureAuthenticated(clientCreds);
1350
- return fetchOfferRequirements(
1351
- this.api,
1352
- offerId,
1353
- clientCreds
2130
+ }
2131
+
2132
+ // src/shared/core/tokens/tokens-namespace.ts
2133
+ var TokensNamespaceImpl = class {
2134
+ /**
2135
+ * Takes the registry origin rather than a `SharedNamespaceContext`: the
2136
+ * registry is unauthenticated and on its own host, so the frontline sender
2137
+ * and the auth check would both be dead weight here.
2138
+ */
2139
+ constructor(baseUrl, logger = null) {
2140
+ this.api = createNabuApiClient(baseUrl, logger);
2141
+ this.log = internalLogger(logger, "TOKENS");
2142
+ }
2143
+ get(token) {
2144
+ return this.log.wrap(
2145
+ "get",
2146
+ token,
2147
+ () => fetchTokenMetadata(this.api, token)
1354
2148
  );
1355
2149
  }
1356
- async fetchRequirementStatuses(offerId) {
1357
- await this.ensureUserAuthenticated();
1358
- return fetchRequirementStatuses(this.api, offerId);
2150
+ list(chain) {
2151
+ return this.log.wrap(
2152
+ "list",
2153
+ chain,
2154
+ () => chain === void 0 ? fetchAllTokensMetadata(this.api) : fetchTokensMetadata(this.api, chain)
2155
+ );
1359
2156
  }
1360
- async ensureAuthenticated(clientCreds) {
1361
- if (!clientCreds) {
1362
- await this.ensureUserAuthenticated();
2157
+ };
2158
+
2159
+ // src/shared/types/offer-option-address.ts
2160
+ var OfferOptionAddressId = (value) => value;
2161
+ var OfferOptionAddress = {
2162
+ /** Maps the API DTO into the SDK offer-option-address domain model. */
2163
+ fromDto: (dto) => ({
2164
+ id: OfferOptionAddressId(dto.id),
2165
+ offerOptionId: OfferOptionId(dto.offer_option_id),
2166
+ address: EvmWalletAddress(dto.address),
2167
+ protocol: dto.protocol,
2168
+ createdAt: new Date(dto.created_at)
2169
+ })
2170
+ };
2171
+ var ConnectExternalWalletParams = {
2172
+ /** Maps connect-wallet params into the API DTO payload. */
2173
+ toDto: (params) => ({
2174
+ offer_option_id: params.offerOptionId,
2175
+ wallet_address: params.walletAddress,
2176
+ chain: params.chain,
2177
+ signature: params.signature
2178
+ })
2179
+ };
2180
+
2181
+ // src/shared/types/wallet-ownership-challenge.ts
2182
+ var WalletOwnershipChallenge = {
2183
+ /** Maps the API DTO into the SDK wallet-ownership-challenge domain model. */
2184
+ fromDto: (dto) => ({
2185
+ message: dto.message,
2186
+ expiresAt: new Date(dto.expires_at)
2187
+ })
2188
+ };
2189
+ var CreateWalletOwnershipChallengeParams = {
2190
+ /**
2191
+ * Maps challenge-request params into the API DTO payload. The discriminated
2192
+ * union guarantees SIWE fields are present exactly when `challengeType` is
2193
+ * `siwe`, so the mapping narrows on the discriminant.
2194
+ */
2195
+ toDto: (params) => {
2196
+ switch (params.challengeType) {
2197
+ case "plain":
2198
+ return {
2199
+ wallet_address: params.walletAddress,
2200
+ chain: params.chain,
2201
+ challenge_type: "plain"
2202
+ };
2203
+ case "siwe":
2204
+ return {
2205
+ wallet_address: params.walletAddress,
2206
+ chain: params.chain,
2207
+ challenge_type: "siwe",
2208
+ domain: params.domain,
2209
+ uri: params.uri,
2210
+ statement: params.statement
2211
+ };
2212
+ default: {
2213
+ const _exhaustive = params;
2214
+ return _exhaustive;
2215
+ }
1363
2216
  }
1364
2217
  }
1365
- async ensureUserAuthenticated() {
1366
- const token = await this.accessToken();
1367
- if (token === null) {
1368
- throw new NotAuthenticatedError();
1369
- }
2218
+ };
2219
+
2220
+ // src/shared/api/frontline/wallet-connect.ts
2221
+ async function createWalletOwnershipChallenge(api, params) {
2222
+ const dto = await api.send({
2223
+ method: "POST",
2224
+ url: "/v1/wallet-ownership",
2225
+ body: CreateWalletOwnershipChallengeParams.toDto(params),
2226
+ attributes: Attributes.protected()
2227
+ });
2228
+ return WalletOwnershipChallenge.fromDto(dto);
2229
+ }
2230
+ async function connectExternalWallet(api, params) {
2231
+ const dto = await api.send({
2232
+ method: "POST",
2233
+ url: `/v1/offers/${params.offerId}/addresses`,
2234
+ body: ConnectExternalWalletParams.toDto(params),
2235
+ attributes: Attributes.protected()
2236
+ });
2237
+ return OfferOptionAddress.fromDto(dto);
2238
+ }
2239
+ async function listOptionAddresses(api, offerId, offerOptionId) {
2240
+ const { data } = await api.send({
2241
+ method: "GET",
2242
+ url: `/v1/offers/${offerId}/addresses`,
2243
+ queryParams: { offer_option_id: offerOptionId },
2244
+ attributes: Attributes.protected()
2245
+ });
2246
+ return data.map(OfferOptionAddress.fromDto);
2247
+ }
2248
+ async function removeOptionAddress(api, offerId, addressId) {
2249
+ const dto = await api.send({
2250
+ method: "DELETE",
2251
+ url: `/v1/offers/${offerId}/addresses/${addressId}`,
2252
+ attributes: Attributes.protected()
2253
+ });
2254
+ return OfferOptionAddress.fromDto(dto);
2255
+ }
2256
+
2257
+ // src/shared/core/wallets/wallets-namespace.ts
2258
+ var WalletsNamespaceImpl = class {
2259
+ constructor(ctx) {
2260
+ this.ctx = ctx;
2261
+ this.log = internalLogger(ctx.logger, "WALLETS");
2262
+ }
2263
+ async createOwnershipChallenge(params) {
2264
+ return this.log.wrap("createOwnershipChallenge", params, async () => {
2265
+ await this.ctx.ensureUserAuthenticated();
2266
+ return createWalletOwnershipChallenge(
2267
+ this.ctx.api,
2268
+ params
2269
+ );
2270
+ });
1370
2271
  }
1371
- async fetchPii() {
1372
- await this.ensureUserAuthenticated();
1373
- return fetchPii(this.api);
2272
+ async connectExternal(params) {
2273
+ return this.log.wrap("connectExternal", params, async () => {
2274
+ await this.ctx.ensureUserAuthenticated();
2275
+ return connectExternalWallet(this.ctx.api, params);
2276
+ });
1374
2277
  }
1375
- async submitDocument(documentType, fields) {
1376
- await this.ensureUserAuthenticated();
1377
- return submitDocument(this.api, documentType, fields);
2278
+ async list(params) {
2279
+ return this.log.wrap("list", params, async () => {
2280
+ await this.ctx.ensureUserAuthenticated();
2281
+ return listOptionAddresses(
2282
+ this.ctx.api,
2283
+ params.offerId,
2284
+ params.offerOptionId
2285
+ );
2286
+ });
1378
2287
  }
1379
- async createKycToken(levelName, reset) {
1380
- await this.ensureUserAuthenticated();
1381
- return createKycToken(this.api, levelName, reset);
2288
+ async remove(params) {
2289
+ return this.log.wrap("remove", params, async () => {
2290
+ await this.ctx.ensureUserAuthenticated();
2291
+ return removeOptionAddress(
2292
+ this.ctx.api,
2293
+ params.offerId,
2294
+ params.addressId
2295
+ );
2296
+ });
2297
+ }
2298
+ };
2299
+
2300
+ // src/server/core/coinlist-server.ts
2301
+ var ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS = 60;
2302
+ var CoinListServerImpl = class {
2303
+ constructor(_config) {
2304
+ this._config = _config;
2305
+ const logger = _config.logger ?? null;
2306
+ this.api = new ApiClient(
2307
+ {
2308
+ baseUrl: _config.baseUrl ?? PUBLIC_API_BASE_URL,
2309
+ xApiVersion: API_VERSION
2310
+ },
2311
+ // When refresh=true the renewal middleware has received a 401 and wants a
2312
+ // fresh token. A read-only store cannot persist a new session, so return
2313
+ // null immediately — this tells the middleware to skip the retry rather
2314
+ // than re-sending with the same expired token and wasting a round-trip.
2315
+ (refresh) => refresh && !this._config.sessionStore.setSession ? Promise.resolve(null) : this.auth.getAccessToken(),
2316
+ logger
2317
+ );
2318
+ this.auth = new ServerAuthNamespaceImpl(this.api, {
2319
+ ..._config,
2320
+ accessTokenExpiryBufferSeconds: _config.accessTokenExpiryBufferSeconds ?? ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS,
2321
+ strict: _config.strict ?? false
2322
+ });
2323
+ const ctx = {
2324
+ api: this.api,
2325
+ logger,
2326
+ ensureUserAuthenticated: () => this.ensureAuthenticated(void 0),
2327
+ ensureAuthenticated: (clientCreds) => this.ensureAuthenticated(clientCreds)
2328
+ };
2329
+ this.offers = new ServerOffersNamespaceImpl(ctx);
2330
+ this.requirements = new ServerRequirementsNamespaceImpl(ctx);
2331
+ this.wallets = new WalletsNamespaceImpl(ctx);
2332
+ this.erc20 = new Erc20NamespaceImpl(ctx);
2333
+ this.tokenSale = new CoinListTokenSaleNamespaceImpl(ctx);
2334
+ this.superstate = new SuperstateSwapNamespaceImpl(ctx);
2335
+ this.ondo = new OndoNamespaceImpl(ctx);
2336
+ this.tokens = new TokensNamespaceImpl(
2337
+ _config.tokensBaseUrl ?? NABU_BASE_URL,
2338
+ logger
2339
+ );
2340
+ }
2341
+ /**
2342
+ * An app-level token authenticates a request on its own; without one the
2343
+ * caller needs a user session.
2344
+ */
2345
+ async ensureAuthenticated(clientCreds) {
2346
+ if (clientCreds) return;
2347
+ const token = await this.auth.getAccessToken();
2348
+ if (token === null) {
2349
+ throw new NotAuthenticatedError();
2350
+ }
1382
2351
  }
1383
2352
  };
1384
2353
  function createCoinListServer(config) {
1385
2354
  return new CoinListServerImpl(config);
1386
2355
  }
2356
+
2357
+ // src/server/core/observability/pino-server-logger.ts
2358
+ var import_pino = require("pino");
2359
+
2360
+ // src/shared/core/observability/pino-logger.ts
2361
+ function toPinoRecord(event) {
2362
+ try {
2363
+ const record = {};
2364
+ for (const key of ownKeys(event.fields)) {
2365
+ record[key] = readProperty(event.fields, key, 0, /* @__PURE__ */ new WeakSet());
2366
+ }
2367
+ const cause = "cause" in event ? event.cause : void 0;
2368
+ if (cause !== void 0) {
2369
+ record.cause = sanitize(cause, 0, /* @__PURE__ */ new WeakSet());
2370
+ }
2371
+ return { ...record, scope: event.scope, ...event.bindings };
2372
+ } catch (_) {
2373
+ return { "log.render": "<unrenderable event>" };
2374
+ }
2375
+ }
2376
+ var PINO_LEVEL = {
2377
+ none: "silent",
2378
+ error: "error",
2379
+ warn: "warn",
2380
+ info: "info",
2381
+ debug: "debug"
2382
+ };
2383
+ var MAX_DEPTH = 8;
2384
+ function sanitize(value, depth, seen) {
2385
+ switch (typeof value) {
2386
+ case "string":
2387
+ case "boolean":
2388
+ return value;
2389
+ case "number":
2390
+ return Number.isFinite(value) ? value : String(value);
2391
+ case "bigint":
2392
+ return value.toString();
2393
+ case "undefined":
2394
+ return "<undefined>";
2395
+ case "function":
2396
+ return "<function>";
2397
+ case "symbol":
2398
+ return value.toString();
2399
+ case "object":
2400
+ return value === null ? null : sanitizeObject(value, depth, seen);
2401
+ default:
2402
+ return "<unrenderable>";
2403
+ }
2404
+ }
2405
+ function sanitizeObject(value, depth, seen) {
2406
+ if (seen.has(value)) return "<circular>";
2407
+ if (depth >= MAX_DEPTH) return "<max depth>";
2408
+ if (value instanceof Error) return describeError(value);
2409
+ if (value instanceof Date) return describeDate(value);
2410
+ seen.add(value);
2411
+ try {
2412
+ if (Array.isArray(value)) {
2413
+ return value.map(
2414
+ (_item, index) => readProperty(value, String(index), depth, seen)
2415
+ );
2416
+ }
2417
+ const out = {};
2418
+ for (const key of ownKeys(value)) {
2419
+ out[key] = readProperty(value, key, depth, seen);
2420
+ }
2421
+ return out;
2422
+ } finally {
2423
+ seen.delete(value);
2424
+ }
2425
+ }
2426
+ function readProperty(owner, key, depth, seen) {
2427
+ try {
2428
+ return sanitize(owner[key], depth + 1, seen);
2429
+ } catch (_) {
2430
+ return "<unreadable>";
2431
+ }
2432
+ }
2433
+ function ownKeys(value) {
2434
+ try {
2435
+ return Object.keys(value);
2436
+ } catch (_) {
2437
+ return [];
2438
+ }
2439
+ }
2440
+ function describeError(error) {
2441
+ return {
2442
+ name: safeRead(() => error.name),
2443
+ message: safeRead(() => error.message),
2444
+ stack: safeRead(() => error.stack)
2445
+ };
2446
+ }
2447
+ function describeDate(date) {
2448
+ return safeRead(() => date.toISOString());
2449
+ }
2450
+ function safeRead(read) {
2451
+ try {
2452
+ const value = read();
2453
+ return typeof value === "string" ? value : "<unreadable>";
2454
+ } catch (_) {
2455
+ return "<unreadable>";
2456
+ }
2457
+ }
2458
+ var SDK_LOGGER_NAME = "@coinlist-co/react";
2459
+ function loggerOverPino(sink, level) {
2460
+ return {
2461
+ level: () => level,
2462
+ debug: (event) => emit(sink, "debug", event),
2463
+ info: (event) => emit(sink, "info", event),
2464
+ warn: (event) => emit(sink, "warn", event),
2465
+ error: (event) => emit(sink, "error", event)
2466
+ };
2467
+ }
2468
+ function emit(sink, method, event) {
2469
+ try {
2470
+ const value = event();
2471
+ sink[method](toPinoRecord(value), value.msg);
2472
+ } catch (error) {
2473
+ reportRenderFailure(sink, error);
2474
+ }
2475
+ }
2476
+ function reportRenderFailure(sink, error) {
2477
+ try {
2478
+ sink.error(
2479
+ { "error.type": error instanceof Error ? error.name : typeof error },
2480
+ "log event failed to render"
2481
+ );
2482
+ } catch (_) {
2483
+ }
2484
+ }
2485
+
2486
+ // src/server/core/observability/pino-server-logger.ts
2487
+ function pinoServerLogger(options) {
2488
+ return loggerOverPino(
2489
+ // `name` as a child binding rather than pino's `name` option: the option
2490
+ // is honoured by pino's node build and silently dropped by its browser
2491
+ // build, so a binding is the only spelling that identifies the SDK in
2492
+ // both environments.
2493
+ (0, import_pino.pino)({
2494
+ level: PINO_LEVEL[options.level]
2495
+ }).child({ name: SDK_LOGGER_NAME }),
2496
+ options.level
2497
+ );
2498
+ }
1387
2499
  // Annotate the CommonJS export names for ESM import in node:
1388
2500
  0 && (module.exports = {
2501
+ ServerAuthNamespaceImpl,
2502
+ ServerOffersNamespaceImpl,
2503
+ ServerRequirementsNamespaceImpl,
1389
2504
  WritableSessionStoreRequiredError,
1390
- createCoinListServer
2505
+ createCoinListServer,
2506
+ emptySessionStore,
2507
+ pinoServerLogger
1391
2508
  });
1392
2509
  //# sourceMappingURL=index.cjs.map