@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
@@ -4,6 +4,8 @@ declare const NFT_METADATA_TAG = 39052n;
4
4
  declare const NFT_MEDIA_TAG = 39053n;
5
5
  declare const NFT_LINK_TAG = 39054n;
6
6
  declare const NFT_SIGNED_TAG = 39055n;
7
+ /** The media type of an NftLink that points at a metadata document instead of a media file. */
8
+ declare const NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
7
9
  /** An inline file. */
8
10
  interface NftMedia {
9
11
  readonly kind: 'media';
@@ -33,6 +35,8 @@ interface NftMetadata {
33
35
  readonly external_url: string | null;
34
36
  readonly attributes: readonly NftAttribute[];
35
37
  readonly collection: string | null;
38
+ /** The collection the item claims: 1–64 bytes as even-length hex (decoded lowercase). Never verified here. */
39
+ readonly collection_id: string | null;
36
40
  }
37
41
  type NftContent = NftMetadata | NftMedia | NftLink;
38
42
  type NftSignatureStatus = 'unsigned' | 'valid' | 'invalid';
@@ -45,10 +49,27 @@ interface ParsedNft {
45
49
  readonly signature: Uint8Array;
46
50
  } | null;
47
51
  }
52
+ /** What an NftSigned signature binds besides its payload, exactly as the token's mint records it. */
53
+ interface NftSignatureContext {
54
+ /** The network identifier α (`NetworkId.id`). */
55
+ readonly networkId: number | bigint;
56
+ /** The genesis recipient predicate, as `EncodedPredicate.toCBOR()` bytes. */
57
+ readonly recipientPredicate: Uint8Array;
58
+ /** The 32 raw token id bytes. */
59
+ readonly tokenId: Uint8Array;
60
+ readonly tokenType: Uint8Array;
61
+ }
48
62
  /** Encode one unsigned item. Throws SphereError('…', 'VALIDATION_ERROR') naming the offending field. */
49
63
  declare function encodeNftContent(content: NftContent): Uint8Array;
50
64
  /** Structural parse of a genesis payload. NEVER throws; null = not a recognised NFT. */
51
65
  declare function parseNftPayload(data: Uint8Array | null): ParsedNft | null;
66
+ /**
67
+ * Parse the file a document link points at: exactly one NftMetadata or NftMedia item.
68
+ * NEVER throws; null = not a document. Check the bytes with verifyNftLinkContent first.
69
+ */
70
+ declare function parseNftDocument(bytes: Uint8Array): NftMetadata | NftMedia | null;
71
+ /** Is this an NftLink to a metadata document ({@link NFT_DOCUMENT_MEDIA_TYPE}), resolved with parseNftDocument? */
72
+ declare function isNftDocumentLink(content: NftContent): boolean;
52
73
  /** Does `bytes` match the link's sha256? Pure, sync. */
53
74
  declare function verifyNftLinkContent(link: NftLink, bytes: Uint8Array): boolean;
54
75
 
@@ -1425,4 +1446,4 @@ declare class PaymentsFacade implements PaymentsV2 {
1425
1446
  declare const HEARTBEAT_SEED_MS = 5000;
1426
1447
  declare const HEARTBEAT_CAP_MS = 120000;
1427
1448
 
1428
- export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintNftRequest, type MintResult, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintJournalEntry, type NftSignatureStatus, type NftView, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendCoinlessRequest, type SendRequest, type SendWholeTokenRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, encodeNftContent, isRetryableAckError, parseNftPayload, supportsDeterministicMint, sweepSupersededState, verifyNftLinkContent };
1449
+ export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintNftRequest, type MintResult, NFT_DOCUMENT_MEDIA_TYPE, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintJournalEntry, type NftSignatureContext, type NftSignatureStatus, type NftView, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendCoinlessRequest, type SendRequest, type SendWholeTokenRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, encodeNftContent, isNftDocumentLink, isRetryableAckError, parseNftDocument, parseNftPayload, supportsDeterministicMint, sweepSupersededState, verifyNftLinkContent };
@@ -4,6 +4,8 @@ declare const NFT_METADATA_TAG = 39052n;
4
4
  declare const NFT_MEDIA_TAG = 39053n;
5
5
  declare const NFT_LINK_TAG = 39054n;
6
6
  declare const NFT_SIGNED_TAG = 39055n;
7
+ /** The media type of an NftLink that points at a metadata document instead of a media file. */
8
+ declare const NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
7
9
  /** An inline file. */
8
10
  interface NftMedia {
9
11
  readonly kind: 'media';
@@ -33,6 +35,8 @@ interface NftMetadata {
33
35
  readonly external_url: string | null;
34
36
  readonly attributes: readonly NftAttribute[];
35
37
  readonly collection: string | null;
38
+ /** The collection the item claims: 1–64 bytes as even-length hex (decoded lowercase). Never verified here. */
39
+ readonly collection_id: string | null;
36
40
  }
37
41
  type NftContent = NftMetadata | NftMedia | NftLink;
38
42
  type NftSignatureStatus = 'unsigned' | 'valid' | 'invalid';
@@ -45,10 +49,27 @@ interface ParsedNft {
45
49
  readonly signature: Uint8Array;
46
50
  } | null;
47
51
  }
52
+ /** What an NftSigned signature binds besides its payload, exactly as the token's mint records it. */
53
+ interface NftSignatureContext {
54
+ /** The network identifier α (`NetworkId.id`). */
55
+ readonly networkId: number | bigint;
56
+ /** The genesis recipient predicate, as `EncodedPredicate.toCBOR()` bytes. */
57
+ readonly recipientPredicate: Uint8Array;
58
+ /** The 32 raw token id bytes. */
59
+ readonly tokenId: Uint8Array;
60
+ readonly tokenType: Uint8Array;
61
+ }
48
62
  /** Encode one unsigned item. Throws SphereError('…', 'VALIDATION_ERROR') naming the offending field. */
49
63
  declare function encodeNftContent(content: NftContent): Uint8Array;
50
64
  /** Structural parse of a genesis payload. NEVER throws; null = not a recognised NFT. */
51
65
  declare function parseNftPayload(data: Uint8Array | null): ParsedNft | null;
66
+ /**
67
+ * Parse the file a document link points at: exactly one NftMetadata or NftMedia item.
68
+ * NEVER throws; null = not a document. Check the bytes with verifyNftLinkContent first.
69
+ */
70
+ declare function parseNftDocument(bytes: Uint8Array): NftMetadata | NftMedia | null;
71
+ /** Is this an NftLink to a metadata document ({@link NFT_DOCUMENT_MEDIA_TYPE}), resolved with parseNftDocument? */
72
+ declare function isNftDocumentLink(content: NftContent): boolean;
52
73
  /** Does `bytes` match the link's sha256? Pure, sync. */
53
74
  declare function verifyNftLinkContent(link: NftLink, bytes: Uint8Array): boolean;
54
75
 
@@ -1425,4 +1446,4 @@ declare class PaymentsFacade implements PaymentsV2 {
1425
1446
  declare const HEARTBEAT_SEED_MS = 5000;
1426
1447
  declare const HEARTBEAT_CAP_MS = 120000;
1427
1448
 
1428
- export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintNftRequest, type MintResult, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintJournalEntry, type NftSignatureStatus, type NftView, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendCoinlessRequest, type SendRequest, type SendWholeTokenRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, encodeNftContent, isRetryableAckError, parseNftPayload, supportsDeterministicMint, sweepSupersededState, verifyNftLinkContent };
1449
+ export { ATTENTION_MINT_UNRESOLVED, ATTENTION_RECIPIENT_NETWORK_UNVERIFIED, ATTENTION_RESEED_REJECTED, type AckOutcome, type AckRequest, type ApplyDeltaResult, type CheckpointReseeder, type ConnectionStatus, type DeliverOptions, type DeliveryJournalEntry, type DeliveryPort, type DeliveryReceipt, type DeterministicMintCapable, type FacadeClient, type FacadeSession, HEARTBEAT_CAP_MS, HEARTBEAT_SEED_MS, type HistoryEntry, type HistoryPage, type IncomingDelivery, type IntentBackstopEntry, type IntentPayload, type InventoryAsset, type InventoryItem, type InventoryPage, MAX_RESELECT, type MintJournalEntry, type MintNftRequest, type MintResult, NFT_DOCUMENT_MEDIA_TYPE, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftMintJournalEntry, type NftSignatureContext, type NftSignatureStatus, type NftView, type OpOutcome, type OutcomeClass, type PaymentRequestStatus, type PaymentRequestView, PaymentsFacade, type PaymentsFacadeDeps, type PaymentsRequestsApi, type PaymentsV2, type PaymentsV2Events, type PendingTransfer, type PlannedOp, type RecipientInfo, type RetryableAckError, STORE_KEYS, type ScopedKV, type SendCoinlessRequest, type SendRequest, type SendWholeTokenRequest, type SettlingLink, type ShortfallEntry, type StoragePort, type StreamCursor, type StreamName, createScopedKV, encodeNftContent, isNftDocumentLink, isRetryableAckError, parseNftDocument, parseNftPayload, supportsDeterministicMint, sweepSupersededState, verifyNftLinkContent };
@@ -454,7 +454,8 @@ var NFT_MEDIA_TAG = 39053n;
454
454
  var NFT_LINK_TAG = 39054n;
455
455
  var NFT_SIGNED_TAG = 39055n;
456
456
  var NFT_FORMAT_VERSION = 1n;
457
- var METADATA_ARITY = 8;
457
+ var NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
458
+ var METADATA_ARITY = 9;
458
459
  var MEDIA_ARITY = 3;
459
460
  var LINK_ARITY = 4;
460
461
  var SIGNED_ARITY = 4;
@@ -462,11 +463,15 @@ var CREATOR_BYTES = 33;
462
463
  var SIGNATURE_BYTES = 65;
463
464
  var MAX_URI_LENGTH = 2048;
464
465
  var LINK_SCHEMES = ["https://", "ipfs://", "ar://"];
466
+ var SIGNED_DOMAIN = new TextEncoder().encode("UNICITY_NFT_SIGNED");
465
467
  var MEDIA_TYPE_PATTERN = /^[a-z0-9][a-z0-9!#$&^_.+-]{0,126}\/[a-z0-9][a-z0-9!#$&^_.+-]{0,126}$/;
466
468
  var SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/i;
469
+ var COLLECTION_ID_PATTERN = /^(?:[0-9a-f]{2}){1,64}$/i;
467
470
  var LONE_SURROGATE = /\p{Cs}/u;
468
471
  var CBOR_MAJOR_TYPE_MASK = 224;
469
472
  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";
473
+ var COLLECTION_ID_RULE = "must be null or 1\u201364 bytes as even-length hex (2\u2013128 characters)";
474
+ var DOCUMENT_AS_MEDIA_RULE = `must not be ${NFT_DOCUMENT_MEDIA_TYPE}: a document link is a token's content, never media`;
470
475
  var UTF8 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
471
476
  function refuse(field, rule, cause) {
472
477
  return new SphereError(`Invalid NFT ${field}: ${rule}`, "VALIDATION_ERROR", cause);
@@ -478,6 +483,7 @@ var fieldName = (prefix, name) => prefix === "" ? name : `${prefix}.${name}`;
478
483
  var isText = (value) => typeof value === "string" && value.length > 0 && !LONE_SURROGATE.test(value);
479
484
  var isBytes2 = (value, length) => value instanceof Uint8Array && (length === void 0 ? value.length > 0 : value.length === length);
480
485
  var isMediaType = (value) => typeof value === "string" && MEDIA_TYPE_PATTERN.test(value);
486
+ var isCollectionId = (value) => typeof value === "string" && COLLECTION_ID_PATTERN.test(value);
481
487
  var isAttributeValue = (value) => typeof value === "number" ? Number.isSafeInteger(value) : isText(value);
482
488
  function hasSpaceOrControl(value) {
483
489
  for (let i = 0; i < value.length; i++) {
@@ -520,8 +526,9 @@ function checkLink(prefix, link) {
520
526
  function checkMediaRef(field, ref) {
521
527
  if (ref === null) return;
522
528
  if (ref?.kind === "media") return checkMedia(field, ref);
523
- if (ref?.kind === "link") return checkLink(field, ref);
524
- throw refuse(field, "must be an NftMedia, an NftLink or null");
529
+ if (ref?.kind !== "link") throw refuse(field, "must be an NftMedia, an NftLink or null");
530
+ checkLink(field, ref);
531
+ ensure(!isNftDocumentLink(ref), fieldName(field, "media_type"), DOCUMENT_AS_MEDIA_RULE);
525
532
  }
526
533
  function checkAttributes(attributes) {
527
534
  ensure(Array.isArray(attributes), "attributes", "must be an array \u2014 [] when there are none");
@@ -538,6 +545,7 @@ function checkMetadata(metadata) {
538
545
  checkOptionalText("external_url", metadata.external_url);
539
546
  checkAttributes(metadata.attributes);
540
547
  checkOptionalText("collection", metadata.collection);
548
+ ensure(metadata.collection_id === null || isCollectionId(metadata.collection_id), "collection_id", COLLECTION_ID_RULE);
541
549
  }
542
550
  function checkContent(content) {
543
551
  switch (content?.kind) {
@@ -595,6 +603,7 @@ function arrayCbor(items) {
595
603
  }
596
604
  return out;
597
605
  }
606
+ var optionalHexBytes = (value) => CborSerializer.encodeNullable(value, (hex) => CborSerializer.encodeByteString(HexConverter.decode(hex.toLowerCase())));
598
607
  function metadataCbor(metadata) {
599
608
  return versioned(
600
609
  NFT_METADATA_TAG,
@@ -604,7 +613,8 @@ function metadataCbor(metadata) {
604
613
  mediaRefCbor(metadata.animation_url),
605
614
  optionalText(metadata.external_url),
606
615
  arrayCbor(metadata.attributes.map(attributeCbor)),
607
- optionalText(metadata.collection)
616
+ optionalText(metadata.collection),
617
+ optionalHexBytes(metadata.collection_id)
608
618
  );
609
619
  }
610
620
  function encodeNftContent(content) {
@@ -645,13 +655,14 @@ function decodeMedia(body) {
645
655
  const [, mediaType, bytes] = versionedFields(body, MEDIA_ARITY);
646
656
  return { kind: "media", media_type: decodeText(mediaType), bytes: CborDeserializer.decodeByteString(bytes) };
647
657
  }
658
+ var decodeHex = (item) => HexConverter.encode(CborDeserializer.decodeByteString(item));
648
659
  function decodeLink(body) {
649
660
  const [, mediaType, uri, digest] = versionedFields(body, LINK_ARITY);
650
661
  return {
651
662
  kind: "link",
652
663
  media_type: decodeText(mediaType),
653
664
  uri: decodeText(uri),
654
- sha256: HexConverter.encode(CborDeserializer.decodeByteString(digest))
665
+ sha256: decodeHex(digest)
655
666
  };
656
667
  }
657
668
  function decodeMetadata(body) {
@@ -664,7 +675,8 @@ function decodeMetadata(body) {
664
675
  animation_url: decodeMediaRef("animation_url", fields[4]),
665
676
  external_url: decodeOptionalText(fields[5]),
666
677
  attributes: decodeAttributes(fields[6]),
667
- collection: decodeOptionalText(fields[7])
678
+ collection: decodeOptionalText(fields[7]),
679
+ collection_id: CborDeserializer.decodeNullable(fields[8], decodeHex)
668
680
  };
669
681
  }
670
682
  var MEDIA_REF_DECODERS = /* @__PURE__ */ new Map([
@@ -676,6 +688,10 @@ var UNSIGNED_DECODERS = /* @__PURE__ */ new Map([
676
688
  [NFT_MEDIA_TAG, decodeMedia],
677
689
  [NFT_LINK_TAG, decodeLink]
678
690
  ]);
691
+ var DOCUMENT_DECODERS = /* @__PURE__ */ new Map([
692
+ [NFT_METADATA_TAG, decodeMetadata],
693
+ [NFT_MEDIA_TAG, decodeMedia]
694
+ ]);
679
695
  function decodeBody(decoders, field, tag, body) {
680
696
  const decode = decoders.get(tag);
681
697
  if (decode === void 0) throw refuse(field, `tag ${tag} is not allowed here`);
@@ -710,6 +726,18 @@ function parseNftPayload(data) {
710
726
  return null;
711
727
  }
712
728
  }
729
+ function parseNftDocument(bytes) {
730
+ try {
731
+ const document = decodeItem(DOCUMENT_DECODERS, "document", bytes);
732
+ checkContent(document);
733
+ return document;
734
+ } catch {
735
+ return null;
736
+ }
737
+ }
738
+ function isNftDocumentLink(content) {
739
+ return content?.kind === "link" && content.media_type === NFT_DOCUMENT_MEDIA_TYPE;
740
+ }
713
741
  function verifyNftLinkContent(link, bytes) {
714
742
  return HexConverter.encode(sha256(bytes)) === link.sha256.toLowerCase();
715
743
  }
@@ -5737,6 +5765,7 @@ export {
5737
5765
  HEARTBEAT_CAP_MS,
5738
5766
  HEARTBEAT_SEED_MS,
5739
5767
  MAX_RESELECT,
5768
+ NFT_DOCUMENT_MEDIA_TYPE,
5740
5769
  NFT_LINK_TAG,
5741
5770
  NFT_MAX_PAYLOAD_BYTES,
5742
5771
  NFT_MEDIA_TAG,
@@ -5746,7 +5775,9 @@ export {
5746
5775
  STORE_KEYS,
5747
5776
  createScopedKV,
5748
5777
  encodeNftContent,
5778
+ isNftDocumentLink,
5749
5779
  isRetryableAckError,
5780
+ parseNftDocument,
5750
5781
  parseNftPayload,
5751
5782
  supportsDeterministicMint,
5752
5783
  sweepSupersededState,