@coinlist-co/react 0.12.2-rc.7b430dd → 0.12.2-rc.8a0d02a

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 (31) hide show
  1. package/dist/{chunk-DCW7NQXH.js → chunk-3WW5FLT7.js} +52 -19
  2. package/dist/chunk-3WW5FLT7.js.map +1 -0
  3. package/dist/{chunk-MOE5S6CE.js → chunk-C6GF7MDF.js} +915 -458
  4. package/dist/chunk-C6GF7MDF.js.map +1 -0
  5. package/dist/{chunk-VH34YC3Q.js → chunk-IZJ4JSSC.js} +78 -4
  6. package/dist/chunk-IZJ4JSSC.js.map +1 -0
  7. package/dist/client/index.cjs +12103 -8452
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +1640 -37
  10. package/dist/client/index.d.ts +1640 -37
  11. package/dist/client/index.js +7923 -4800
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/server/index.cjs +789 -142
  14. package/dist/server/index.cjs.map +1 -1
  15. package/dist/server/index.d.cts +69 -41
  16. package/dist/server/index.d.ts +69 -41
  17. package/dist/server/index.js +323 -65
  18. package/dist/server/index.js.map +1 -1
  19. package/dist/{tokens-namespace-CIWBtgt2.d.cts → time-CVZpAkGY.d.cts} +878 -192
  20. package/dist/{tokens-namespace-CIWBtgt2.d.ts → time-CVZpAkGY.d.ts} +878 -192
  21. package/dist/{token-registry-snapshot-BNBNuDu1.d.ts → token-registry-snapshot-BkwA8KmD.d.ts} +74 -8
  22. package/dist/{token-registry-snapshot-CqI6dXM_.d.cts → token-registry-snapshot-bR14QehS.d.cts} +74 -8
  23. package/dist/universal/index.cjs +982 -448
  24. package/dist/universal/index.cjs.map +1 -1
  25. package/dist/universal/index.d.cts +91 -5
  26. package/dist/universal/index.d.ts +91 -5
  27. package/dist/universal/index.js +44 -2
  28. package/package.json +1 -1
  29. package/dist/chunk-DCW7NQXH.js.map +0 -1
  30. package/dist/chunk-MOE5S6CE.js.map +0 -1
  31. package/dist/chunk-VH34YC3Q.js.map +0 -1
@@ -1,3 +1,27 @@
1
+ // src/universal/api/internal-access-token-source.ts
2
+ var SentWith = {
3
+ userToken: (token) => ({
4
+ type: "user-token",
5
+ token
6
+ }),
7
+ noUserToken: { type: "no-user-token" }
8
+ };
9
+ var TokenTrigger = {
10
+ beforeRequest: { type: "before-request" },
11
+ after401: (rejected) => ({
12
+ type: "after-401",
13
+ rejected
14
+ })
15
+ };
16
+ function isRejectedToken(token, rejected) {
17
+ switch (rejected.type) {
18
+ case "user-token":
19
+ return rejected.token.value === token.value;
20
+ case "no-user-token":
21
+ return false;
22
+ }
23
+ }
24
+
1
25
  // src/universal/api/http-attributes.ts
2
26
  var empty = {};
3
27
  var concat = (left, right) => ({
@@ -25,6 +49,10 @@ var retryAttempt = (attempt) => ({
25
49
  var renewAttempted = (value) => ({
26
50
  renewAttempted: value
27
51
  });
52
+ var notRetryable = () => ({ retryable: false });
53
+ var sentWith = (token) => ({
54
+ sentWith: token
55
+ });
28
56
  var requestId = (id) => ({ requestId: id });
29
57
  var getRequestId = (attrs) => attrs?.requestId ?? null;
30
58
  var isProtected = (attrs) => attrs?.protected === true;
@@ -32,6 +60,8 @@ var needUserAgent = (attrs) => attrs?.userAgent === true;
32
60
  var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
33
61
  var getRetryAttempt = (attrs) => attrs?.retryAttempt ?? 0;
34
62
  var wasRenewAttempted = (attrs) => attrs?.renewAttempted === true;
63
+ var isRetryable = (attrs) => attrs?.retryable !== false;
64
+ var getSentWith = (attrs) => attrs?.sentWith === void 0 ? SentWith.noUserToken : SentWith.userToken(attrs.sentWith);
35
65
  var getClientCredentials = (attrs) => attrs?.clientCredentials;
36
66
  var Attributes = {
37
67
  empty,
@@ -47,6 +77,10 @@ var Attributes = {
47
77
  getRetryAttempt,
48
78
  renewAttempted,
49
79
  wasRenewAttempted,
80
+ notRetryable,
81
+ isRetryable,
82
+ sentWith,
83
+ getSentWith,
50
84
  clientCredentials,
51
85
  getClientCredentials,
52
86
  requestId,
@@ -209,6 +243,54 @@ var MathError = class extends Error {
209
243
  }
210
244
  };
211
245
 
246
+ // src/universal/types/time.ts
247
+ var MAX_EPOCH_MILLIS = 864e13;
248
+ var EpochMillis = {
249
+ /**
250
+ * @throws {@link ValidationError} unless `value` is an integer a `Date` can
251
+ * represent: at most {@link MAX_EPOCH_MILLIS} either side of the epoch.
252
+ */
253
+ of: (value) => {
254
+ if (!Number.isInteger(value) || Math.abs(value) > MAX_EPOCH_MILLIS) {
255
+ throw new ValidationError(
256
+ `EpochMillis must be an integer within \xB1${MAX_EPOCH_MILLIS}, got ${value}`
257
+ );
258
+ }
259
+ return value;
260
+ },
261
+ /** The wall clock. Code that needs the time takes a `TimeEff` instead. */
262
+ now: () => EpochMillis.of(Date.now()),
263
+ /** @throws {@link ValidationError} for an invalid `Date`. */
264
+ fromDate: (date) => EpochMillis.of(date.getTime()),
265
+ /** How long after `from` the instant `to` is; negative if it is before. */
266
+ elapsed: (from, to) => Millis.of(to - from),
267
+ plus: (at, duration) => EpochMillis.of(at + duration)
268
+ };
269
+ var Millis = {
270
+ of: (value) => value
271
+ };
272
+ var Seconds = {
273
+ /**
274
+ * @throws {@link ValidationError} unless `value` is a non-negative integer.
275
+ */
276
+ of: (value) => {
277
+ if (!Number.isInteger(value) || value < 0) {
278
+ throw new ValidationError(
279
+ `Seconds must be a non-negative integer, got ${value}`
280
+ );
281
+ }
282
+ return value;
283
+ },
284
+ toMillis: (value) => Millis.of(value * 1e3)
285
+ };
286
+ function isExpired({
287
+ expiresAt,
288
+ now,
289
+ buffer = Millis.of(0)
290
+ }) {
291
+ return now >= expiresAt - buffer;
292
+ }
293
+
212
294
  // src/universal/core/shared/blockchain/erc20/abi.ts
213
295
  var ERC20_ABI = [
214
296
  {
@@ -309,66 +391,6 @@ var ERC20_ABI = [
309
391
  }
310
392
  ];
311
393
 
312
- // src/universal/api/pagination.ts
313
- async function fetchAllPages(fetchPage, baseParams) {
314
- const items = [];
315
- let cursor = null;
316
- do {
317
- const params = {
318
- ...baseParams ?? {},
319
- after: cursor ?? void 0
320
- };
321
- const page = await fetchPage(params);
322
- items.push(...page.data);
323
- cursor = page.startingAfter;
324
- } while (cursor);
325
- return items;
326
- }
327
-
328
- // src/universal/types/pagination.ts
329
- var Cursor = (value) => value;
330
- var PaginatedResponse = {
331
- fromDto: (dto, itemMapper) => PaginatedResponse.fromDtoPage(dto, (items) => items.map(itemMapper)),
332
- /**
333
- * For a mapper that decides the page as a whole - one that drops items it
334
- * cannot map, such as `Offer.listFromDto` - rather than item by item. The
335
- * cursors are the wire's either way: dropping an item changes what the
336
- * page holds, not where the next page starts.
337
- */
338
- fromDtoPage: (dto, pageMapper) => ({
339
- data: pageMapper(dto.data),
340
- startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
341
- startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
342
- })
343
- };
344
- var PaginationParams = {
345
- toQueryParams: (params) => {
346
- const queryParams = {};
347
- if (params.after) {
348
- queryParams.starting_after = params.after;
349
- }
350
- if (params.before) {
351
- queryParams.starting_before = params.before;
352
- }
353
- if (params.limit) {
354
- queryParams.limit = params.limit;
355
- }
356
- return queryParams;
357
- }
358
- };
359
-
360
- // src/universal/types/asset.ts
361
- var AssetId = (value) => value;
362
- var AssetCode = (value) => value;
363
- var Asset = {
364
- fromDto: (dto) => ({
365
- id: AssetId(dto.id),
366
- code: AssetCode(dto.code),
367
- name: dto.name,
368
- fractionalDigits: dto.fractional_digits
369
- })
370
- };
371
-
372
394
  // src/universal/types/blockchain/core.ts
373
395
  var ETHEREUM_CHAINS = {
374
396
  ethereum_mainnet: true,
@@ -466,6 +488,66 @@ var StablecoinSymbol = (value) => value;
466
488
  var KnownAssetSymbol = StablecoinSymbol;
467
489
  var Bps = (value) => value;
468
490
 
491
+ // src/universal/core/shared/blockchain/math.ts
492
+ import { parseUnits } from "viem";
493
+ function blockchainAmountFromRawOrThrow({
494
+ label,
495
+ raw,
496
+ decimals
497
+ }) {
498
+ const trimmed = raw.trim();
499
+ if (trimmed === "") {
500
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
501
+ }
502
+ let value;
503
+ try {
504
+ value = BigInt(trimmed);
505
+ } catch {
506
+ throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
507
+ }
508
+ try {
509
+ return BlockchainAmount({ raw: assertUint256(value), decimals });
510
+ } catch {
511
+ throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
512
+ }
513
+ }
514
+ function parseBlockchainAmount(amount, decimals) {
515
+ const trimmed = amount.trim();
516
+ if (trimmed === "") return { valid: false, reason: { type: "empty" } };
517
+ if (trimmed.startsWith("-")) {
518
+ return { valid: false, reason: { type: "negative" } };
519
+ }
520
+ if (/[eE]/.test(trimmed)) {
521
+ return { valid: false, reason: { type: "invalid-format" } };
522
+ }
523
+ if (trimmed === ".") {
524
+ return { valid: false, reason: { type: "invalid-format" } };
525
+ }
526
+ const normalised = trimmed.replace(/^\./, "0.").replace(/\.$/, "");
527
+ if (!/^\d+(\.\d+)?$/.test(normalised)) {
528
+ return { valid: false, reason: { type: "invalid-format" } };
529
+ }
530
+ const [, fraction = ""] = normalised.split(".");
531
+ if (fraction.length > decimals) {
532
+ return {
533
+ valid: false,
534
+ reason: { type: "too-many-decimals", maxDecimals: decimals }
535
+ };
536
+ }
537
+ try {
538
+ const raw = parseUnits(normalised, decimals);
539
+ if (raw > MAX_UINT_256) {
540
+ return { valid: false, reason: { type: "overflow" } };
541
+ }
542
+ return {
543
+ valid: true,
544
+ amount: BlockchainAmount({ raw, decimals })
545
+ };
546
+ } catch {
547
+ return { valid: false, reason: { type: "invalid-format" } };
548
+ }
549
+ }
550
+
469
551
  // src/universal/core/shared/utils/crypto.ts
470
552
  async function sha256(data) {
471
553
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
@@ -541,6 +623,12 @@ function requiredDate(value, field) {
541
623
  }
542
624
  return date;
543
625
  }
626
+ function dateOrNull(value, field) {
627
+ return value === null ? null : requiredDate(value, field);
628
+ }
629
+ function decimalOrNull(value) {
630
+ return value === null ? null : DecimalString(value);
631
+ }
544
632
  function requiredArray(value, field) {
545
633
  if (!Array.isArray(value)) {
546
634
  throw new ValidationError(
@@ -550,98 +638,647 @@ function requiredArray(value, field) {
550
638
  return value;
551
639
  }
552
640
 
553
- // src/universal/types/offer.ts
554
- var OfferId = (value) => value;
555
- var OfferSlug = (value) => value;
556
- var OFFER_TYPES = {
557
- "coinlist::token_sale": true,
558
- "superstate::swap": true,
559
- "ondo::swap": true
641
+ // src/universal/types/providers/centrifuge/centrifuge.ts
642
+ var CentrifugeVaultStatus = {
643
+ fromDto: (dto) => ({
644
+ chain: EthereumChain(dto.chain),
645
+ symbol: AssetSymbol(dto.symbol),
646
+ vaultAddress: EvmContractAddress(dto.vault_address),
647
+ linked: dto.linked,
648
+ permissioned: dto.permissioned,
649
+ membershipValidUntil: dateOrNull(
650
+ dto.membership_valid_until,
651
+ "CentrifugeVaultStatus.membership_valid_until"
652
+ ),
653
+ halted: dto.halted,
654
+ priceUpdatedAt: dateOrNull(
655
+ dto.price_updated_at,
656
+ "CentrifugeVaultStatus.price_updated_at"
657
+ ),
658
+ orderability: parseOrderability(
659
+ dto.can_order,
660
+ dto.reasons,
661
+ "CentrifugeVaultStatus"
662
+ ),
663
+ asOf: requiredDate(dto.as_of, "CentrifugeVaultStatus.as_of")
664
+ })
560
665
  };
561
- var isOfferType = (value) => Object.keys(OFFER_TYPES).includes(value);
562
- var OfferEditorial = {
563
- /**
564
- * `model` prefixes the field in the error (`'Offer'`, `'OfferDetail'`), so
565
- * the same three checks name the payload that failed them.
566
- */
567
- fromDto: (dto, model) => ({
568
- tagline: requiredString(dto.tagline, `${model}.tagline`),
569
- bannerUrl: requiredString(dto.banner_url, `${model}.banner_url`),
570
- startsAt: requiredDate(dto.starts_at, `${model}.starts_at`)
666
+ var CentrifugeVaultBuyTransaction = {
667
+ fromDto: (dto) => {
668
+ const spendInputAmount = blockchainAmountFromRawOrThrow({
669
+ label: "spend_input_amount",
670
+ raw: dto.spend_input_amount,
671
+ decimals: AssetDecimals(dto.spend_input_decimals)
672
+ });
673
+ if (spendInputAmount.raw <= 0n) {
674
+ throw new ValidationError(
675
+ `spend_input_amount: must be greater than zero ("${dto.spend_input_amount}") - a deposit of nothing is not a request`
676
+ );
677
+ }
678
+ return {
679
+ ...parseTransactionCore(dto, "CentrifugeVaultBuyTransaction"),
680
+ spendInputAmount
681
+ };
682
+ }
683
+ };
684
+ var CentrifugeVaultClaimTransaction = {
685
+ fromDto: (dto) => ({
686
+ ...parseTransactionCore(dto, "CentrifugeVaultClaimTransaction"),
687
+ claimableShares: blockchainAmountFromRawOrThrow({
688
+ label: "claimable_shares",
689
+ raw: dto.claimable_shares,
690
+ decimals: AssetDecimals(dto.share_decimals)
691
+ })
571
692
  })
572
693
  };
573
- var Offer = {
694
+ var CentrifugeVaultPosition = {
574
695
  fromDto: (dto) => {
575
- const tokens = requiredArray(dto.tokens, "Offer.tokens");
576
- const base2 = {
577
- id: OfferId(dto.id),
578
- slug: OfferSlug(dto.slug),
579
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
580
- tokens: OfferToken.listFromDto(tokens)
696
+ const assetDecimals = AssetDecimals(dto.asset_decimals);
697
+ const shareDecimals = AssetDecimals(dto.share_decimals);
698
+ const asset = (label, raw) => blockchainAmountFromRawOrThrow({ label, raw, decimals: assetDecimals });
699
+ const shares = (label, raw) => blockchainAmountFromRawOrThrow({ label, raw, decimals: shareDecimals });
700
+ return {
701
+ chain: EthereumChain(dto.chain),
702
+ symbol: AssetSymbol(dto.symbol),
703
+ walletAddress: EvmWalletAddress(dto.wallet_address),
704
+ status: dto.status,
705
+ requested: asset("requested", dto.requested),
706
+ pending: asset("pending", dto.pending),
707
+ filledAssets: asset("filled_assets", dto.filled_assets),
708
+ earnedShares: shares("earned_shares", dto.earned_shares),
709
+ claimedShares: shares("claimed_shares", dto.claimed_shares),
710
+ claimableShares: shares("claimable_shares", dto.claimable_shares),
711
+ shareBalance: shares("share_balance", dto.share_balance),
712
+ averagePrice: decimalOrNull(dto.average_price),
713
+ frozen: dto.frozen,
714
+ asOf: requiredDate(dto.as_of, "CentrifugeVaultPosition.as_of")
581
715
  };
582
- switch (dto.type) {
583
- case "coinlist::token_sale":
584
- return {
585
- ...base2,
586
- ...OfferEditorial.fromDto(dto, "Offer"),
587
- type: dto.type,
588
- logoUrl: requiredString(dto.logo_url, "Offer.logo_url")
589
- };
590
- case "superstate::swap":
591
- return {
592
- ...base2,
593
- ...OfferEditorial.fromDto(dto, "Offer"),
594
- type: dto.type,
595
- logoUrl: notBlankStringOrNull(dto.logo_url)
596
- };
597
- // `tagline`, `banner_url` and `starts_at` arrive as `null` and are left
598
- // on the wire: copying them would hand every consumer a `startsAt` that
599
- // is 1970 for one variant and a date for the others.
600
- case "ondo::swap":
601
- return {
602
- ...base2,
603
- type: dto.type,
604
- logoUrl: notBlankStringOrNull(dto.logo_url)
605
- };
606
- default:
607
- return unknownTypeError(dto, "Offer");
608
- }
609
- },
610
- /**
611
- * Maps a page of offers, dropping every offer whose `type` this SDK does not
612
- * name. The same reasoning as {@link OfferToken.listFromDto}: a plain `.map`
613
- * would throw out of `fromDto` and, through `PaginatedResponse.fromDto`,
614
- * reject the whole page, so one offer of an unknown type would blank the
615
- * grid for every offer beside it. A single offer fetched by id still
616
- * throws, because there is nothing beside it to keep.
617
- */
618
- listFromDto: (dtos) => dtos.filter((dto) => isOfferType(dto.type)).map(Offer.fromDto)
716
+ }
619
717
  };
620
- var OfferToken = {
718
+ var CentrifugeVaultRedeemPosition = {
621
719
  fromDto: (dto) => ({
622
- role: dto.role,
623
- chain: Chain(dto.chain),
624
- address: EvmContractAddress(dto.address)
625
- }),
720
+ chain: EthereumChain(dto.chain),
721
+ symbol: AssetSymbol(dto.symbol),
722
+ walletAddress: EvmWalletAddress(dto.wallet_address),
723
+ status: dto.status,
724
+ pending: blockchainAmountFromRawOrThrow({
725
+ label: "pending",
726
+ raw: dto.pending,
727
+ decimals: AssetDecimals(dto.share_decimals)
728
+ }),
729
+ claimableAssets: blockchainAmountFromRawOrThrow({
730
+ label: "claimable_assets",
731
+ raw: dto.claimable_assets,
732
+ decimals: AssetDecimals(dto.asset_decimals)
733
+ }),
734
+ frozen: dto.frozen,
735
+ asOf: requiredDate(dto.as_of, "CentrifugeVaultRedeemPosition.as_of")
736
+ })
737
+ };
738
+ var CentrifugeVaultLeg = {
626
739
  /**
627
- * Maps an offer's token list, dropping every token on a chain this SDK does
628
- * not name. Frontline's chain registry runs ahead of {@link Chain}, and a
629
- * plain `.map` would throw out of `Offer.fromDto` and, through
630
- * `PaginatedResponse.fromDto`, reject the whole offers page - which is how
631
- * one Base token blanked production's offers list. Dropping costs that
632
- * token's metadata alone: `coinlist.tokens.get` takes an `EthereumChain`,
633
- * so nobody could have looked it up anyway.
634
- *
635
- * Same shape as `TokenMetadata.fromRegistryDto`.
740
+ * What a claim on the leg would collect: shares for `invest`, the funding
741
+ * token for `redeem`.
636
742
  */
637
- listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferToken.fromDto)
743
+ claimable: (leg) => {
744
+ switch (leg.direction) {
745
+ case "invest":
746
+ return leg.position.claimableShares;
747
+ case "redeem":
748
+ return leg.position.claimableAssets;
749
+ default: {
750
+ const exhaustive = leg;
751
+ return exhaustive;
752
+ }
753
+ }
754
+ },
755
+ /** Whether the leg has anything queued or anything ready to claim. */
756
+ isActive: (leg) => leg.position.pending.raw > 0n || CentrifugeVaultLeg.claimable(leg).raw > 0n
638
757
  };
639
-
640
- // src/universal/types/trading.ts
641
- var Ticker = (value) => value;
642
- var Isin = (value) => value;
758
+ var CentrifugeVaultLegId = {
759
+ /** Addresses compare case-insensitively: frontline echoes them lower case. */
760
+ of: (leg) => [
761
+ leg.direction,
762
+ leg.position.chain,
763
+ leg.position.walletAddress.toLowerCase()
764
+ ].join(":")
765
+ };
766
+ var CentrifugeVaultClaimProceedsTransaction = {
767
+ fromDto: (dto) => ({
768
+ ...parseTransactionCore(dto, "CentrifugeVaultClaimProceedsTransaction"),
769
+ claimableAssets: blockchainAmountFromRawOrThrow({
770
+ label: "claimable_assets",
771
+ raw: dto.claimable_assets,
772
+ decimals: AssetDecimals(dto.asset_decimals)
773
+ })
774
+ })
775
+ };
776
+ function parseOrderability(canOrder, reasons, model) {
777
+ const [first, ...rest] = reasons;
778
+ if (canOrder) {
779
+ if (first !== void 0) {
780
+ throw new ValidationError(
781
+ `${model}.reasons: expected none when can_order is true, got ${JSON.stringify(reasons)}`
782
+ );
783
+ }
784
+ return { type: "orderable" };
785
+ }
786
+ if (first === void 0) {
787
+ throw new ValidationError(
788
+ `${model}.reasons: expected at least one when can_order is false`
789
+ );
790
+ }
791
+ return { type: "blocked", reasons: [first, ...rest] };
792
+ }
793
+ function parseTransactionCore(dto, model) {
794
+ return {
795
+ tx: {
796
+ to: EvmContractAddress(dto.to),
797
+ data: HexEncodedTransactionData(dto.data)
798
+ },
799
+ expiresAt: dateOrNull(dto.expires_at, `${model}.expires_at`)
800
+ };
801
+ }
802
+
803
+ // src/universal/api/frontline/providers/centrifuge/centrifuge.ts
804
+ async function getCentrifugeVaultStatus(api, params) {
805
+ const dto = await api.send({
806
+ method: "GET",
807
+ url: "/v1/centrifuge/vault/status",
808
+ queryParams: {
809
+ symbol: params.symbol,
810
+ chain: params.chain
811
+ },
812
+ attributes: Attributes.protected()
813
+ });
814
+ return CentrifugeVaultStatus.fromDto(dto);
815
+ }
816
+ async function buildCentrifugeVaultBuy(api, params) {
817
+ const dto = await api.send({
818
+ method: "POST",
819
+ url: "/v1/centrifuge/vault/invest",
820
+ body: {
821
+ ...walletFields(params),
822
+ amount: params.amount.raw.toString()
823
+ },
824
+ attributes: Attributes.protected()
825
+ });
826
+ if (dto.spend_input_decimals !== params.amount.decimals) {
827
+ throw new ValidationError(
828
+ `spend_input_decimals: the request was priced in ${dto.spend_input_decimals} decimals but the deposit was sized in ${params.amount.decimals}`
829
+ );
830
+ }
831
+ return CentrifugeVaultBuyTransaction.fromDto(dto);
832
+ }
833
+ async function getCentrifugeVaultPosition(api, params) {
834
+ const dto = await api.send({
835
+ method: "GET",
836
+ url: "/v1/centrifuge/vault/position",
837
+ queryParams: walletFields(params),
838
+ attributes: Attributes.protected()
839
+ });
840
+ return CentrifugeVaultPosition.fromDto(dto);
841
+ }
842
+ async function getCentrifugeVaultRedeemPosition(api, params) {
843
+ const dto = await api.send({
844
+ method: "GET",
845
+ url: "/v1/centrifuge/vault/redeem-position",
846
+ queryParams: walletFields(params),
847
+ attributes: Attributes.protected()
848
+ });
849
+ return CentrifugeVaultRedeemPosition.fromDto(dto);
850
+ }
851
+ async function createCentrifugeVaultClaim(api, params) {
852
+ const dto = await api.send({
853
+ method: "POST",
854
+ url: "/v1/centrifuge/vault/claim",
855
+ body: walletFields(params),
856
+ attributes: Attributes.protected()
857
+ });
858
+ return CentrifugeVaultClaimTransaction.fromDto(dto);
859
+ }
860
+ async function createCentrifugeVaultClaimProceeds(api, params) {
861
+ const dto = await api.send({
862
+ method: "POST",
863
+ url: "/v1/centrifuge/vault/claim-proceeds",
864
+ body: walletFields(params),
865
+ attributes: Attributes.protected()
866
+ });
867
+ return CentrifugeVaultClaimProceedsTransaction.fromDto(dto);
868
+ }
869
+ function walletFields(params) {
870
+ return {
871
+ symbol: params.symbol,
872
+ chain: params.chain,
873
+ wallet_address: params.walletAddress
874
+ };
875
+ }
876
+
877
+ // src/universal/core/shared/observability/log-cause.ts
878
+ import {
879
+ BaseError,
880
+ ContractFunctionExecutionError,
881
+ ContractFunctionRevertedError,
882
+ HttpRequestError,
883
+ RpcError,
884
+ SocketClosedError,
885
+ TimeoutError,
886
+ WebSocketRequestError
887
+ } from "viem";
888
+ function classifyLogCause(error) {
889
+ if (error instanceof HttpError) {
890
+ return httpCause(error);
891
+ }
892
+ if (error instanceof ValidationError) {
893
+ return { type: "validation", message: error.message };
894
+ }
895
+ if (error instanceof InvariantError) {
896
+ return { type: "invariant", message: error.message };
897
+ }
898
+ if (error instanceof MathError) {
899
+ return { type: "math", message: error.message };
900
+ }
901
+ if (error instanceof NotAuthenticatedError) {
902
+ return { type: "not-authenticated" };
903
+ }
904
+ if (error instanceof NotImplementedError) {
905
+ return { type: "not-implemented" };
906
+ }
907
+ if (error instanceof BaseError) {
908
+ const http = error.walk((e) => e instanceof HttpError);
909
+ if (http instanceof HttpError) {
910
+ return httpCause(http);
911
+ }
912
+ return { type: "rpc", reason: rpcFailureReason(error) };
913
+ }
914
+ return { type: "generic-error", name: errorName(error) };
915
+ }
916
+ function rpcFailureReason(error) {
917
+ if (error.walk((e) => e instanceof ContractFunctionRevertedError)) {
918
+ return "reverted";
919
+ }
920
+ if (error.walk((e) => e instanceof RpcError)) {
921
+ return "node-rejected";
922
+ }
923
+ if (error.walk(
924
+ (e) => e instanceof HttpRequestError || e instanceof WebSocketRequestError || e instanceof SocketClosedError || e instanceof TimeoutError
925
+ )) {
926
+ return "transport";
927
+ }
928
+ if (error instanceof ContractFunctionExecutionError) {
929
+ return "malformed-response";
930
+ }
931
+ return "unknown";
932
+ }
933
+ function describeErrorUnredacted(error) {
934
+ if (error instanceof HttpError) {
935
+ return describeHttpErrorRedacted(error);
936
+ }
937
+ if (error instanceof Error) {
938
+ return `${error.name}: ${error.message}`;
939
+ }
940
+ return `thrown non-error: ${stringifyUnredacted(error)}`;
941
+ }
942
+ function stringifyUnredacted(value) {
943
+ if (value === void 0) return "";
944
+ try {
945
+ return JSON.stringify(
946
+ value,
947
+ (_key, item) => typeof item === "bigint" ? `${item}` : item
948
+ ) ?? String(value);
949
+ } catch (_) {
950
+ return "<unserializable>";
951
+ }
952
+ }
953
+ function describeHttpErrorRedacted(error) {
954
+ const code = apiErrorCode(error);
955
+ const status = error.response.status;
956
+ return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
957
+ }
958
+ function errorName(error) {
959
+ return error instanceof Error ? error.name : `non-error ${typeof error}`;
960
+ }
961
+ function httpCause(error) {
962
+ return {
963
+ type: "http",
964
+ requestId: error.requestId,
965
+ status: error.response.status,
966
+ code: apiErrorCode(error),
967
+ eventId: apiErrorEventId(error)
968
+ };
969
+ }
970
+ function apiErrorEventId(error) {
971
+ const body = error.response.body;
972
+ if (typeof body !== "object" || body === null) return null;
973
+ const eventId = body.event_id;
974
+ return typeof eventId === "string" ? eventId : null;
975
+ }
976
+
977
+ // src/universal/core/shared/observability/internal-logger.ts
978
+ function internalLogger(logger, scope) {
979
+ return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
980
+ }
981
+ var LEVEL_RANK = {
982
+ none: 0,
983
+ error: 1,
984
+ warn: 2,
985
+ info: 3,
986
+ debug: 4
987
+ };
988
+ function scopedLogger(logger, scope, bindings) {
989
+ const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
990
+ const safe = (event) => ({
991
+ msg: event.msg,
992
+ scope,
993
+ bindings,
994
+ fields: event.fields ?? {},
995
+ ...event.cause === void 0 ? {} : { cause: event.cause }
996
+ });
997
+ const unredacted = (event) => ({
998
+ msg: event.msg,
999
+ scope,
1000
+ bindings,
1001
+ fields: event.fields ?? {}
1002
+ });
1003
+ const self = {
1004
+ child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
1005
+ debug: (event) => {
1006
+ if (admits("debug")) logger.debug(() => unredacted(event()));
1007
+ },
1008
+ info: (event) => {
1009
+ if (admits("info")) logger.info(() => safe(event()));
1010
+ },
1011
+ warn: (event) => {
1012
+ if (admits("warn")) logger.warn(() => safe(event()));
1013
+ },
1014
+ error: (event) => {
1015
+ if (admits("error")) logger.error(() => safe(event()));
1016
+ },
1017
+ failure: (event, error) => {
1018
+ if (admits("debug"))
1019
+ logger.debug(() => unredacted(verbatim(event(), error)));
1020
+ if (admits("error")) logger.error(() => safe(classified(event(), error)));
1021
+ },
1022
+ warning: (event, error) => {
1023
+ if (admits("debug"))
1024
+ logger.debug(() => unredacted(verbatim(event(), error)));
1025
+ if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
1026
+ },
1027
+ wrap: async (op, params, run) => {
1028
+ const opLog = self.child({ op });
1029
+ opLog.debug(() => ({ msg: "call", fields: { params } }));
1030
+ try {
1031
+ return await run();
1032
+ } catch (error) {
1033
+ opLog.failure(() => ({ msg: "call failed" }), error);
1034
+ throw error;
1035
+ }
1036
+ }
1037
+ };
1038
+ return self;
1039
+ }
1040
+ function verbatim(event, error) {
1041
+ return {
1042
+ msg: event.msg,
1043
+ fields: { ...event.fields, error: describeErrorUnredacted(error) }
1044
+ };
1045
+ }
1046
+ function classified(event, error) {
1047
+ return { ...event, cause: event.cause ?? classifyLogCause(error) };
1048
+ }
1049
+ var noopInternalLogger = {
1050
+ child: () => noopInternalLogger,
1051
+ debug: () => void 0,
1052
+ info: () => void 0,
1053
+ warn: () => void 0,
1054
+ error: () => void 0,
1055
+ failure: () => void 0,
1056
+ warning: () => void 0,
1057
+ wrap: (_op, _params, run) => run()
1058
+ };
1059
+
1060
+ // src/universal/core/checkout/centrifuge/centrifuge-namespace.ts
1061
+ var CentrifugeNamespaceImpl = class {
1062
+ constructor(ctx) {
1063
+ this.ctx = ctx;
1064
+ this.log = internalLogger(ctx.logger, "CENTRIFUGE");
1065
+ }
1066
+ async getVaultStatus(params) {
1067
+ return this.log.wrap("getVaultStatus", params, async () => {
1068
+ await this.ctx.ensureUserAuthenticated();
1069
+ return getCentrifugeVaultStatus(this.ctx.api, params);
1070
+ });
1071
+ }
1072
+ async getPosition(params) {
1073
+ return this.log.wrap("getPosition", params, async () => {
1074
+ await this.ctx.ensureUserAuthenticated();
1075
+ return getCentrifugeVaultPosition(this.ctx.api, params);
1076
+ });
1077
+ }
1078
+ async getRedeemPosition(params) {
1079
+ return this.log.wrap("getRedeemPosition", params, async () => {
1080
+ await this.ctx.ensureUserAuthenticated();
1081
+ return getCentrifugeVaultRedeemPosition(this.ctx.api, params);
1082
+ });
1083
+ }
1084
+ async createClaim(params) {
1085
+ return this.log.wrap("createClaim", params, async () => {
1086
+ await this.ctx.ensureUserAuthenticated();
1087
+ return createCentrifugeVaultClaim(this.ctx.api, params);
1088
+ });
1089
+ }
1090
+ async createClaimProceeds(params) {
1091
+ return this.log.wrap("createClaimProceeds", params, async () => {
1092
+ await this.ctx.ensureUserAuthenticated();
1093
+ return createCentrifugeVaultClaimProceeds(this.ctx.api, params);
1094
+ });
1095
+ }
1096
+ async buildBuyTransaction(params) {
1097
+ return this.log.wrap("buildBuyTransaction", params, async () => {
1098
+ await this.ctx.ensureUserAuthenticated();
1099
+ return buildCentrifugeVaultBuy(this.ctx.api, params);
1100
+ });
1101
+ }
1102
+ };
1103
+
1104
+ // src/universal/api/pagination.ts
1105
+ async function fetchAllPages(fetchPage, baseParams) {
1106
+ const items = [];
1107
+ let cursor = null;
1108
+ do {
1109
+ const params = {
1110
+ ...baseParams ?? {},
1111
+ after: cursor ?? void 0
1112
+ };
1113
+ const page = await fetchPage(params);
1114
+ items.push(...page.data);
1115
+ cursor = page.startingAfter;
1116
+ } while (cursor);
1117
+ return items;
1118
+ }
1119
+
1120
+ // src/universal/types/pagination.ts
1121
+ var Cursor = (value) => value;
1122
+ var PaginatedResponse = {
1123
+ fromDto: (dto, itemMapper) => PaginatedResponse.fromDtoPage(dto, (items) => items.map(itemMapper)),
1124
+ /**
1125
+ * For a mapper that decides the page as a whole - one that drops items it
1126
+ * cannot map, such as `Offer.listFromDto` - rather than item by item. The
1127
+ * cursors are the wire's either way: dropping an item changes what the
1128
+ * page holds, not where the next page starts.
1129
+ */
1130
+ fromDtoPage: (dto, pageMapper) => ({
1131
+ data: pageMapper(dto.data),
1132
+ startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
1133
+ startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
1134
+ })
1135
+ };
1136
+ var PaginationParams = {
1137
+ toQueryParams: (params) => {
1138
+ const queryParams = {};
1139
+ if (params.after) {
1140
+ queryParams.starting_after = params.after;
1141
+ }
1142
+ if (params.before) {
1143
+ queryParams.starting_before = params.before;
1144
+ }
1145
+ if (params.limit) {
1146
+ queryParams.limit = params.limit;
1147
+ }
1148
+ return queryParams;
1149
+ }
1150
+ };
1151
+
1152
+ // src/universal/types/asset.ts
1153
+ var AssetId = (value) => value;
1154
+ var AssetCode = (value) => value;
1155
+ var Asset = {
1156
+ fromDto: (dto) => ({
1157
+ id: AssetId(dto.id),
1158
+ code: AssetCode(dto.code),
1159
+ name: dto.name,
1160
+ fractionalDigits: dto.fractional_digits
1161
+ })
1162
+ };
1163
+
1164
+ // src/universal/types/offer.ts
1165
+ var OfferId = (value) => value;
1166
+ var OfferSlug = (value) => value;
1167
+ var OFFER_TYPES = {
1168
+ "coinlist::token_sale": true,
1169
+ "superstate::swap": true,
1170
+ "ondo::swap": true,
1171
+ "centrifuge::vault": true
1172
+ };
1173
+ var isOfferType = (value) => Object.keys(OFFER_TYPES).includes(value);
1174
+ var OfferEditorial = {
1175
+ /**
1176
+ * `model` prefixes the field in the error (`'Offer'`, `'OfferDetail'`), so
1177
+ * the same three checks name the payload that failed them.
1178
+ */
1179
+ fromDto: (dto, model) => ({
1180
+ tagline: requiredString(dto.tagline, `${model}.tagline`),
1181
+ bannerUrl: requiredString(dto.banner_url, `${model}.banner_url`),
1182
+ startsAt: requiredDate(dto.starts_at, `${model}.starts_at`)
1183
+ })
1184
+ };
1185
+ var Offer = {
1186
+ fromDto: (dto) => {
1187
+ const tokens = requiredArray(dto.tokens, "Offer.tokens");
1188
+ const base2 = {
1189
+ id: OfferId(dto.id),
1190
+ slug: OfferSlug(dto.slug),
1191
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1192
+ tokens: OfferToken.listFromDto(tokens)
1193
+ };
1194
+ switch (dto.type) {
1195
+ case "coinlist::token_sale":
1196
+ return {
1197
+ ...base2,
1198
+ ...OfferEditorial.fromDto(dto, "Offer"),
1199
+ type: dto.type,
1200
+ logoUrl: requiredString(dto.logo_url, "Offer.logo_url")
1201
+ };
1202
+ case "superstate::swap":
1203
+ return {
1204
+ ...base2,
1205
+ ...OfferEditorial.fromDto(dto, "Offer"),
1206
+ type: dto.type,
1207
+ logoUrl: notBlankStringOrNull(dto.logo_url)
1208
+ };
1209
+ // `tagline`, `banner_url` and `starts_at` arrive as `null` and are left
1210
+ // on the wire: copying them would hand every consumer a `startsAt` that
1211
+ // is 1970 for one variant and a date for the others.
1212
+ case "ondo::swap":
1213
+ case "centrifuge::vault":
1214
+ return {
1215
+ ...base2,
1216
+ type: dto.type,
1217
+ logoUrl: notBlankStringOrNull(dto.logo_url)
1218
+ };
1219
+ default:
1220
+ return unknownTypeError(dto, "Offer");
1221
+ }
1222
+ },
1223
+ /**
1224
+ * Maps a page of offers, dropping every offer whose `type` this SDK does not
1225
+ * name. The same reasoning as {@link OfferToken.listFromDto}: a plain `.map`
1226
+ * would throw out of `fromDto` and, through `PaginatedResponse.fromDto`,
1227
+ * reject the whole page, so one offer of an unknown type would blank the
1228
+ * grid for every offer beside it. A single offer fetched by id still
1229
+ * throws, because there is nothing beside it to keep.
1230
+ */
1231
+ listFromDto: (dtos) => dtos.filter((dto) => isOfferType(dto.type)).map(Offer.fromDto)
1232
+ };
1233
+ var OfferToken = {
1234
+ fromDto: (dto) => ({
1235
+ role: dto.role,
1236
+ chain: Chain(dto.chain),
1237
+ address: EvmContractAddress(dto.address)
1238
+ }),
1239
+ /**
1240
+ * Maps an offer's token list, dropping every token on a chain this SDK does
1241
+ * not name. Frontline's chain registry runs ahead of {@link Chain}, and a
1242
+ * plain `.map` would throw out of `Offer.fromDto` and, through
1243
+ * `PaginatedResponse.fromDto`, reject the whole offers page - which is how
1244
+ * one Base token blanked production's offers list. Dropping costs that
1245
+ * token's metadata alone: `coinlist.tokens.get` takes an `EthereumChain`,
1246
+ * so nobody could have looked it up anyway.
1247
+ *
1248
+ * Same shape as `TokenMetadata.fromRegistryDto`.
1249
+ */
1250
+ listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferToken.fromDto)
1251
+ };
1252
+
1253
+ // src/universal/types/trading.ts
1254
+ var Ticker = (value) => value;
1255
+ var Isin = (value) => value;
643
1256
 
644
1257
  // src/universal/types/offer-detail.ts
1258
+ var AsyncOfferDetail = {
1259
+ /**
1260
+ * Narrows an offer fetched generically, e.g. on an offer page, to one with
1261
+ * something to claim.
1262
+ *
1263
+ * An exhaustive `switch` rather than a list of async types, so a new offer
1264
+ * type is a compile error here until someone decides whether it settles
1265
+ * later.
1266
+ */
1267
+ is: (offer) => {
1268
+ switch (offer.type) {
1269
+ case "centrifuge::vault":
1270
+ return true;
1271
+ case "ondo::swap":
1272
+ case "superstate::swap":
1273
+ case "coinlist::token_sale":
1274
+ return false;
1275
+ default: {
1276
+ const exhaustive = offer;
1277
+ return exhaustive;
1278
+ }
1279
+ }
1280
+ }
1281
+ };
645
1282
  var OfferOptionId = (value) => value;
646
1283
  var OfferOptionSlug = (value) => value;
647
1284
  var OfferSwapContract = {
@@ -650,6 +1287,19 @@ var OfferSwapContract = {
650
1287
  address: EvmContractAddress(dto.address)
651
1288
  })
652
1289
  };
1290
+ var OfferVaultContract = {
1291
+ fromDto: (dto) => ({
1292
+ chain: Chain(dto.chain),
1293
+ address: EvmContractAddress(dto.address)
1294
+ }),
1295
+ /**
1296
+ * Drops every proxy on a chain this SDK does not name, as
1297
+ * `OfferToken.listFromDto` does: frontline publishes the full offer-token
1298
+ * chain list, which runs ahead of {@link Chain}, and one unmodelled chain
1299
+ * should not throw away the proxies the SDK can use.
1300
+ */
1301
+ listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferVaultContract.fromDto)
1302
+ };
653
1303
  var OfferDetail = {
654
1304
  fromDto: (dto) => {
655
1305
  const fundingAssets = requiredArray(
@@ -712,6 +1362,18 @@ var OfferDetail = {
712
1362
  "OfferDetail.swap_contracts"
713
1363
  ).map(OfferSwapContract.fromDto)
714
1364
  };
1365
+ // No editorial, as for Ondo. `[]` is fine and a missing key is not, for
1366
+ // the same reason as `swap_contracts`: this is the spender a user
1367
+ // approves.
1368
+ case "centrifuge::vault":
1369
+ return {
1370
+ ...base2,
1371
+ type: dto.type,
1372
+ logoUrl: notBlankStringOrNull(dto.logo_url),
1373
+ vaultContracts: OfferVaultContract.listFromDto(
1374
+ requiredArray(dto.vault_contracts, "OfferDetail.vault_contracts")
1375
+ )
1376
+ };
715
1377
  default:
716
1378
  return unknownTypeError(dto, "OfferDetail");
717
1379
  }
@@ -766,258 +1428,75 @@ var ParticipationsPaginationParams = {
766
1428
  queryParams["filters[0][field]"] = "offer_id";
767
1429
  queryParams["filters[0][op]"] = "==";
768
1430
  queryParams["filters[0][value]"] = params.offerId;
769
- }
770
- return queryParams;
771
- }
772
- };
773
- var Participation = {
774
- /** Maps API DTO shape into the SDK participation domain model. */
775
- fromDto: (dto) => {
776
- const walletAddress = notBlankStringOrNull(dto.wallet_address);
777
- return {
778
- id: ParticipationId(dto.id),
779
- offerId: OfferId(dto.offer_id),
780
- offerOptionId: OfferOptionId(dto.offer_option_id),
781
- status: dto.status,
782
- amount: dto.amount,
783
- displayAmount: dto.amount_string,
784
- asset: Asset.fromDto(dto.asset),
785
- chain: Blockchain(dto.chain),
786
- insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
787
- updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
788
- walletAddress: walletAddress ? WalletAddress(walletAddress) : null
789
- };
790
- }
791
- };
792
- var CreateParticipationParams = {
793
- /** Maps participation creation params into API DTO payload. */
794
- toDto: (params) => ({
795
- offer_id: params.offerId,
796
- offer_option_id: params.offerOptionId,
797
- chain: params.chain,
798
- wallet_address: params.walletAddress,
799
- amount: params.amount,
800
- asset_id: params.assetId,
801
- approval_transaction_hash: params.approvalTransactionHash
802
- })
803
- };
804
-
805
- // src/universal/api/frontline/providers/coin-list/token-sale.ts
806
- async function fetchParticipations(api, offerId) {
807
- return fetchAllPages(
808
- (params) => fetchParticipationsPage(api, params),
809
- { offerId }
810
- );
811
- }
812
- async function fetchParticipationsPage(api, params) {
813
- const pageDto = await api.send({
814
- method: "GET",
815
- url: "/v1/participations",
816
- queryParams: ParticipationsPaginationParams.toQueryParams(params),
817
- attributes: Attributes.protected()
818
- });
819
- return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
820
- }
821
- async function fetchParticipation(api, id) {
822
- const dto = await api.send({
823
- method: "GET",
824
- url: `/v1/participations/${id}`,
825
- attributes: Attributes.protected()
826
- });
827
- return Participation.fromDto(dto);
828
- }
829
- async function createParticipation(api, params) {
830
- const dto = await api.send({
831
- method: "POST",
832
- url: "/v1/participations",
833
- body: CreateParticipationParams.toDto(params),
834
- attributes: Attributes.protected()
835
- });
836
- return Participation.fromDto(dto);
837
- }
838
-
839
- // src/universal/core/shared/observability/log-cause.ts
840
- import {
841
- BaseError,
842
- ContractFunctionExecutionError,
843
- ContractFunctionRevertedError,
844
- HttpRequestError,
845
- RpcError,
846
- SocketClosedError,
847
- TimeoutError,
848
- WebSocketRequestError
849
- } from "viem";
850
- function classifyLogCause(error) {
851
- if (error instanceof HttpError) {
852
- return httpCause(error);
853
- }
854
- if (error instanceof ValidationError) {
855
- return { type: "validation", message: error.message };
856
- }
857
- if (error instanceof InvariantError) {
858
- return { type: "invariant", message: error.message };
859
- }
860
- if (error instanceof MathError) {
861
- return { type: "math", message: error.message };
862
- }
863
- if (error instanceof NotAuthenticatedError) {
864
- return { type: "not-authenticated" };
865
- }
866
- if (error instanceof NotImplementedError) {
867
- return { type: "not-implemented" };
868
- }
869
- if (error instanceof BaseError) {
870
- const http = error.walk((e) => e instanceof HttpError);
871
- if (http instanceof HttpError) {
872
- return httpCause(http);
873
- }
874
- return { type: "rpc", reason: rpcFailureReason(error) };
875
- }
876
- return { type: "generic-error", name: errorName(error) };
877
- }
878
- function rpcFailureReason(error) {
879
- if (error.walk((e) => e instanceof ContractFunctionRevertedError)) {
880
- return "reverted";
881
- }
882
- if (error.walk((e) => e instanceof RpcError)) {
883
- return "node-rejected";
884
- }
885
- if (error.walk(
886
- (e) => e instanceof HttpRequestError || e instanceof WebSocketRequestError || e instanceof SocketClosedError || e instanceof TimeoutError
887
- )) {
888
- return "transport";
889
- }
890
- if (error instanceof ContractFunctionExecutionError) {
891
- return "malformed-response";
892
- }
893
- return "unknown";
894
- }
895
- function describeErrorUnredacted(error) {
896
- if (error instanceof HttpError) {
897
- return describeHttpErrorRedacted(error);
898
- }
899
- if (error instanceof Error) {
900
- return `${error.name}: ${error.message}`;
1431
+ }
1432
+ return queryParams;
901
1433
  }
902
- return `thrown non-error: ${stringifyUnredacted(error)}`;
903
- }
904
- function stringifyUnredacted(value) {
905
- if (value === void 0) return "";
906
- try {
907
- return JSON.stringify(
908
- value,
909
- (_key, item) => typeof item === "bigint" ? `${item}` : item
910
- ) ?? String(value);
911
- } catch (_) {
912
- return "<unserializable>";
1434
+ };
1435
+ var Participation = {
1436
+ /** Maps API DTO shape into the SDK participation domain model. */
1437
+ fromDto: (dto) => {
1438
+ const walletAddress = notBlankStringOrNull(dto.wallet_address);
1439
+ return {
1440
+ id: ParticipationId(dto.id),
1441
+ offerId: OfferId(dto.offer_id),
1442
+ offerOptionId: OfferOptionId(dto.offer_option_id),
1443
+ status: dto.status,
1444
+ amount: dto.amount,
1445
+ displayAmount: dto.amount_string,
1446
+ asset: Asset.fromDto(dto.asset),
1447
+ chain: Blockchain(dto.chain),
1448
+ insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
1449
+ updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
1450
+ walletAddress: walletAddress ? WalletAddress(walletAddress) : null
1451
+ };
913
1452
  }
914
- }
915
- function describeHttpErrorRedacted(error) {
916
- const code = apiErrorCode(error);
917
- const status = error.response.status;
918
- return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
919
- }
920
- function errorName(error) {
921
- return error instanceof Error ? error.name : `non-error ${typeof error}`;
922
- }
923
- function httpCause(error) {
924
- return {
925
- type: "http",
926
- requestId: error.requestId,
927
- status: error.response.status,
928
- code: apiErrorCode(error),
929
- eventId: apiErrorEventId(error)
930
- };
931
- }
932
- function apiErrorEventId(error) {
933
- const body = error.response.body;
934
- if (typeof body !== "object" || body === null) return null;
935
- const eventId = body.event_id;
936
- return typeof eventId === "string" ? eventId : null;
937
- }
1453
+ };
1454
+ var CreateParticipationParams = {
1455
+ /** Maps participation creation params into API DTO payload. */
1456
+ toDto: (params) => ({
1457
+ offer_id: params.offerId,
1458
+ offer_option_id: params.offerOptionId,
1459
+ chain: params.chain,
1460
+ wallet_address: params.walletAddress,
1461
+ amount: params.amount,
1462
+ asset_id: params.assetId,
1463
+ approval_transaction_hash: params.approvalTransactionHash
1464
+ })
1465
+ };
938
1466
 
939
- // src/universal/core/shared/observability/internal-logger.ts
940
- function internalLogger(logger, scope) {
941
- return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
1467
+ // src/universal/api/frontline/providers/coin-list/token-sale.ts
1468
+ async function fetchParticipations(api, offerId) {
1469
+ return fetchAllPages(
1470
+ (params) => fetchParticipationsPage(api, params),
1471
+ { offerId }
1472
+ );
942
1473
  }
943
- var LEVEL_RANK = {
944
- none: 0,
945
- error: 1,
946
- warn: 2,
947
- info: 3,
948
- debug: 4
949
- };
950
- function scopedLogger(logger, scope, bindings) {
951
- const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
952
- const safe = (event) => ({
953
- msg: event.msg,
954
- scope,
955
- bindings,
956
- fields: event.fields ?? {},
957
- ...event.cause === void 0 ? {} : { cause: event.cause }
958
- });
959
- const unredacted = (event) => ({
960
- msg: event.msg,
961
- scope,
962
- bindings,
963
- fields: event.fields ?? {}
1474
+ async function fetchParticipationsPage(api, params) {
1475
+ const pageDto = await api.send({
1476
+ method: "GET",
1477
+ url: "/v1/participations",
1478
+ queryParams: ParticipationsPaginationParams.toQueryParams(params),
1479
+ attributes: Attributes.protected()
964
1480
  });
965
- const self = {
966
- child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
967
- debug: (event) => {
968
- if (admits("debug")) logger.debug(() => unredacted(event()));
969
- },
970
- info: (event) => {
971
- if (admits("info")) logger.info(() => safe(event()));
972
- },
973
- warn: (event) => {
974
- if (admits("warn")) logger.warn(() => safe(event()));
975
- },
976
- error: (event) => {
977
- if (admits("error")) logger.error(() => safe(event()));
978
- },
979
- failure: (event, error) => {
980
- if (admits("debug"))
981
- logger.debug(() => unredacted(verbatim(event(), error)));
982
- if (admits("error")) logger.error(() => safe(classified(event(), error)));
983
- },
984
- warning: (event, error) => {
985
- if (admits("debug"))
986
- logger.debug(() => unredacted(verbatim(event(), error)));
987
- if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
988
- },
989
- wrap: async (op, params, run) => {
990
- const opLog = self.child({ op });
991
- opLog.debug(() => ({ msg: "call", fields: { params } }));
992
- try {
993
- return await run();
994
- } catch (error) {
995
- opLog.failure(() => ({ msg: "call failed" }), error);
996
- throw error;
997
- }
998
- }
999
- };
1000
- return self;
1481
+ return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
1001
1482
  }
1002
- function verbatim(event, error) {
1003
- return {
1004
- msg: event.msg,
1005
- fields: { ...event.fields, error: describeErrorUnredacted(error) }
1006
- };
1483
+ async function fetchParticipation(api, id) {
1484
+ const dto = await api.send({
1485
+ method: "GET",
1486
+ url: `/v1/participations/${id}`,
1487
+ attributes: Attributes.protected()
1488
+ });
1489
+ return Participation.fromDto(dto);
1007
1490
  }
1008
- function classified(event, error) {
1009
- return { ...event, cause: event.cause ?? classifyLogCause(error) };
1491
+ async function createParticipation(api, params) {
1492
+ const dto = await api.send({
1493
+ method: "POST",
1494
+ url: "/v1/participations",
1495
+ body: CreateParticipationParams.toDto(params),
1496
+ attributes: Attributes.protected()
1497
+ });
1498
+ return Participation.fromDto(dto);
1010
1499
  }
1011
- var noopInternalLogger = {
1012
- child: () => noopInternalLogger,
1013
- debug: () => void 0,
1014
- info: () => void 0,
1015
- warn: () => void 0,
1016
- error: () => void 0,
1017
- failure: () => void 0,
1018
- warning: () => void 0,
1019
- wrap: (_op, _params, run) => run()
1020
- };
1021
1500
 
1022
1501
  // src/universal/core/checkout/coin-list/token-sale-namespace.ts
1023
1502
  var CoinListTokenSaleNamespaceImpl = class {
@@ -1069,7 +1548,11 @@ function formatAmount(amount, locale, options) {
1069
1548
  const decimal = formatRawAmount(amount);
1070
1549
  let [integerPart, fractionPart = ""] = decimal.split(".");
1071
1550
  const maxFractionDigits = options?.maxFractionDigits;
1072
- const minFractionDigits = maxFractionDigits !== void 0 ? Math.min(maxFractionDigits, amount.decimals) : Math.min(2, amount.decimals);
1551
+ const minFractionDigits = Math.min(
1552
+ options?.minFractionDigits ?? (maxFractionDigits !== void 0 ? maxFractionDigits : 2),
1553
+ maxFractionDigits ?? amount.decimals,
1554
+ amount.decimals
1555
+ );
1073
1556
  if (maxFractionDigits !== void 0 && fractionPart.length > maxFractionDigits) {
1074
1557
  ({ integerPart, fractionPart } = roundFractionHalfUp(
1075
1558
  integerPart,
@@ -1077,7 +1560,8 @@ function formatAmount(amount, locale, options) {
1077
1560
  maxFractionDigits
1078
1561
  ));
1079
1562
  }
1080
- const fraction = minFractionDigits === 0 ? "" : fractionPart.padEnd(minFractionDigits, "0");
1563
+ const trimmed = fractionPart.replace(/0+$/, "");
1564
+ const fraction = trimmed.padEnd(minFractionDigits, "0");
1081
1565
  const integerFormatted = BigInt(integerPart).toLocaleString(locale);
1082
1566
  if (minFractionDigits === 0 && fraction === "") {
1083
1567
  return FormattedAmountUi(integerFormatted);
@@ -1146,6 +1630,14 @@ function assetAmount(amount, symbol) {
1146
1630
  return FormattedAmountAssetUi(`${amount} ${symbol}`);
1147
1631
  }
1148
1632
  var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
1633
+ var SHARE_MAX_FRACTION_DIGITS = AssetDecimals(6);
1634
+ var SHARE_MIN_FRACTION_DIGITS = AssetDecimals(2);
1635
+ function formatShareAmount(amount, locale) {
1636
+ return formatAmount(amount, locale, {
1637
+ maxFractionDigits: SHARE_MAX_FRACTION_DIGITS,
1638
+ minFractionDigits: SHARE_MIN_FRACTION_DIGITS
1639
+ });
1640
+ }
1149
1641
  var USD_FRACTION_DIGITS = AssetDecimals(2);
1150
1642
  function formattedUsdPrice(amount, locale) {
1151
1643
  if (!amount) return NA_AMOUNT_ASSET_UI;
@@ -1212,66 +1704,6 @@ function explorerBaseUrl(chain) {
1212
1704
  }
1213
1705
  }
1214
1706
 
1215
- // src/universal/core/shared/blockchain/math.ts
1216
- import { parseUnits } from "viem";
1217
- function blockchainAmountFromRawOrThrow({
1218
- label,
1219
- raw,
1220
- decimals
1221
- }) {
1222
- const trimmed = raw.trim();
1223
- if (trimmed === "") {
1224
- throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1225
- }
1226
- let value;
1227
- try {
1228
- value = BigInt(trimmed);
1229
- } catch {
1230
- throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
1231
- }
1232
- try {
1233
- return BlockchainAmount({ raw: assertUint256(value), decimals });
1234
- } catch {
1235
- throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
1236
- }
1237
- }
1238
- function parseBlockchainAmount(amount, decimals) {
1239
- const trimmed = amount.trim();
1240
- if (trimmed === "") return { valid: false, reason: { type: "empty" } };
1241
- if (trimmed.startsWith("-")) {
1242
- return { valid: false, reason: { type: "negative" } };
1243
- }
1244
- if (/[eE]/.test(trimmed)) {
1245
- return { valid: false, reason: { type: "invalid-format" } };
1246
- }
1247
- if (trimmed === ".") {
1248
- return { valid: false, reason: { type: "invalid-format" } };
1249
- }
1250
- const normalised = trimmed.replace(/^\./, "0.").replace(/\.$/, "");
1251
- if (!/^\d+(\.\d+)?$/.test(normalised)) {
1252
- return { valid: false, reason: { type: "invalid-format" } };
1253
- }
1254
- const [, fraction = ""] = normalised.split(".");
1255
- if (fraction.length > decimals) {
1256
- return {
1257
- valid: false,
1258
- reason: { type: "too-many-decimals", maxDecimals: decimals }
1259
- };
1260
- }
1261
- try {
1262
- const raw = parseUnits(normalised, decimals);
1263
- if (raw > MAX_UINT_256) {
1264
- return { valid: false, reason: { type: "overflow" } };
1265
- }
1266
- return {
1267
- valid: true,
1268
- amount: BlockchainAmount({ raw, decimals })
1269
- };
1270
- } catch {
1271
- return { valid: false, reason: { type: "invalid-format" } };
1272
- }
1273
- }
1274
-
1275
1707
  // src/universal/types/providers/ondo/ondo.ts
1276
1708
  var OndoTradingStatus = {
1277
1709
  fromDto: (dto) => {
@@ -1287,7 +1719,6 @@ var OndoTradingStatus = {
1287
1719
  };
1288
1720
  }
1289
1721
  };
1290
- var decimalOrNull = (value) => value === null ? null : DecimalString(value);
1291
1722
  var OndoQuote = {
1292
1723
  fromDto: (dto) => {
1293
1724
  const assetDecimals = AssetDecimals(dto.asset_decimals);
@@ -2944,11 +3375,18 @@ var HttpClient = class {
2944
3375
  );
2945
3376
  let response = await this.executeRequest(preparedRequest);
2946
3377
  for (const middleware of this.middleware.afterRequest ?? []) {
3378
+ let retried = false;
2947
3379
  response = await middleware({
2948
3380
  request: preparedRequest,
2949
3381
  response,
2950
- retry: (nextRequest = preparedRequest) => this.runRequestWithAfterMiddleware(nextRequest)
3382
+ retry: (nextRequest = preparedRequest) => {
3383
+ retried = true;
3384
+ return this.runRequestWithAfterMiddleware(nextRequest);
3385
+ }
2951
3386
  });
3387
+ if (retried) {
3388
+ return response;
3389
+ }
2952
3390
  }
2953
3391
  return response;
2954
3392
  }
@@ -3394,6 +3832,9 @@ export {
3394
3832
  VERIFY_IDENTITY_PATH,
3395
3833
  VERIFY_IDENTITY_ACCREDITATION_PATH,
3396
3834
  WALLET_PATH,
3835
+ SentWith,
3836
+ TokenTrigger,
3837
+ isRejectedToken,
3397
3838
  Attributes,
3398
3839
  HttpError,
3399
3840
  apiErrorCode,
@@ -3406,14 +3847,11 @@ export {
3406
3847
  describeErrorUnredacted,
3407
3848
  internalLogger,
3408
3849
  HttpClient,
3850
+ EpochMillis,
3851
+ Millis,
3852
+ Seconds,
3853
+ isExpired,
3409
3854
  ERC20_ABI,
3410
- fetchAllPages,
3411
- Cursor,
3412
- PaginatedResponse,
3413
- PaginationParams,
3414
- AssetId,
3415
- AssetCode,
3416
- Asset,
3417
3855
  ETHEREUM_CHAINS,
3418
3856
  EthereumChain,
3419
3857
  SOLANA_CHAINS,
@@ -3435,6 +3873,24 @@ export {
3435
3873
  StablecoinSymbol,
3436
3874
  KnownAssetSymbol,
3437
3875
  Bps,
3876
+ blockchainAmountFromRawOrThrow,
3877
+ parseBlockchainAmount,
3878
+ CentrifugeVaultStatus,
3879
+ CentrifugeVaultBuyTransaction,
3880
+ CentrifugeVaultClaimTransaction,
3881
+ CentrifugeVaultPosition,
3882
+ CentrifugeVaultRedeemPosition,
3883
+ CentrifugeVaultLeg,
3884
+ CentrifugeVaultLegId,
3885
+ CentrifugeVaultClaimProceedsTransaction,
3886
+ CentrifugeNamespaceImpl,
3887
+ fetchAllPages,
3888
+ Cursor,
3889
+ PaginatedResponse,
3890
+ PaginationParams,
3891
+ AssetId,
3892
+ AssetCode,
3893
+ Asset,
3438
3894
  OfferId,
3439
3895
  OfferSlug,
3440
3896
  isOfferType,
@@ -3443,9 +3899,11 @@ export {
3443
3899
  OfferToken,
3444
3900
  Ticker,
3445
3901
  Isin,
3902
+ AsyncOfferDetail,
3446
3903
  OfferOptionId,
3447
3904
  OfferOptionSlug,
3448
3905
  OfferSwapContract,
3906
+ OfferVaultContract,
3449
3907
  OfferDetail,
3450
3908
  OfferOption,
3451
3909
  FaqItem,
@@ -3473,14 +3931,13 @@ export {
3473
3931
  usdAmount,
3474
3932
  assetAmount,
3475
3933
  NA_AMOUNT_ASSET_UI,
3934
+ formatShareAmount,
3476
3935
  formattedUsdPrice,
3477
3936
  viemChain,
3478
3937
  getChainId,
3479
3938
  chainFromId,
3480
3939
  getNetworkName,
3481
3940
  txExplorerUrl,
3482
- blockchainAmountFromRawOrThrow,
3483
- parseBlockchainAmount,
3484
3941
  OndoTradingStatus,
3485
3942
  OndoQuote,
3486
3943
  OndoBuyTransaction,
@@ -3521,4 +3978,4 @@ export {
3521
3978
  OAuthRefreshToken,
3522
3979
  OAuthSession
3523
3980
  };
3524
- //# sourceMappingURL=chunk-MOE5S6CE.js.map
3981
+ //# sourceMappingURL=chunk-C6GF7MDF.js.map