@unicitylabs/sphere-sdk 0.17.2-dev.3 → 0.17.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.
package/dist/index.d.cts CHANGED
@@ -334,7 +334,7 @@ interface PaymentsV2 {
334
334
  * }
335
335
  * ```
336
336
  */
337
- type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
337
+ type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'PAYMENTS_NOT_COMPOSED' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
338
338
  declare class SphereError extends Error {
339
339
  readonly code: SphereErrorCode;
340
340
  readonly cause?: unknown;
@@ -2862,6 +2862,9 @@ interface WalletApiTransportConfig {
2862
2862
  /** DI seam: supply the whole per-address bundle (offline tests, custom hosts). */
2863
2863
  paymentsV2Transport?(args: PaymentsV2TransportArgs): PaymentsV2Transport;
2864
2864
  }
2865
+ /** The messaging-only opt-out (#793) — sharing the `walletApi` field is what makes "configured" and "deliberately absent" mutually exclusive. */
2866
+ declare const NO_PAYMENTS = "none";
2867
+ type WalletApiOption = WalletApiTransportConfig | typeof NO_PAYMENTS;
2865
2868
 
2866
2869
  /**
2867
2870
  * Text Wallet Backup Serialization Types
@@ -2953,14 +2956,17 @@ interface InitProgress {
2953
2956
  /** Callback for tracking wallet initialization progress */
2954
2957
  type InitProgressCallback = (progress: InitProgress) => void;
2955
2958
  /**
2956
- * The wallet-api transport config every wallet needs (money moves only through
2957
- * the wallet-api vertical): `{ network, baseUrl, deviceId?, ... }` —
2958
- * `createWalletApiProviders` (impl/shared/wallet-api) builds it. Shared by all
2959
- * four init-option shapes below.
2959
+ * The wallet-api transport config every wallet that moves money needs:
2960
+ * `{ network, baseUrl, deviceId?, ... }` — `createWalletApiProviders`
2961
+ * (impl/shared/wallet-api) builds it. Shared by all four init-option shapes below.
2960
2962
  */
2961
2963
  interface SphereWalletApiOptions {
2962
- /** Wallet-api transport config — REQUIRED (init throws INVALID_CONFIG without it). */
2963
- walletApi?: WalletApiTransportConfig;
2964
+ /**
2965
+ * Wallet-api transport config — REQUIRED, with one explicit escape: `'none'`
2966
+ * composes no money at all (#793). Omitting the field still throws INVALID_CONFIG:
2967
+ * "I forgot it" must never read the same as "I meant it".
2968
+ */
2969
+ walletApi?: WalletApiOption;
2964
2970
  /** @deprecated REMOVED with the P11 flip — any truthy value throws INVALID_CONFIG (invoicing no longer exists in the SDK). */
2965
2971
  accounting?: unknown;
2966
2972
  /** @deprecated REMOVED with the P11 flip — any truthy value throws INVALID_CONFIG (swaps no longer exist in the SDK). */
@@ -3232,7 +3238,11 @@ declare class Sphere {
3232
3238
  private _market;
3233
3239
  /** The ACTIVE address's running vertical — §7: exactly one at a time, ever. */
3234
3240
  private _paymentsV2Active;
3235
- /** Resolved wallet-api transport composition (network + per-address factory); set at init, fail-closed. */
3241
+ /**
3242
+ * Money composition, set at init. `null` = never resolved (a construction bug),
3243
+ * `NO_PAYMENTS` = the explicit #793 opt-out, an object = a real composition. One
3244
+ * spelling for the last two would read a forgotten resolve as messaging-only.
3245
+ */
3236
3246
  private _paymentsV2Composition;
3237
3247
  /**
3238
3248
  * §7 lifecycle mutex: every stop/start pair runs strictly serialized, so
@@ -3419,6 +3429,12 @@ declare class Sphere {
3419
3429
  static generateMnemonic(strength?: 128 | 256): string;
3420
3430
  /** Payments (the §4 facade — the active address's running vertical). */
3421
3431
  get payments(): PaymentsV2;
3432
+ /**
3433
+ * Whether this Sphere composes money at all (#793) — fixed for the instance's life,
3434
+ * so a messaging-only wallet can branch without a try/catch. Not a liveness check:
3435
+ * `true` still leaves `payments` throwing NOT_INITIALIZED mid-init or mid-switch.
3436
+ */
3437
+ get hasPayments(): boolean;
3422
3438
  /** Communications module */
3423
3439
  get communications(): CommunicationsModule;
3424
3440
  /** Group chat module (NIP-29). Null if not configured. */
@@ -4915,4 +4931,4 @@ declare function normalizeAddress(address: string): string;
4915
4931
  */
4916
4932
  declare function addressesMatch(a: string, b: string): boolean;
4917
4933
 
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 };
4934
+ 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, NO_PAYMENTS, 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 WalletApiOption, 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
@@ -334,7 +334,7 @@ interface PaymentsV2 {
334
334
  * }
335
335
  * ```
336
336
  */
337
- type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
337
+ type SphereErrorCode = 'NOT_INITIALIZED' | 'ALREADY_INITIALIZED' | 'INVALID_CONFIG' | 'INVALID_IDENTITY' | 'INSUFFICIENT_BALANCE' | 'INVALID_RECIPIENT' | 'TRANSFER_FAILED' | 'TRANSFER_CONFLICT' | 'CERTIFICATION_UNCONFIRMED' | 'CHECKPOINT_PERSIST_FAILED' | 'SPLIT_CHECKPOINT_LOST' | 'CHECKPOINT_TRUSTBASE_MISMATCH' | 'STORAGE_ERROR' | 'SEND_SYNC_PENDING' | 'SEND_PARTIALLY_COMPLETED' | 'TRANSPORT_ERROR' | 'AGGREGATOR_ERROR' | 'VALIDATION_ERROR' | 'INVALID_AMOUNT' | 'NETWORK_ERROR' | 'TIMEOUT' | 'DECRYPTION_ERROR' | 'MODULE_NOT_AVAILABLE' | 'PAYMENTS_NOT_COMPOSED' | 'SIGNING_ERROR' | 'SEND_QUEUE_TIMEOUT' | 'SEND_INSUFFICIENT_BALANCE' | 'SEND_RESERVATION_CANCELLED' | 'SEND_QUEUE_FULL' | 'MODULE_DESTROYED' | 'REENTRANT_GATE' | 'INVOICE_NO_TARGETS' | 'INVOICE_INVALID_ADDRESS' | 'INVOICE_NO_ASSETS' | 'INVOICE_INVALID_ASSET' | 'INVOICE_INVALID_AMOUNT' | 'INVOICE_INVALID_COIN' | 'INVOICE_INVALID_NFT' | 'INVOICE_PAST_DUE_DATE' | 'INVOICE_DUPLICATE_ADDRESS' | 'INVOICE_DUPLICATE_COIN' | 'INVOICE_DUPLICATE_NFT' | 'INVOICE_MINT_FAILED' | 'INVOICE_INVALID_PROOF' | 'INVOICE_WRONG_TOKEN_TYPE' | 'INVOICE_INVALID_DATA' | 'INVOICE_ALREADY_EXISTS' | 'INVOICE_NOT_FOUND' | 'INVOICE_NOT_TARGET' | 'INVOICE_ALREADY_CLOSED' | 'INVOICE_ALREADY_CANCELLED' | 'INVOICE_ORACLE_REQUIRED' | 'INVOICE_TERMINATED' | 'INVOICE_INVALID_TARGET' | 'INVOICE_INVALID_ASSET_INDEX' | 'INVOICE_RETURN_EXCEEDS_BALANCE' | 'INVOICE_INVALID_DELIVERY_METHOD' | 'INVOICE_INVALID_REFUND_ADDRESS' | 'INVOICE_INVALID_CONTACT' | 'INVOICE_INVALID_ID' | 'INVOICE_TOO_MANY_TARGETS' | 'INVOICE_TOO_MANY_ASSETS' | 'INVOICE_MEMO_TOO_LONG' | 'INVOICE_TERMS_TOO_LARGE' | 'INVOICE_NOT_TERMINATED' | 'INVOICE_NOT_CANCELLED' | 'INVOICE_STORAGE_FAILED' | 'RATE_LIMITED' | 'COMMUNICATIONS_UNAVAILABLE' | 'SWAP_INVALID_DEAL' | 'SWAP_INVALID_MANIFEST' | 'SWAP_NOT_FOUND' | 'SWAP_WRONG_STATE' | 'SWAP_RESOLVE_FAILED' | 'SWAP_DM_SEND_FAILED' | 'SWAP_ESCROW_REJECTED' | 'SWAP_DEPOSIT_FAILED' | 'SWAP_PAYOUT_VERIFICATION_FAILED' | 'SWAP_ALREADY_EXISTS' | 'SWAP_ALREADY_COMPLETED' | 'SWAP_ALREADY_CANCELLED' | 'SWAP_TIMEOUT' | 'SWAP_LIMIT_EXCEEDED' | 'SWAP_ALREADY_INITIALIZED' | 'SWAP_MODULE_DESTROYED' | 'SWAP_NOT_INITIALIZED';
338
338
  declare class SphereError extends Error {
339
339
  readonly code: SphereErrorCode;
340
340
  readonly cause?: unknown;
@@ -2862,6 +2862,9 @@ interface WalletApiTransportConfig {
2862
2862
  /** DI seam: supply the whole per-address bundle (offline tests, custom hosts). */
2863
2863
  paymentsV2Transport?(args: PaymentsV2TransportArgs): PaymentsV2Transport;
2864
2864
  }
2865
+ /** The messaging-only opt-out (#793) — sharing the `walletApi` field is what makes "configured" and "deliberately absent" mutually exclusive. */
2866
+ declare const NO_PAYMENTS = "none";
2867
+ type WalletApiOption = WalletApiTransportConfig | typeof NO_PAYMENTS;
2865
2868
 
2866
2869
  /**
2867
2870
  * Text Wallet Backup Serialization Types
@@ -2953,14 +2956,17 @@ interface InitProgress {
2953
2956
  /** Callback for tracking wallet initialization progress */
2954
2957
  type InitProgressCallback = (progress: InitProgress) => void;
2955
2958
  /**
2956
- * The wallet-api transport config every wallet needs (money moves only through
2957
- * the wallet-api vertical): `{ network, baseUrl, deviceId?, ... }` —
2958
- * `createWalletApiProviders` (impl/shared/wallet-api) builds it. Shared by all
2959
- * four init-option shapes below.
2959
+ * The wallet-api transport config every wallet that moves money needs:
2960
+ * `{ network, baseUrl, deviceId?, ... }` — `createWalletApiProviders`
2961
+ * (impl/shared/wallet-api) builds it. Shared by all four init-option shapes below.
2960
2962
  */
2961
2963
  interface SphereWalletApiOptions {
2962
- /** Wallet-api transport config — REQUIRED (init throws INVALID_CONFIG without it). */
2963
- walletApi?: WalletApiTransportConfig;
2964
+ /**
2965
+ * Wallet-api transport config — REQUIRED, with one explicit escape: `'none'`
2966
+ * composes no money at all (#793). Omitting the field still throws INVALID_CONFIG:
2967
+ * "I forgot it" must never read the same as "I meant it".
2968
+ */
2969
+ walletApi?: WalletApiOption;
2964
2970
  /** @deprecated REMOVED with the P11 flip — any truthy value throws INVALID_CONFIG (invoicing no longer exists in the SDK). */
2965
2971
  accounting?: unknown;
2966
2972
  /** @deprecated REMOVED with the P11 flip — any truthy value throws INVALID_CONFIG (swaps no longer exist in the SDK). */
@@ -3232,7 +3238,11 @@ declare class Sphere {
3232
3238
  private _market;
3233
3239
  /** The ACTIVE address's running vertical — §7: exactly one at a time, ever. */
3234
3240
  private _paymentsV2Active;
3235
- /** Resolved wallet-api transport composition (network + per-address factory); set at init, fail-closed. */
3241
+ /**
3242
+ * Money composition, set at init. `null` = never resolved (a construction bug),
3243
+ * `NO_PAYMENTS` = the explicit #793 opt-out, an object = a real composition. One
3244
+ * spelling for the last two would read a forgotten resolve as messaging-only.
3245
+ */
3236
3246
  private _paymentsV2Composition;
3237
3247
  /**
3238
3248
  * §7 lifecycle mutex: every stop/start pair runs strictly serialized, so
@@ -3419,6 +3429,12 @@ declare class Sphere {
3419
3429
  static generateMnemonic(strength?: 128 | 256): string;
3420
3430
  /** Payments (the §4 facade — the active address's running vertical). */
3421
3431
  get payments(): PaymentsV2;
3432
+ /**
3433
+ * Whether this Sphere composes money at all (#793) — fixed for the instance's life,
3434
+ * so a messaging-only wallet can branch without a try/catch. Not a liveness check:
3435
+ * `true` still leaves `payments` throwing NOT_INITIALIZED mid-init or mid-switch.
3436
+ */
3437
+ get hasPayments(): boolean;
3422
3438
  /** Communications module */
3423
3439
  get communications(): CommunicationsModule;
3424
3440
  /** Group chat module (NIP-29). Null if not configured. */
@@ -4915,4 +4931,4 @@ declare function normalizeAddress(address: string): string;
4915
4931
  */
4916
4932
  declare function addressesMatch(a: string, b: string): boolean;
4917
4933
 
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 };
4934
+ 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, NO_PAYMENTS, 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 WalletApiOption, 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
@@ -4558,6 +4558,26 @@ var GroupVisibility = {
4558
4558
  PRIVATE: "PRIVATE"
4559
4559
  };
4560
4560
 
4561
+ // modules/groupchat/group-id.ts
4562
+ var MAX_SLUG_LENGTH = 24;
4563
+ var RANDOM_BYTES = 8;
4564
+ function groupIdSlug(name) {
4565
+ const slug = name.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().replace(/['\u2019]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4566
+ if (slug.length <= MAX_SLUG_LENGTH) return slug;
4567
+ const head = slug.slice(0, MAX_SLUG_LENGTH + 1);
4568
+ const hyphen = head.lastIndexOf("-");
4569
+ return hyphen > 0 ? head.slice(0, hyphen) : slug.slice(0, MAX_SLUG_LENGTH);
4570
+ }
4571
+ function newGroupId(name) {
4572
+ const crypto2 = globalThis.crypto;
4573
+ if (typeof crypto2?.getRandomValues !== "function") {
4574
+ throw new SphereError("Creating a group requires crypto.getRandomValues", "INVALID_CONFIG");
4575
+ }
4576
+ const bytes = crypto2.getRandomValues(new Uint8Array(RANDOM_BYTES));
4577
+ const random = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
4578
+ return `${groupIdSlug(name) || "group"}-${random}`;
4579
+ }
4580
+
4561
4581
  // modules/groupchat/GroupChatModule.ts
4562
4582
  function createNip29Filter(data) {
4563
4583
  return new Filter3(data);
@@ -5169,9 +5189,9 @@ var GroupChatModule = class {
5169
5189
  if (!this.client) return null;
5170
5190
  const creatorPubkey = this.getMyPublicKey();
5171
5191
  if (!creatorPubkey) return null;
5172
- const proposedGroupId = options.name.toLowerCase().replace(/[^a-z0-9]/g, "").slice(0, 20) || this.randomId();
5173
5192
  try {
5174
5193
  const isPrivate = options.visibility === GroupVisibility.PRIVATE;
5194
+ const proposedGroupId = newGroupId(options.name);
5175
5195
  const eventId = await this.client.createAndPublishEvent({
5176
5196
  kind: NIP29_KINDS.CREATE_GROUP,
5177
5197
  tags: [["h", proposedGroupId]],
@@ -16990,7 +17010,16 @@ var WalletApiSplitCheckpointStore = class {
16990
17010
  };
16991
17011
 
16992
17012
  // core/payments-v2-wiring.ts
17013
+ var NO_PAYMENTS = "none";
17014
+ function readPaymentsOptOut(walletApi) {
17015
+ if (walletApi === NO_PAYMENTS) return NO_PAYMENTS;
17016
+ throw new SphereError(
17017
+ `walletApi must be a wallet-api transport config or the literal '${NO_PAYMENTS}' (the explicit messaging-only opt-out, #793) \u2014 received ${JSON.stringify(walletApi)}.`,
17018
+ "INVALID_CONFIG"
17019
+ );
17020
+ }
16993
17021
  function resolvePaymentsV2Composition(walletApi, sphereNetwork) {
17022
+ if (typeof walletApi === "string") return readPaymentsOptOut(walletApi);
16994
17023
  const source = walletApi;
16995
17024
  const network = typeof source?.network === "string" && source.network !== "" ? source.network : null;
16996
17025
  if (!source || network === null) {
@@ -17270,7 +17299,11 @@ var Sphere = class _Sphere {
17270
17299
  // The payments vertical (the ONLY money path since the P11 flip)
17271
17300
  /** The ACTIVE address's running vertical — §7: exactly one at a time, ever. */
17272
17301
  _paymentsV2Active = null;
17273
- /** Resolved wallet-api transport composition (network + per-address factory); set at init, fail-closed. */
17302
+ /**
17303
+ * Money composition, set at init. `null` = never resolved (a construction bug),
17304
+ * `NO_PAYMENTS` = the explicit #793 opt-out, an object = a real composition. One
17305
+ * spelling for the last two would read a forgotten resolve as messaging-only.
17306
+ */
17274
17307
  _paymentsV2Composition = null;
17275
17308
  /**
17276
17309
  * §7 lifecycle mutex: every stop/start pair runs strictly serialized, so
@@ -17946,10 +17979,24 @@ var Sphere = class _Sphere {
17946
17979
  get payments() {
17947
17980
  const facade = this._paymentsV2Active?.facade;
17948
17981
  if (!facade) {
17982
+ if (this._paymentsV2Composition === NO_PAYMENTS) {
17983
+ throw new SphereError(
17984
+ "payments is not composed: this Sphere was initialised with `walletApi: 'none'`, the explicit messaging-only composition. Money has no path here \u2014 re-init with a wallet-api transport config to move any.",
17985
+ "PAYMENTS_NOT_COMPOSED"
17986
+ );
17987
+ }
17949
17988
  throw new SphereError("Sphere not initialized", "NOT_INITIALIZED");
17950
17989
  }
17951
17990
  return facade;
17952
17991
  }
17992
+ /**
17993
+ * Whether this Sphere composes money at all (#793) — fixed for the instance's life,
17994
+ * so a messaging-only wallet can branch without a try/catch. Not a liveness check:
17995
+ * `true` still leaves `payments` throwing NOT_INITIALIZED mid-init or mid-switch.
17996
+ */
17997
+ get hasPayments() {
17998
+ return this._paymentsV2Composition !== NO_PAYMENTS;
17999
+ }
17953
18000
  /** Communications module */
17954
18001
  get communications() {
17955
18002
  this.ensureReady();
@@ -19977,6 +20024,7 @@ var Sphere = class _Sphere {
19977
20024
  * breaks initialization.
19978
20025
  */
19979
20026
  async buildTokenEngine(identity) {
20027
+ if (this._paymentsV2Composition === NO_PAYMENTS) return void 0;
19980
20028
  const oracle = this._oracle;
19981
20029
  const privateKey = (identity ?? this._identity)?.privateKey;
19982
20030
  const trustBaseJson = oracle.getTrustBaseJson?.() ?? null;
@@ -20082,6 +20130,7 @@ var Sphere = class _Sphere {
20082
20130
  * setOracleApiKey rebuild is what future operations snapshot.
20083
20131
  */
20084
20132
  async startPaymentsV2Inner(index, identity) {
20133
+ if (this._paymentsV2Composition === NO_PAYMENTS) return;
20085
20134
  if (!this._paymentsV2Composition) {
20086
20135
  throw new SphereError("wallet-api composition required for money", "INVALID_CONFIG");
20087
20136
  }
@@ -20773,6 +20822,7 @@ export {
20773
20822
  NFT_SIGNED_TAG,
20774
20823
  NIP29_KINDS,
20775
20824
  NOSTR_EVENT_KINDS,
20825
+ NO_PAYMENTS,
20776
20826
  NostrClient4 as NostrClient,
20777
20827
  NostrKeyManager4 as NostrKeyManager,
20778
20828
  PartialSendConflictError,