@coinlist-co/react 0.12.1-rc.6b77fc6 → 0.12.1-rc.9aec85a

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.
@@ -7,7 +7,7 @@ import {
7
7
  getUUIDv4,
8
8
  internalLogger,
9
9
  viemChain
10
- } from "./chunk-2YEJXE2V.js";
10
+ } from "./chunk-MOE5S6CE.js";
11
11
 
12
12
  // src/universal/api/nabu/config.ts
13
13
  var NABU_BASE_URL = "https://asset.coinlist.co";
@@ -402,4 +402,4 @@ export {
402
402
  SDK_LOGGER_NAME,
403
403
  loggerOverPino
404
404
  };
405
- //# sourceMappingURL=chunk-DOSABR7Q.js.map
405
+ //# sourceMappingURL=chunk-DCW7NQXH.js.map
@@ -328,8 +328,15 @@ async function fetchAllPages(fetchPage, baseParams) {
328
328
  // src/universal/types/pagination.ts
329
329
  var Cursor = (value) => value;
330
330
  var PaginatedResponse = {
331
- fromDto: (dto, itemMapper) => ({
332
- data: dto.data.map(itemMapper),
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),
333
340
  startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
334
341
  startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
335
342
  })
@@ -459,53 +466,6 @@ var StablecoinSymbol = (value) => value;
459
466
  var KnownAssetSymbol = StablecoinSymbol;
460
467
  var Bps = (value) => value;
461
468
 
462
- // src/universal/types/offer.ts
463
- var OfferId = (value) => value;
464
- var OfferSlug = (value) => value;
465
- var Offer = {
466
- fromDto: (dto) => {
467
- if (!Array.isArray(dto.tokens)) {
468
- throw new ValidationError(
469
- `Offer.tokens: expected an array, got ${typeof dto.tokens}`
470
- );
471
- }
472
- return {
473
- id: OfferId(dto.id),
474
- slug: OfferSlug(dto.slug),
475
- type: dto.type,
476
- tagline: dto.tagline,
477
- bannerUrl: dto.banner_url,
478
- logoUrl: dto.logo_url,
479
- startsAt: new Date(dto.starts_at),
480
- endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
481
- tokens: OfferToken.listFromDto(dto.tokens)
482
- };
483
- }
484
- };
485
- var OfferToken = {
486
- fromDto: (dto) => ({
487
- role: dto.role,
488
- chain: Chain(dto.chain),
489
- address: EvmContractAddress(dto.address)
490
- }),
491
- /**
492
- * Maps an offer's token list, dropping every token on a chain this SDK does
493
- * not name. Frontline's chain registry runs ahead of {@link Chain}, and a
494
- * plain `.map` would throw out of `Offer.fromDto` and, through
495
- * `PaginatedResponse.fromDto`, reject the whole offers page - which is how
496
- * one Base token blanked production's offers list. Dropping costs that
497
- * token's metadata alone: `coinlist.tokens.get` takes an `EthereumChain`,
498
- * so nobody could have looked it up anyway.
499
- *
500
- * Same shape as `TokenMetadata.fromRegistryDto`.
501
- */
502
- listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferToken.fromDto)
503
- };
504
-
505
- // src/universal/types/trading.ts
506
- var Ticker = (value) => value;
507
- var Isin = (value) => value;
508
-
509
469
  // src/universal/core/shared/utils/crypto.ts
510
470
  async function sha256(data) {
511
471
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
@@ -556,6 +516,131 @@ function notBlankStringOrNull(value) {
556
516
  }
557
517
  }
558
518
 
519
+ // src/universal/core/shared/utils/wire.ts
520
+ function unknownTypeError(dto, model) {
521
+ const type = dto.type;
522
+ throw new ValidationError(
523
+ `${model}.type: unknown type ${JSON.stringify(type)}`
524
+ );
525
+ }
526
+ function requiredString(value, field) {
527
+ const text = notBlankStringOrNull(value);
528
+ if (text === null) {
529
+ throw new ValidationError(
530
+ `${field}: expected a non-blank string, got ${typeof value === "string" ? "a blank string" : String(value)}`
531
+ );
532
+ }
533
+ return text;
534
+ }
535
+ function requiredDate(value, field) {
536
+ const date = typeof value === "string" ? new Date(value) : null;
537
+ if (date === null || Number.isNaN(date.getTime())) {
538
+ throw new ValidationError(
539
+ `${field}: expected a date, got ${JSON.stringify(value)}`
540
+ );
541
+ }
542
+ return date;
543
+ }
544
+ function requiredArray(value, field) {
545
+ if (!Array.isArray(value)) {
546
+ throw new ValidationError(
547
+ `${field}: expected an array, got ${typeof value}`
548
+ );
549
+ }
550
+ return value;
551
+ }
552
+
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
560
+ };
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`)
571
+ })
572
+ };
573
+ var Offer = {
574
+ 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)
581
+ };
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)
619
+ };
620
+ var OfferToken = {
621
+ fromDto: (dto) => ({
622
+ role: dto.role,
623
+ chain: Chain(dto.chain),
624
+ address: EvmContractAddress(dto.address)
625
+ }),
626
+ /**
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`.
636
+ */
637
+ listFromDto: (dtos) => dtos.filter((dto) => isChain(dto.chain)).map(OfferToken.fromDto)
638
+ };
639
+
640
+ // src/universal/types/trading.ts
641
+ var Ticker = (value) => value;
642
+ var Isin = (value) => value;
643
+
559
644
  // src/universal/types/offer-detail.ts
560
645
  var OfferOptionId = (value) => value;
561
646
  var OfferOptionSlug = (value) => value;
@@ -567,76 +652,69 @@ var OfferSwapContract = {
567
652
  };
568
653
  var OfferDetail = {
569
654
  fromDto: (dto) => {
570
- if (!Array.isArray(dto.funding_assets)) {
571
- throw new ValidationError(
572
- `OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
573
- );
574
- }
575
- if (!Array.isArray(dto.options)) {
576
- throw new ValidationError(
577
- `OfferDetail.options: expected an array, got ${typeof dto.options}`
578
- );
579
- }
580
- if (!Array.isArray(dto.terms)) {
581
- throw new ValidationError(
582
- `OfferDetail.terms: expected an array, got ${typeof dto.terms}`
583
- );
584
- }
585
- if (!Array.isArray(dto.links)) {
586
- throw new ValidationError(
587
- `OfferDetail.links: expected an array, got ${typeof dto.links}`
588
- );
589
- }
590
- if (!Array.isArray(dto.faqs)) {
591
- throw new ValidationError(
592
- `OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
593
- );
594
- }
595
- if (!Array.isArray(dto.milestones)) {
596
- throw new ValidationError(
597
- `OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
598
- );
599
- }
600
- if (!Array.isArray(dto.tokens)) {
601
- throw new ValidationError(
602
- `OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
603
- );
604
- }
605
- const swapContracts = dto.swap_contracts === void 0 ? [] : dto.swap_contracts;
606
- if (!Array.isArray(swapContracts)) {
607
- throw new ValidationError(
608
- `OfferDetail.swap_contracts: expected an array, got ${typeof swapContracts}`
609
- );
610
- }
655
+ const fundingAssets = requiredArray(
656
+ dto.funding_assets,
657
+ "OfferDetail.funding_assets"
658
+ );
659
+ const options = requiredArray(dto.options, "OfferDetail.options");
660
+ const terms = requiredArray(dto.terms, "OfferDetail.terms");
661
+ const links = requiredArray(dto.links, "OfferDetail.links");
662
+ const faqs = requiredArray(dto.faqs, "OfferDetail.faqs");
663
+ const milestones = requiredArray(dto.milestones, "OfferDetail.milestones");
664
+ const tokens = requiredArray(dto.tokens, "OfferDetail.tokens");
611
665
  const isin = notBlankStringOrNull(dto.isin);
612
666
  const ticker = notBlankStringOrNull(dto.ticker);
613
- return {
667
+ const base2 = {
614
668
  id: OfferId(dto.id),
615
669
  slug: OfferSlug(dto.slug),
616
- type: dto.type,
617
670
  name: dto.name,
618
671
  asset: Asset.fromDto(dto.asset),
619
- fundingAssets: dto.funding_assets.map(Asset.fromDto),
620
- tokens: OfferToken.listFromDto(dto.tokens),
621
- swapContracts: swapContracts.map(OfferSwapContract.fromDto),
672
+ fundingAssets: fundingAssets.map(Asset.fromDto),
673
+ tokens: OfferToken.listFromDto(tokens),
622
674
  about: notBlankStringOrNull(dto.about),
623
- tagline: dto.tagline,
624
- bannerUrl: dto.banner_url,
625
- logoUrl: dto.logo_url,
626
675
  category: dto.category,
627
676
  issuer: notBlankStringOrNull(dto.issuer),
628
677
  isin: isin === null ? null : Isin(isin),
629
678
  ticker: ticker === null ? null : Ticker(ticker),
630
679
  instrumentType: notBlankStringOrNull(dto.instrument_type),
631
680
  listingVenue: notBlankStringOrNull(dto.listing_venue),
632
- startsAt: new Date(dto.starts_at),
633
681
  endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
634
- faqs: dto.faqs.map(FaqItem.fromDto),
635
- links: dto.links.map(Link.fromDto),
636
- milestones: dto.milestones.map(Milestone.fromDto),
637
- options: dto.options.map(OfferOption.fromDto),
638
- terms: dto.terms.map(TermItem.fromDto)
682
+ faqs: faqs.map(FaqItem.fromDto),
683
+ links: links.map(Link.fromDto),
684
+ milestones: milestones.map(Milestone.fromDto),
685
+ options: options.map(OfferOption.fromDto),
686
+ terms: terms.map(TermItem.fromDto)
639
687
  };
688
+ switch (dto.type) {
689
+ case "coinlist::token_sale":
690
+ return {
691
+ ...base2,
692
+ ...OfferEditorial.fromDto(dto, "OfferDetail"),
693
+ type: dto.type,
694
+ logoUrl: requiredString(dto.logo_url, "OfferDetail.logo_url")
695
+ };
696
+ case "superstate::swap":
697
+ return {
698
+ ...base2,
699
+ ...OfferEditorial.fromDto(dto, "OfferDetail"),
700
+ type: dto.type,
701
+ logoUrl: notBlankStringOrNull(dto.logo_url)
702
+ };
703
+ // `tagline`, `banner_url` and `starts_at` arrive as `null` and are left
704
+ // on the wire, as in `Offer.fromDto`.
705
+ case "ondo::swap":
706
+ return {
707
+ ...base2,
708
+ type: dto.type,
709
+ logoUrl: notBlankStringOrNull(dto.logo_url),
710
+ swapContracts: requiredArray(
711
+ dto.swap_contracts,
712
+ "OfferDetail.swap_contracts"
713
+ ).map(OfferSwapContract.fromDto)
714
+ };
715
+ default:
716
+ return unknownTypeError(dto, "OfferDetail");
717
+ }
640
718
  }
641
719
  };
642
720
  var OfferOption = {
@@ -1166,10 +1244,14 @@ function parseBlockchainAmount(amount, decimals) {
1166
1244
  if (/[eE]/.test(trimmed)) {
1167
1245
  return { valid: false, reason: { type: "invalid-format" } };
1168
1246
  }
1169
- if (!/^\d+(\.\d+)?$/.test(trimmed)) {
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)) {
1170
1252
  return { valid: false, reason: { type: "invalid-format" } };
1171
1253
  }
1172
- const [, fraction = ""] = trimmed.split(".");
1254
+ const [, fraction = ""] = normalised.split(".");
1173
1255
  if (fraction.length > decimals) {
1174
1256
  return {
1175
1257
  valid: false,
@@ -1177,7 +1259,7 @@ function parseBlockchainAmount(amount, decimals) {
1177
1259
  };
1178
1260
  }
1179
1261
  try {
1180
- const raw = parseUnits(trimmed, decimals);
1262
+ const raw = parseUnits(normalised, decimals);
1181
1263
  if (raw > MAX_UINT_256) {
1182
1264
  return { valid: false, reason: { type: "overflow" } };
1183
1265
  }
@@ -3283,7 +3365,7 @@ async function fetchOffersPage(api, params, clientCreds) {
3283
3365
  Attributes.clientCredentials(clientCreds)
3284
3366
  )
3285
3367
  });
3286
- return PaginatedResponse.fromDto(pageDto, Offer.fromDto);
3368
+ return PaginatedResponse.fromDtoPage(pageDto, Offer.listFromDto);
3287
3369
  }
3288
3370
  async function fetchOfferDetails(api, id, clientCreds) {
3289
3371
  const dto = await api.send({
@@ -3355,6 +3437,8 @@ export {
3355
3437
  Bps,
3356
3438
  OfferId,
3357
3439
  OfferSlug,
3440
+ isOfferType,
3441
+ OfferEditorial,
3358
3442
  Offer,
3359
3443
  OfferToken,
3360
3444
  Ticker,
@@ -3437,4 +3521,4 @@ export {
3437
3521
  OAuthRefreshToken,
3438
3522
  OAuthSession
3439
3523
  };
3440
- //# sourceMappingURL=chunk-2YEJXE2V.js.map
3524
+ //# sourceMappingURL=chunk-MOE5S6CE.js.map