@unicitylabs/sphere-sdk 0.17.2-dev.1 → 0.17.2-dev.3

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 (47) hide show
  1. package/dist/connect/index.cjs +202 -8
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.d.cts +81 -4
  4. package/dist/connect/index.d.ts +81 -4
  5. package/dist/connect/index.js +202 -8
  6. package/dist/connect/index.js.map +1 -1
  7. package/dist/core/index.cjs +48 -21
  8. package/dist/core/index.cjs.map +1 -1
  9. package/dist/core/index.d.cts +2 -0
  10. package/dist/core/index.d.ts +2 -0
  11. package/dist/core/index.js +48 -21
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/impl/browser/connect/index.cjs +17 -5
  14. package/dist/impl/browser/connect/index.cjs.map +1 -1
  15. package/dist/impl/browser/connect/index.d.cts +3 -1
  16. package/dist/impl/browser/connect/index.d.ts +3 -1
  17. package/dist/impl/browser/connect/index.js +17 -5
  18. package/dist/impl/browser/connect/index.js.map +1 -1
  19. package/dist/impl/nodejs/connect/index.cjs +16 -4
  20. package/dist/impl/nodejs/connect/index.cjs.map +1 -1
  21. package/dist/impl/nodejs/connect/index.d.cts +1 -1
  22. package/dist/impl/nodejs/connect/index.d.ts +1 -1
  23. package/dist/impl/nodejs/connect/index.js +16 -4
  24. package/dist/impl/nodejs/connect/index.js.map +1 -1
  25. package/dist/impl/wallet-api-v2/index.cjs +3 -0
  26. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  27. package/dist/impl/wallet-api-v2/index.js +3 -0
  28. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  29. package/dist/index.cjs +67 -21
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +22 -1
  32. package/dist/index.d.ts +22 -1
  33. package/dist/index.js +64 -21
  34. package/dist/index.js.map +1 -1
  35. package/dist/modules/payments-v2/index.cjs +40 -6
  36. package/dist/modules/payments-v2/index.cjs.map +1 -1
  37. package/dist/modules/payments-v2/index.d.cts +22 -1
  38. package/dist/modules/payments-v2/index.d.ts +22 -1
  39. package/dist/modules/payments-v2/index.js +37 -6
  40. package/dist/modules/payments-v2/index.js.map +1 -1
  41. package/dist/token-engine/index.cjs +67 -21
  42. package/dist/token-engine/index.cjs.map +1 -1
  43. package/dist/token-engine/index.d.cts +28 -4
  44. package/dist/token-engine/index.d.ts +28 -4
  45. package/dist/token-engine/index.js +64 -21
  46. package/dist/token-engine/index.js.map +1 -1
  47. package/package.json +1 -1
@@ -36,6 +36,7 @@ __export(payments_v2_exports, {
36
36
  HEARTBEAT_CAP_MS: () => HEARTBEAT_CAP_MS,
37
37
  HEARTBEAT_SEED_MS: () => HEARTBEAT_SEED_MS,
38
38
  MAX_RESELECT: () => MAX_RESELECT,
39
+ NFT_DOCUMENT_MEDIA_TYPE: () => NFT_DOCUMENT_MEDIA_TYPE,
39
40
  NFT_LINK_TAG: () => NFT_LINK_TAG,
40
41
  NFT_MAX_PAYLOAD_BYTES: () => NFT_MAX_PAYLOAD_BYTES,
41
42
  NFT_MEDIA_TAG: () => NFT_MEDIA_TAG,
@@ -45,7 +46,9 @@ __export(payments_v2_exports, {
45
46
  STORE_KEYS: () => STORE_KEYS,
46
47
  createScopedKV: () => createScopedKV,
47
48
  encodeNftContent: () => encodeNftContent,
49
+ isNftDocumentLink: () => isNftDocumentLink,
48
50
  isRetryableAckError: () => isRetryableAckError,
51
+ parseNftDocument: () => parseNftDocument,
49
52
  parseNftPayload: () => parseNftPayload,
50
53
  supportsDeterministicMint: () => supportsDeterministicMint,
51
54
  sweepSupersededState: () => sweepSupersededState,
@@ -509,7 +512,8 @@ var NFT_MEDIA_TAG = 39053n;
509
512
  var NFT_LINK_TAG = 39054n;
510
513
  var NFT_SIGNED_TAG = 39055n;
511
514
  var NFT_FORMAT_VERSION = 1n;
512
- var METADATA_ARITY = 8;
515
+ var NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
516
+ var METADATA_ARITY = 9;
513
517
  var MEDIA_ARITY = 3;
514
518
  var LINK_ARITY = 4;
515
519
  var SIGNED_ARITY = 4;
@@ -517,11 +521,15 @@ var CREATOR_BYTES = 33;
517
521
  var SIGNATURE_BYTES = 65;
518
522
  var MAX_URI_LENGTH = 2048;
519
523
  var LINK_SCHEMES = ["https://", "ipfs://", "ar://"];
524
+ var SIGNED_DOMAIN = new TextEncoder().encode("UNICITY_NFT_SIGNED");
520
525
  var MEDIA_TYPE_PATTERN = /^[a-z0-9][a-z0-9!#$&^_.+-]{0,126}\/[a-z0-9][a-z0-9!#$&^_.+-]{0,126}$/;
521
526
  var SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/i;
527
+ var COLLECTION_ID_PATTERN = /^(?:[0-9a-f]{2}){1,64}$/i;
522
528
  var LONE_SURROGATE = /\p{Cs}/u;
523
529
  var CBOR_MAJOR_TYPE_MASK = 224;
524
530
  var ATTRIBUTE_VALUE_RULE = "must be non-empty text or an integer within \xB1(2^53 \u2212 1) \u2014 write decimals and larger numbers as text";
531
+ var COLLECTION_ID_RULE = "must be null or 1\u201364 bytes as even-length hex (2\u2013128 characters)";
532
+ var DOCUMENT_AS_MEDIA_RULE = `must not be ${NFT_DOCUMENT_MEDIA_TYPE}: a document link is a token's content, never media`;
525
533
  var UTF8 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
526
534
  function refuse(field, rule, cause) {
527
535
  return new SphereError(`Invalid NFT ${field}: ${rule}`, "VALIDATION_ERROR", cause);
@@ -533,6 +541,7 @@ var fieldName = (prefix, name) => prefix === "" ? name : `${prefix}.${name}`;
533
541
  var isText = (value) => typeof value === "string" && value.length > 0 && !LONE_SURROGATE.test(value);
534
542
  var isBytes2 = (value, length) => value instanceof Uint8Array && (length === void 0 ? value.length > 0 : value.length === length);
535
543
  var isMediaType = (value) => typeof value === "string" && MEDIA_TYPE_PATTERN.test(value);
544
+ var isCollectionId = (value) => typeof value === "string" && COLLECTION_ID_PATTERN.test(value);
536
545
  var isAttributeValue = (value) => typeof value === "number" ? Number.isSafeInteger(value) : isText(value);
537
546
  function hasSpaceOrControl(value) {
538
547
  for (let i = 0; i < value.length; i++) {
@@ -575,8 +584,9 @@ function checkLink(prefix, link) {
575
584
  function checkMediaRef(field, ref) {
576
585
  if (ref === null) return;
577
586
  if (ref?.kind === "media") return checkMedia(field, ref);
578
- if (ref?.kind === "link") return checkLink(field, ref);
579
- throw refuse(field, "must be an NftMedia, an NftLink or null");
587
+ if (ref?.kind !== "link") throw refuse(field, "must be an NftMedia, an NftLink or null");
588
+ checkLink(field, ref);
589
+ ensure(!isNftDocumentLink(ref), fieldName(field, "media_type"), DOCUMENT_AS_MEDIA_RULE);
580
590
  }
581
591
  function checkAttributes(attributes) {
582
592
  ensure(Array.isArray(attributes), "attributes", "must be an array \u2014 [] when there are none");
@@ -593,6 +603,7 @@ function checkMetadata(metadata) {
593
603
  checkOptionalText("external_url", metadata.external_url);
594
604
  checkAttributes(metadata.attributes);
595
605
  checkOptionalText("collection", metadata.collection);
606
+ ensure(metadata.collection_id === null || isCollectionId(metadata.collection_id), "collection_id", COLLECTION_ID_RULE);
596
607
  }
597
608
  function checkContent(content) {
598
609
  switch (content?.kind) {
@@ -650,6 +661,7 @@ function arrayCbor(items) {
650
661
  }
651
662
  return out;
652
663
  }
664
+ var optionalHexBytes = (value) => import_CborSerializer.CborSerializer.encodeNullable(value, (hex) => import_CborSerializer.CborSerializer.encodeByteString(import_HexConverter.HexConverter.decode(hex.toLowerCase())));
653
665
  function metadataCbor(metadata) {
654
666
  return versioned(
655
667
  NFT_METADATA_TAG,
@@ -659,7 +671,8 @@ function metadataCbor(metadata) {
659
671
  mediaRefCbor(metadata.animation_url),
660
672
  optionalText(metadata.external_url),
661
673
  arrayCbor(metadata.attributes.map(attributeCbor)),
662
- optionalText(metadata.collection)
674
+ optionalText(metadata.collection),
675
+ optionalHexBytes(metadata.collection_id)
663
676
  );
664
677
  }
665
678
  function encodeNftContent(content) {
@@ -700,13 +713,14 @@ function decodeMedia(body) {
700
713
  const [, mediaType, bytes] = versionedFields(body, MEDIA_ARITY);
701
714
  return { kind: "media", media_type: decodeText(mediaType), bytes: import_CborDeserializer.CborDeserializer.decodeByteString(bytes) };
702
715
  }
716
+ var decodeHex = (item) => import_HexConverter.HexConverter.encode(import_CborDeserializer.CborDeserializer.decodeByteString(item));
703
717
  function decodeLink(body) {
704
718
  const [, mediaType, uri, digest] = versionedFields(body, LINK_ARITY);
705
719
  return {
706
720
  kind: "link",
707
721
  media_type: decodeText(mediaType),
708
722
  uri: decodeText(uri),
709
- sha256: import_HexConverter.HexConverter.encode(import_CborDeserializer.CborDeserializer.decodeByteString(digest))
723
+ sha256: decodeHex(digest)
710
724
  };
711
725
  }
712
726
  function decodeMetadata(body) {
@@ -719,7 +733,8 @@ function decodeMetadata(body) {
719
733
  animation_url: decodeMediaRef("animation_url", fields[4]),
720
734
  external_url: decodeOptionalText(fields[5]),
721
735
  attributes: decodeAttributes(fields[6]),
722
- collection: decodeOptionalText(fields[7])
736
+ collection: decodeOptionalText(fields[7]),
737
+ collection_id: import_CborDeserializer.CborDeserializer.decodeNullable(fields[8], decodeHex)
723
738
  };
724
739
  }
725
740
  var MEDIA_REF_DECODERS = /* @__PURE__ */ new Map([
@@ -731,6 +746,10 @@ var UNSIGNED_DECODERS = /* @__PURE__ */ new Map([
731
746
  [NFT_MEDIA_TAG, decodeMedia],
732
747
  [NFT_LINK_TAG, decodeLink]
733
748
  ]);
749
+ var DOCUMENT_DECODERS = /* @__PURE__ */ new Map([
750
+ [NFT_METADATA_TAG, decodeMetadata],
751
+ [NFT_MEDIA_TAG, decodeMedia]
752
+ ]);
734
753
  function decodeBody(decoders, field, tag, body) {
735
754
  const decode = decoders.get(tag);
736
755
  if (decode === void 0) throw refuse(field, `tag ${tag} is not allowed here`);
@@ -765,6 +784,18 @@ function parseNftPayload(data) {
765
784
  return null;
766
785
  }
767
786
  }
787
+ function parseNftDocument(bytes) {
788
+ try {
789
+ const document = decodeItem(DOCUMENT_DECODERS, "document", bytes);
790
+ checkContent(document);
791
+ return document;
792
+ } catch {
793
+ return null;
794
+ }
795
+ }
796
+ function isNftDocumentLink(content) {
797
+ return content?.kind === "link" && content.media_type === NFT_DOCUMENT_MEDIA_TYPE;
798
+ }
768
799
  function verifyNftLinkContent(link, bytes) {
769
800
  return import_HexConverter.HexConverter.encode(sha256(bytes)) === link.sha256.toLowerCase();
770
801
  }
@@ -5793,6 +5824,7 @@ var PaymentsFacade = class {
5793
5824
  HEARTBEAT_CAP_MS,
5794
5825
  HEARTBEAT_SEED_MS,
5795
5826
  MAX_RESELECT,
5827
+ NFT_DOCUMENT_MEDIA_TYPE,
5796
5828
  NFT_LINK_TAG,
5797
5829
  NFT_MAX_PAYLOAD_BYTES,
5798
5830
  NFT_MEDIA_TAG,
@@ -5802,7 +5834,9 @@ var PaymentsFacade = class {
5802
5834
  STORE_KEYS,
5803
5835
  createScopedKV,
5804
5836
  encodeNftContent,
5837
+ isNftDocumentLink,
5805
5838
  isRetryableAckError,
5839
+ parseNftDocument,
5806
5840
  parseNftPayload,
5807
5841
  supportsDeterministicMint,
5808
5842
  sweepSupersededState,