@unicitylabs/sphere-sdk 0.17.2-dev.2 → 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 (39) hide show
  1. package/dist/connect/index.cjs +7 -4
  2. package/dist/connect/index.cjs.map +1 -1
  3. package/dist/connect/index.d.cts +4 -0
  4. package/dist/connect/index.d.ts +4 -0
  5. package/dist/connect/index.js +7 -4
  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 +1 -1
  14. package/dist/impl/browser/connect/index.cjs.map +1 -1
  15. package/dist/impl/browser/connect/index.js +1 -1
  16. package/dist/impl/browser/connect/index.js.map +1 -1
  17. package/dist/impl/wallet-api-v2/index.cjs +3 -0
  18. package/dist/impl/wallet-api-v2/index.cjs.map +1 -1
  19. package/dist/impl/wallet-api-v2/index.js +3 -0
  20. package/dist/impl/wallet-api-v2/index.js.map +1 -1
  21. package/dist/index.cjs +67 -21
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +22 -1
  24. package/dist/index.d.ts +22 -1
  25. package/dist/index.js +64 -21
  26. package/dist/index.js.map +1 -1
  27. package/dist/modules/payments-v2/index.cjs +40 -6
  28. package/dist/modules/payments-v2/index.cjs.map +1 -1
  29. package/dist/modules/payments-v2/index.d.cts +22 -1
  30. package/dist/modules/payments-v2/index.d.ts +22 -1
  31. package/dist/modules/payments-v2/index.js +37 -6
  32. package/dist/modules/payments-v2/index.js.map +1 -1
  33. package/dist/token-engine/index.cjs +67 -21
  34. package/dist/token-engine/index.cjs.map +1 -1
  35. package/dist/token-engine/index.d.cts +28 -4
  36. package/dist/token-engine/index.d.ts +28 -4
  37. package/dist/token-engine/index.js +64 -21
  38. package/dist/token-engine/index.js.map +1 -1
  39. package/package.json +1 -1
package/dist/index.d.cts CHANGED
@@ -86,6 +86,8 @@ declare const NFT_METADATA_TAG = 39052n;
86
86
  declare const NFT_MEDIA_TAG = 39053n;
87
87
  declare const NFT_LINK_TAG = 39054n;
88
88
  declare const NFT_SIGNED_TAG = 39055n;
89
+ /** The media type of an NftLink that points at a metadata document instead of a media file. */
90
+ declare const NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
89
91
  /** An inline file. */
90
92
  interface NftMedia {
91
93
  readonly kind: 'media';
@@ -115,6 +117,8 @@ interface NftMetadata {
115
117
  readonly external_url: string | null;
116
118
  readonly attributes: readonly NftAttribute[];
117
119
  readonly collection: string | null;
120
+ /** The collection the item claims: 1–64 bytes as even-length hex (decoded lowercase). Never verified here. */
121
+ readonly collection_id: string | null;
118
122
  }
119
123
  type NftContent = NftMetadata | NftMedia | NftLink;
120
124
  type NftSignatureStatus = 'unsigned' | 'valid' | 'invalid';
@@ -127,10 +131,27 @@ interface ParsedNft {
127
131
  readonly signature: Uint8Array;
128
132
  } | null;
129
133
  }
134
+ /** What an NftSigned signature binds besides its payload, exactly as the token's mint records it. */
135
+ interface NftSignatureContext {
136
+ /** The network identifier α (`NetworkId.id`). */
137
+ readonly networkId: number | bigint;
138
+ /** The genesis recipient predicate, as `EncodedPredicate.toCBOR()` bytes. */
139
+ readonly recipientPredicate: Uint8Array;
140
+ /** The 32 raw token id bytes. */
141
+ readonly tokenId: Uint8Array;
142
+ readonly tokenType: Uint8Array;
143
+ }
130
144
  /** Encode one unsigned item. Throws SphereError('…', 'VALIDATION_ERROR') naming the offending field. */
131
145
  declare function encodeNftContent(content: NftContent): Uint8Array;
132
146
  /** Structural parse of a genesis payload. NEVER throws; null = not a recognised NFT. */
133
147
  declare function parseNftPayload(data: Uint8Array | null): ParsedNft | null;
148
+ /**
149
+ * Parse the file a document link points at: exactly one NftMetadata or NftMedia item.
150
+ * NEVER throws; null = not a document. Check the bytes with verifyNftLinkContent first.
151
+ */
152
+ declare function parseNftDocument(bytes: Uint8Array): NftMetadata | NftMedia | null;
153
+ /** Is this an NftLink to a metadata document ({@link NFT_DOCUMENT_MEDIA_TYPE}), resolved with parseNftDocument? */
154
+ declare function isNftDocumentLink(content: NftContent): boolean;
134
155
  /** Does `bytes` match the link's sha256? Pure, sync. */
135
156
  declare function verifyNftLinkContent(link: NftLink, bytes: Uint8Array): boolean;
136
157
 
@@ -4894,4 +4915,4 @@ declare function normalizeAddress(address: string): string;
4894
4915
  */
4895
4916
  declare function addressesMatch(a: string, b: string): boolean;
4896
4917
 
4897
- export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type Asset, type BaseProvider, type BroadcastHandler, type BroadcastMessage, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, CoinGeckoPriceProvider, type CoinlessToken, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, type DecryptionProgressCallback, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type HistoryRecord, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingMessage, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentStatus, type IntentType, LIMITS, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LogHandler, type LogLevel, type LoggerConfig, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, type MintNftRequest, NETWORKS, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, NIP29_KINDS, NOSTR_EVENT_KINDS, type NetworkHealthResult, type NetworkType, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftSignatureStatus, type NftView, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type ParsedAddress, PartialSendConflictError, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type RegistryNetwork, SIGN_MESSAGE_PREFIX, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type StorageProvider, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenTransferDetail, type TrackedAddress, type TrackedAddressEntry, type HistoryRecord as TransactionHistoryEntry, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type WalletApiTransportConfig, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, addressesMatch, assertFieldEnvelopeShape, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, coinIdsMatch, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createPriceProvider, createSphere, decrypt, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encodeNftContent, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getPublicKey, getTokenDecimals, getTokenDefinition, getTokenIconUrl, getTokenName, getTokenSymbol, hash160, hashSignMessage, hexToBytes, identityFromMnemonicSync, initSphere, isKnownToken, isPossiblyCommittedSendOutcome, isSphereError, isTextWalletEncrypted, isValidAddress, isValidDirectAddress, isValidNametag, isValidPrivateKey, isWalletTextFormat, loadSphere, logger, mnemonicToSeedSync, normalizeAddress, normalizeCoinId, parseAddress, parseAndDecryptWalletText, parseNftPayload, parseTokenAmount, parseWalletText, randomBytes, randomHex, randomUUID, recoverPubkeyFromSignature, ripemd160, safeParseTokenAmount, sha256, signMessage, sleep, sphereExists, toHumanReadable, validateMnemonic, verifyChallengeTemplate, verifyNftLinkContent, verifySignedMessage };
4918
+ export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type Asset, type BaseProvider, type BroadcastHandler, type BroadcastMessage, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, CoinGeckoPriceProvider, type CoinlessToken, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, type DecryptionProgressCallback, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type HistoryRecord, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingMessage, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentStatus, type IntentType, LIMITS, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LogHandler, type LogLevel, type LoggerConfig, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, type MintNftRequest, NETWORKS, NFT_DOCUMENT_MEDIA_TYPE, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, NIP29_KINDS, NOSTR_EVENT_KINDS, type NetworkHealthResult, type NetworkType, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftSignatureContext, type NftSignatureStatus, type NftView, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type ParsedAddress, PartialSendConflictError, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type RegistryNetwork, SIGN_MESSAGE_PREFIX, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type StorageProvider, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenTransferDetail, type TrackedAddress, type TrackedAddressEntry, type HistoryRecord as TransactionHistoryEntry, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type WalletApiTransportConfig, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, addressesMatch, assertFieldEnvelopeShape, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, coinIdsMatch, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createPriceProvider, createSphere, decrypt, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encodeNftContent, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getPublicKey, getTokenDecimals, getTokenDefinition, getTokenIconUrl, getTokenName, getTokenSymbol, hash160, hashSignMessage, hexToBytes, identityFromMnemonicSync, initSphere, isKnownToken, isNftDocumentLink, isPossiblyCommittedSendOutcome, isSphereError, isTextWalletEncrypted, isValidAddress, isValidDirectAddress, isValidNametag, isValidPrivateKey, isWalletTextFormat, loadSphere, logger, mnemonicToSeedSync, normalizeAddress, normalizeCoinId, parseAddress, parseAndDecryptWalletText, parseNftDocument, parseNftPayload, parseTokenAmount, parseWalletText, randomBytes, randomHex, randomUUID, recoverPubkeyFromSignature, ripemd160, safeParseTokenAmount, sha256, signMessage, sleep, sphereExists, toHumanReadable, validateMnemonic, verifyChallengeTemplate, verifyNftLinkContent, verifySignedMessage };
package/dist/index.d.ts CHANGED
@@ -86,6 +86,8 @@ declare const NFT_METADATA_TAG = 39052n;
86
86
  declare const NFT_MEDIA_TAG = 39053n;
87
87
  declare const NFT_LINK_TAG = 39054n;
88
88
  declare const NFT_SIGNED_TAG = 39055n;
89
+ /** The media type of an NftLink that points at a metadata document instead of a media file. */
90
+ declare const NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
89
91
  /** An inline file. */
90
92
  interface NftMedia {
91
93
  readonly kind: 'media';
@@ -115,6 +117,8 @@ interface NftMetadata {
115
117
  readonly external_url: string | null;
116
118
  readonly attributes: readonly NftAttribute[];
117
119
  readonly collection: string | null;
120
+ /** The collection the item claims: 1–64 bytes as even-length hex (decoded lowercase). Never verified here. */
121
+ readonly collection_id: string | null;
118
122
  }
119
123
  type NftContent = NftMetadata | NftMedia | NftLink;
120
124
  type NftSignatureStatus = 'unsigned' | 'valid' | 'invalid';
@@ -127,10 +131,27 @@ interface ParsedNft {
127
131
  readonly signature: Uint8Array;
128
132
  } | null;
129
133
  }
134
+ /** What an NftSigned signature binds besides its payload, exactly as the token's mint records it. */
135
+ interface NftSignatureContext {
136
+ /** The network identifier α (`NetworkId.id`). */
137
+ readonly networkId: number | bigint;
138
+ /** The genesis recipient predicate, as `EncodedPredicate.toCBOR()` bytes. */
139
+ readonly recipientPredicate: Uint8Array;
140
+ /** The 32 raw token id bytes. */
141
+ readonly tokenId: Uint8Array;
142
+ readonly tokenType: Uint8Array;
143
+ }
130
144
  /** Encode one unsigned item. Throws SphereError('…', 'VALIDATION_ERROR') naming the offending field. */
131
145
  declare function encodeNftContent(content: NftContent): Uint8Array;
132
146
  /** Structural parse of a genesis payload. NEVER throws; null = not a recognised NFT. */
133
147
  declare function parseNftPayload(data: Uint8Array | null): ParsedNft | null;
148
+ /**
149
+ * Parse the file a document link points at: exactly one NftMetadata or NftMedia item.
150
+ * NEVER throws; null = not a document. Check the bytes with verifyNftLinkContent first.
151
+ */
152
+ declare function parseNftDocument(bytes: Uint8Array): NftMetadata | NftMedia | null;
153
+ /** Is this an NftLink to a metadata document ({@link NFT_DOCUMENT_MEDIA_TYPE}), resolved with parseNftDocument? */
154
+ declare function isNftDocumentLink(content: NftContent): boolean;
134
155
  /** Does `bytes` match the link's sha256? Pure, sync. */
135
156
  declare function verifyNftLinkContent(link: NftLink, bytes: Uint8Array): boolean;
136
157
 
@@ -4894,4 +4915,4 @@ declare function normalizeAddress(address: string): string;
4894
4915
  */
4895
4916
  declare function addressesMatch(a: string, b: string): boolean;
4896
4917
 
4897
- export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type Asset, type BaseProvider, type BroadcastHandler, type BroadcastMessage, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, CoinGeckoPriceProvider, type CoinlessToken, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, type DecryptionProgressCallback, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type HistoryRecord, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingMessage, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentStatus, type IntentType, LIMITS, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LogHandler, type LogLevel, type LoggerConfig, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, type MintNftRequest, NETWORKS, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, NIP29_KINDS, NOSTR_EVENT_KINDS, type NetworkHealthResult, type NetworkType, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftSignatureStatus, type NftView, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type ParsedAddress, PartialSendConflictError, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type RegistryNetwork, SIGN_MESSAGE_PREFIX, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type StorageProvider, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenTransferDetail, type TrackedAddress, type TrackedAddressEntry, type HistoryRecord as TransactionHistoryEntry, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type WalletApiTransportConfig, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, addressesMatch, assertFieldEnvelopeShape, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, coinIdsMatch, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createPriceProvider, createSphere, decrypt, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encodeNftContent, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getPublicKey, getTokenDecimals, getTokenDefinition, getTokenIconUrl, getTokenName, getTokenSymbol, hash160, hashSignMessage, hexToBytes, identityFromMnemonicSync, initSphere, isKnownToken, isPossiblyCommittedSendOutcome, isSphereError, isTextWalletEncrypted, isValidAddress, isValidDirectAddress, isValidNametag, isValidPrivateKey, isWalletTextFormat, loadSphere, logger, mnemonicToSeedSync, normalizeAddress, normalizeCoinId, parseAddress, parseAndDecryptWalletText, parseNftPayload, parseTokenAmount, parseWalletText, randomBytes, randomHex, randomUUID, recoverPubkeyFromSignature, ripemd160, safeParseTokenAmount, sha256, signMessage, sleep, sphereExists, toHumanReadable, validateMnemonic, verifyChallengeTemplate, verifyNftLinkContent, verifySignedMessage };
4918
+ export { AUTH_CHALLENGE_PREFIX, type AddressInfo, type AddressType, type AggregatorEvent, type AggregatorEventCallback, type AggregatorEventType, type AggregatorProvider, type Asset, type BaseProvider, type BroadcastHandler, type BroadcastMessage, COIN_TYPES, ChallengeTemplateError, type CheckNetworkHealthOptions, CoinGeckoPriceProvider, type CoinlessToken, CommunicationsModule, type CommunicationsModuleConfig, type CommunicationsModuleDependencies, type ComposingIndicator, type ConversationPage, type CreateGroupOptions, DEFAULT_AGGREGATOR_TIMEOUT, DEFAULT_DERIVATION_PATH, DEFAULT_GROUP_RELAYS, DEFAULT_MARKET_API_URL, DEFAULT_NOSTR_RELAYS, type DecryptionProgressCallback, type DerivationMode, type DirectMessage, type DiscoverAddressProgress, type DiscoverAddressesOptions, type DiscoverAddressesResult, type DiscoveredAddress, type EncryptedData, FIELD_ENCRYPTION_HKDF_INFO, FIELD_ENVELOPE_MAX_BYTES, FIELD_ENVELOPE_NONCE_BYTES, FIELD_ENVELOPE_PREFIX, type FullIdentity, type GetConversationPageOptions, GroupChatModule, type GroupChatModuleConfig, type GroupChatModuleDependencies, type GroupData, type GroupMemberData, type GroupMessageData, GroupRole, GroupVisibility, type HealthCheckFn, type HistoryRecord, type Identity, type IdentityConfig, type IncomingBroadcast, type IncomingMessage, type IncomingTransfer, type InitProgress, type InitProgressCallback, type InitProgressStep, type IntentStatus, type IntentType, LIMITS, type LegacyFileParseResult, type LegacyFileParsedData, type LegacyFileType, type LogHandler, type LogLevel, type LoggerConfig, type MarketIntent, MarketModule, type MarketModuleConfig, type MarketModuleDependencies, type MessageHandler, type MintNftRequest, NETWORKS, NFT_DOCUMENT_MEDIA_TYPE, NFT_LINK_TAG, NFT_MAX_PAYLOAD_BYTES, NFT_MEDIA_TAG, NFT_METADATA_TAG, NFT_SIGNED_TAG, NIP29_KINDS, NOSTR_EVENT_KINDS, type NetworkHealthResult, type NetworkType, type NftAttribute, type NftContent, type NftLink, type NftMedia, type NftMediaRef, type NftMetadata, type NftSignatureContext, type NftSignatureStatus, type NftView, type OracleEvent, type OracleEventCallback, type OracleEventType, type OracleProvider, type ParsedAddress, PartialSendConflictError, type PeerInfo, type PostIntentRequest, type PostIntentResult, type PricePlatform, type PriceProvider, type PriceProviderConfig, type ProviderMetadata, type ProviderRole, type ProviderStatus, type ProviderStatusInfo, type RegistryNetwork, SIGN_MESSAGE_PREFIX, STORAGE_KEYS_ADDRESS, STORAGE_KEYS_GLOBAL, STORAGE_PREFIX, type SearchFilters, type SearchIntentResult, type SearchOptions, type SearchResult, type ServiceHealthResult, Sphere, type SphereCreateOptions, SphereError, type SphereErrorCode, type SphereEventHandler, type SphereEventMap, type SphereEventType, type SphereImportOptions, type SphereInitOptions, type SphereInitResult, type SphereLoadOptions, type SphereStatus, type StorageProvider, TEST_NOSTR_RELAYS, TIMEOUTS, type Token, type TokenDefinition, type TokenIcon, type TokenPrice, TokenRegistry, type TokenStatus, type TokenTransferDetail, type TrackedAddress, type TrackedAddressEntry, type HistoryRecord as TransactionHistoryEntry, type TransferRequest, type TransferResult, type TransferStatus, type TransportEvent, type TransportEventCallback, type TransportEventType, type TransportProvider, type WalletApiTransportConfig, type WalletInfo, type WalletJSON, type WalletJSONExportOptions, type WalletSource, addressesMatch, assertFieldEnvelopeShape, base58Decode, base58Encode, bytesToHex, checkNetworkHealth, coinIdsMatch, createCommunicationsModule, createGroupChatModule, createKeyPair, createMarketModule, createPriceProvider, createSphere, decrypt, decryptField, decryptFieldBytes, decryptJson, decryptMnemonic, decryptSimple, decryptTextFormatKey, decryptWithSalt, deriveAddressInfo, deriveChildKey, deriveFieldEncryptionKey, deriveKeyAtPath, doubleSha256, encodeNftContent, encrypt, encryptField, encryptFieldBytes, encryptMnemonic, encryptSimple, extractFromText, findPattern, formatAmount, generateAddressFromMasterKey, generateMasterKey, generateMnemonic, getAddressId, getAddressStorageKey, getCoinIdByName, getCoinIdBySymbol, getPublicKey, getTokenDecimals, getTokenDefinition, getTokenIconUrl, getTokenName, getTokenSymbol, hash160, hashSignMessage, hexToBytes, identityFromMnemonicSync, initSphere, isKnownToken, isNftDocumentLink, isPossiblyCommittedSendOutcome, isSphereError, isTextWalletEncrypted, isValidAddress, isValidDirectAddress, isValidNametag, isValidPrivateKey, isWalletTextFormat, loadSphere, logger, mnemonicToSeedSync, normalizeAddress, normalizeCoinId, parseAddress, parseAndDecryptWalletText, parseNftDocument, parseNftPayload, parseTokenAmount, parseWalletText, randomBytes, randomHex, randomUUID, recoverPubkeyFromSignature, ripemd160, safeParseTokenAmount, sha256, signMessage, sleep, sphereExists, toHumanReadable, validateMnemonic, verifyChallengeTemplate, verifyNftLinkContent, verifySignedMessage };
package/dist/index.js CHANGED
@@ -9802,7 +9802,8 @@ var NFT_MEDIA_TAG = 39053n;
9802
9802
  var NFT_LINK_TAG = 39054n;
9803
9803
  var NFT_SIGNED_TAG = 39055n;
9804
9804
  var NFT_FORMAT_VERSION = 1n;
9805
- var METADATA_ARITY = 8;
9805
+ var NFT_DOCUMENT_MEDIA_TYPE = "application/vnd.unicity.nft+cbor";
9806
+ var METADATA_ARITY = 9;
9806
9807
  var MEDIA_ARITY = 3;
9807
9808
  var LINK_ARITY = 4;
9808
9809
  var SIGNED_ARITY = 4;
@@ -9810,12 +9811,15 @@ var CREATOR_BYTES = 33;
9810
9811
  var SIGNATURE_BYTES = 65;
9811
9812
  var MAX_URI_LENGTH = 2048;
9812
9813
  var LINK_SCHEMES = ["https://", "ipfs://", "ar://"];
9813
- var SIGNED_DOMAIN = "NftSigned";
9814
+ var SIGNED_DOMAIN = new TextEncoder().encode("UNICITY_NFT_SIGNED");
9814
9815
  var MEDIA_TYPE_PATTERN = /^[a-z0-9][a-z0-9!#$&^_.+-]{0,126}\/[a-z0-9][a-z0-9!#$&^_.+-]{0,126}$/;
9815
9816
  var SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/i;
9817
+ var COLLECTION_ID_PATTERN = /^(?:[0-9a-f]{2}){1,64}$/i;
9816
9818
  var LONE_SURROGATE = /\p{Cs}/u;
9817
9819
  var CBOR_MAJOR_TYPE_MASK = 224;
9818
9820
  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";
9821
+ var COLLECTION_ID_RULE = "must be null or 1\u201364 bytes as even-length hex (2\u2013128 characters)";
9822
+ var DOCUMENT_AS_MEDIA_RULE = `must not be ${NFT_DOCUMENT_MEDIA_TYPE}: a document link is a token's content, never media`;
9819
9823
  var UTF8 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
9820
9824
  function refuse(field, rule, cause) {
9821
9825
  return new SphereError(`Invalid NFT ${field}: ${rule}`, "VALIDATION_ERROR", cause);
@@ -9827,6 +9831,7 @@ var fieldName = (prefix, name) => prefix === "" ? name : `${prefix}.${name}`;
9827
9831
  var isText = (value) => typeof value === "string" && value.length > 0 && !LONE_SURROGATE.test(value);
9828
9832
  var isBytes3 = (value, length) => value instanceof Uint8Array && (length === void 0 ? value.length > 0 : value.length === length);
9829
9833
  var isMediaType = (value) => typeof value === "string" && MEDIA_TYPE_PATTERN.test(value);
9834
+ var isCollectionId = (value) => typeof value === "string" && COLLECTION_ID_PATTERN.test(value);
9830
9835
  var isAttributeValue = (value) => typeof value === "number" ? Number.isSafeInteger(value) : isText(value);
9831
9836
  function hasSpaceOrControl(value) {
9832
9837
  for (let i = 0; i < value.length; i++) {
@@ -9869,8 +9874,9 @@ function checkLink(prefix, link) {
9869
9874
  function checkMediaRef(field, ref) {
9870
9875
  if (ref === null) return;
9871
9876
  if (ref?.kind === "media") return checkMedia(field, ref);
9872
- if (ref?.kind === "link") return checkLink(field, ref);
9873
- throw refuse(field, "must be an NftMedia, an NftLink or null");
9877
+ if (ref?.kind !== "link") throw refuse(field, "must be an NftMedia, an NftLink or null");
9878
+ checkLink(field, ref);
9879
+ ensure(!isNftDocumentLink(ref), fieldName(field, "media_type"), DOCUMENT_AS_MEDIA_RULE);
9874
9880
  }
9875
9881
  function checkAttributes(attributes) {
9876
9882
  ensure(Array.isArray(attributes), "attributes", "must be an array \u2014 [] when there are none");
@@ -9887,6 +9893,7 @@ function checkMetadata(metadata) {
9887
9893
  checkOptionalText("external_url", metadata.external_url);
9888
9894
  checkAttributes(metadata.attributes);
9889
9895
  checkOptionalText("collection", metadata.collection);
9896
+ ensure(metadata.collection_id === null || isCollectionId(metadata.collection_id), "collection_id", COLLECTION_ID_RULE);
9890
9897
  }
9891
9898
  function checkContent(content) {
9892
9899
  switch (content?.kind) {
@@ -9944,6 +9951,7 @@ function arrayCbor(items) {
9944
9951
  }
9945
9952
  return out;
9946
9953
  }
9954
+ var optionalHexBytes = (value) => CborSerializer.encodeNullable(value, (hex) => CborSerializer.encodeByteString(HexConverter.decode(hex.toLowerCase())));
9947
9955
  function metadataCbor(metadata) {
9948
9956
  return versioned(
9949
9957
  NFT_METADATA_TAG,
@@ -9953,7 +9961,8 @@ function metadataCbor(metadata) {
9953
9961
  mediaRefCbor(metadata.animation_url),
9954
9962
  optionalText(metadata.external_url),
9955
9963
  arrayCbor(metadata.attributes.map(attributeCbor)),
9956
- optionalText(metadata.collection)
9964
+ optionalText(metadata.collection),
9965
+ optionalHexBytes(metadata.collection_id)
9957
9966
  );
9958
9967
  }
9959
9968
  function encodeNftContent(content) {
@@ -10011,13 +10020,14 @@ function decodeMedia(body) {
10011
10020
  const [, mediaType, bytes] = versionedFields(body, MEDIA_ARITY);
10012
10021
  return { kind: "media", media_type: decodeText(mediaType), bytes: CborDeserializer.decodeByteString(bytes) };
10013
10022
  }
10023
+ var decodeHex = (item) => HexConverter.encode(CborDeserializer.decodeByteString(item));
10014
10024
  function decodeLink(body) {
10015
10025
  const [, mediaType, uri, digest] = versionedFields(body, LINK_ARITY);
10016
10026
  return {
10017
10027
  kind: "link",
10018
10028
  media_type: decodeText(mediaType),
10019
10029
  uri: decodeText(uri),
10020
- sha256: HexConverter.encode(CborDeserializer.decodeByteString(digest))
10030
+ sha256: decodeHex(digest)
10021
10031
  };
10022
10032
  }
10023
10033
  function decodeMetadata(body) {
@@ -10030,7 +10040,8 @@ function decodeMetadata(body) {
10030
10040
  animation_url: decodeMediaRef("animation_url", fields[4]),
10031
10041
  external_url: decodeOptionalText(fields[5]),
10032
10042
  attributes: decodeAttributes(fields[6]),
10033
- collection: decodeOptionalText(fields[7])
10043
+ collection: decodeOptionalText(fields[7]),
10044
+ collection_id: CborDeserializer.decodeNullable(fields[8], decodeHex)
10034
10045
  };
10035
10046
  }
10036
10047
  var MEDIA_REF_DECODERS = /* @__PURE__ */ new Map([
@@ -10042,6 +10053,10 @@ var UNSIGNED_DECODERS = /* @__PURE__ */ new Map([
10042
10053
  [NFT_MEDIA_TAG, decodeMedia],
10043
10054
  [NFT_LINK_TAG, decodeLink]
10044
10055
  ]);
10056
+ var DOCUMENT_DECODERS = /* @__PURE__ */ new Map([
10057
+ [NFT_METADATA_TAG, decodeMetadata],
10058
+ [NFT_MEDIA_TAG, decodeMedia]
10059
+ ]);
10045
10060
  function decodeBody(decoders, field, tag, body) {
10046
10061
  const decode = decoders.get(tag);
10047
10062
  if (decode === void 0) throw refuse(field, `tag ${tag} is not allowed here`);
@@ -10076,20 +10091,35 @@ function parseNftPayload(data) {
10076
10091
  return null;
10077
10092
  }
10078
10093
  }
10079
- function nftSignedDigest(tokenIdCbor, recipientPredicateCbor, payload) {
10094
+ function parseNftDocument(bytes) {
10095
+ try {
10096
+ const document = decodeItem(DOCUMENT_DECODERS, "document", bytes);
10097
+ checkContent(document);
10098
+ return document;
10099
+ } catch {
10100
+ return null;
10101
+ }
10102
+ }
10103
+ function isNftDocumentLink(content) {
10104
+ return content?.kind === "link" && content.media_type === NFT_DOCUMENT_MEDIA_TYPE;
10105
+ }
10106
+ function nftSignedDigest(context, payload) {
10080
10107
  const preimage = CborSerializer.encodeArray(
10081
- CborSerializer.encodeTextString(SIGNED_DOMAIN),
10082
- tokenIdCbor,
10083
- recipientPredicateCbor,
10108
+ CborSerializer.encodeByteString(SIGNED_DOMAIN),
10109
+ CborSerializer.encodeUnsignedInteger(NFT_FORMAT_VERSION),
10110
+ CborSerializer.encodeUnsignedInteger(NetworkId.fromId(context.networkId).id),
10111
+ CborSerializer.encodeByteString(context.recipientPredicate),
10112
+ CborSerializer.encodeByteString(context.tokenId),
10113
+ CborSerializer.encodeByteString(context.tokenType),
10084
10114
  CborSerializer.encodeByteString(payload)
10085
10115
  );
10086
10116
  return new DataHasher(HashAlgorithm.SHA256).update(preimage).digest();
10087
10117
  }
10088
- async function verifyNftSignature(signed, tokenIdCbor, recipientPredicateCbor) {
10118
+ async function verifyNftSignature(signed, context) {
10089
10119
  try {
10090
10120
  if (!SigningService.isPublicKeyValid(signed.creator)) return "invalid";
10091
10121
  const signature = Signature.decode(signed.signature);
10092
- const digest = await nftSignedDigest(tokenIdCbor, recipientPredicateCbor, signed.payload);
10122
+ const digest = await nftSignedDigest(context, signed.payload);
10093
10123
  return await SigningService.verifyWithPublicKey(digest, signature, signed.creator) ? "valid" : "invalid";
10094
10124
  } catch {
10095
10125
  return "invalid";
@@ -10223,8 +10253,8 @@ function assertMintableData(data) {
10223
10253
  function nftRecipientCbor(pubkey) {
10224
10254
  return EncodedPredicate.fromPredicate(SignaturePredicate.create(pubkey)).toCBOR();
10225
10255
  }
10226
- async function signPayload(deps, payload, tokenId, recipientPubkey) {
10227
- const digest = await nftSignedDigest(tokenId.toCBOR(), nftRecipientCbor(recipientPubkey), payload);
10256
+ async function signPayload(deps, payload, context) {
10257
+ const digest = await nftSignedDigest(context, payload);
10228
10258
  const signature = await deps.signingService.sign(digest);
10229
10259
  return encodeNftSigned(deps.signingService.publicKey, payload, signature.encode());
10230
10260
  }
@@ -10233,31 +10263,41 @@ async function planNftMint(deps, params) {
10233
10263
  const tokenType = new TokenType(params.tokenType).bytes;
10234
10264
  const salt = TokenSalt.generate();
10235
10265
  const tokenId = await TokenId.fromSalt(deps.networkId, salt);
10236
- const data = params.sign ? await signPayload(deps, payload, tokenId, params.recipientPubkey) : payload;
10266
+ const data = params.sign ? await signPayload(deps, payload, {
10267
+ networkId: deps.networkId.id,
10268
+ recipientPredicate: nftRecipientCbor(params.recipientPubkey),
10269
+ tokenId: tokenId.bytes,
10270
+ tokenType
10271
+ }) : payload;
10237
10272
  assertMintableData(data);
10238
10273
  return { data, salt: salt.toBytes(), tokenType, tokenId: HexConverter.encode(tokenId.bytes) };
10239
10274
  }
10240
- async function verifyAgainst(signed, tokenIdCbor, genesisRecipientCbor) {
10275
+ async function verifyAgainst(signed, genesisContext) {
10241
10276
  try {
10242
- return await verifyNftSignature(signed, tokenIdCbor, genesisRecipientCbor());
10277
+ return await verifyNftSignature(signed, genesisContext());
10243
10278
  } catch {
10244
10279
  return "invalid";
10245
10280
  }
10246
10281
  }
10247
- async function readNftData(data, tokenIdCbor, genesisRecipientCbor) {
10282
+ async function readNftData(data, genesisContext) {
10248
10283
  const parsed = parseNftPayload(data);
10249
10284
  if (parsed === null) return null;
10250
10285
  if (parsed.signed === null) return { content: parsed.content, creator: null, signature: "unsigned" };
10251
10286
  return {
10252
10287
  content: parsed.content,
10253
10288
  creator: HexConverter.encode(parsed.signed.creator),
10254
- signature: await verifyAgainst(parsed.signed, tokenIdCbor, genesisRecipientCbor)
10289
+ signature: await verifyAgainst(parsed.signed, genesisContext)
10255
10290
  };
10256
10291
  }
10257
10292
  async function readTokenNft(token) {
10258
10293
  try {
10259
10294
  const { genesis } = token.sdkToken;
10260
- return await readNftData(genesis.data, genesis.tokenId.toCBOR(), () => genesis.recipient.toCBOR());
10295
+ return await readNftData(genesis.data, () => ({
10296
+ networkId: genesis.networkId.id,
10297
+ recipientPredicate: genesis.recipient.toCBOR(),
10298
+ tokenId: genesis.tokenId.bytes,
10299
+ tokenType: genesis.tokenType.bytes
10300
+ }));
10261
10301
  } catch {
10262
10302
  return null;
10263
10303
  }
@@ -20725,6 +20765,7 @@ export {
20725
20765
  LIMITS,
20726
20766
  MarketModule,
20727
20767
  NETWORKS,
20768
+ NFT_DOCUMENT_MEDIA_TYPE,
20728
20769
  NFT_LINK_TAG,
20729
20770
  NFT_MAX_PAYLOAD_BYTES,
20730
20771
  NFT_MEDIA_TAG,
@@ -20803,6 +20844,7 @@ export {
20803
20844
  identityFromMnemonicSync,
20804
20845
  initSphere,
20805
20846
  isKnownToken,
20847
+ isNftDocumentLink,
20806
20848
  isPhoneNumber2 as isPhoneNumber,
20807
20849
  isPossiblyCommittedSendOutcome,
20808
20850
  isSphereError,
@@ -20820,6 +20862,7 @@ export {
20820
20862
  normalizeNametag2 as normalizeNametag,
20821
20863
  parseAddress,
20822
20864
  parseAndDecryptWalletText,
20865
+ parseNftDocument,
20823
20866
  parseNftPayload,
20824
20867
  parseTokenAmount,
20825
20868
  parseWalletText,