@bananalink-sdk/protocol 1.2.8 → 1.3.0

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 (52) hide show
  1. package/dist/{chunk-32OWUOZ3.js → chunk-KJ7QIHAY.js} +11 -7
  2. package/dist/chunk-KJ7QIHAY.js.map +1 -0
  3. package/dist/{chunk-VXLUSU5B.cjs → chunk-MUYKP6UQ.cjs} +63 -8
  4. package/dist/chunk-MUYKP6UQ.cjs.map +1 -0
  5. package/dist/{chunk-MCZG7QEM.cjs → chunk-NGPP7HUR.cjs} +11 -7
  6. package/dist/chunk-NGPP7HUR.cjs.map +1 -0
  7. package/dist/{chunk-LELPCIE7.js → chunk-OBJR2TL4.js} +54 -4
  8. package/dist/chunk-OBJR2TL4.js.map +1 -0
  9. package/dist/crypto/providers/noble-provider.cjs +2 -3
  10. package/dist/crypto/providers/noble-provider.d.cts +0 -7
  11. package/dist/crypto/providers/noble-provider.d.ts +0 -7
  12. package/dist/crypto/providers/noble-provider.js +1 -2
  13. package/dist/crypto/providers/node-provider.cjs +7 -29
  14. package/dist/crypto/providers/node-provider.cjs.map +1 -1
  15. package/dist/crypto/providers/node-provider.d.cts +0 -7
  16. package/dist/crypto/providers/node-provider.d.ts +0 -7
  17. package/dist/crypto/providers/node-provider.js +7 -29
  18. package/dist/crypto/providers/node-provider.js.map +1 -1
  19. package/dist/crypto/providers/quickcrypto-provider.cjs +8 -46
  20. package/dist/crypto/providers/quickcrypto-provider.cjs.map +1 -1
  21. package/dist/crypto/providers/quickcrypto-provider.d.cts +0 -9
  22. package/dist/crypto/providers/quickcrypto-provider.d.ts +0 -9
  23. package/dist/crypto/providers/quickcrypto-provider.js +7 -45
  24. package/dist/crypto/providers/quickcrypto-provider.js.map +1 -1
  25. package/dist/crypto/providers/webcrypto-provider.cjs +0 -2
  26. package/dist/crypto/providers/webcrypto-provider.cjs.map +1 -1
  27. package/dist/crypto/providers/webcrypto-provider.d.cts +0 -7
  28. package/dist/crypto/providers/webcrypto-provider.d.ts +0 -7
  29. package/dist/crypto/providers/webcrypto-provider.js +0 -2
  30. package/dist/crypto/providers/webcrypto-provider.js.map +1 -1
  31. package/dist/crypto-export.cjs +50 -51
  32. package/dist/crypto-export.cjs.map +1 -1
  33. package/dist/crypto-export.js +2 -4
  34. package/dist/crypto-export.js.map +1 -1
  35. package/dist/index.cjs +3 -4
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.js +2 -3
  38. package/dist/index.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/crypto/providers/noble-provider.ts +44 -49
  41. package/src/crypto/providers/node-provider.ts +18 -59
  42. package/src/crypto/providers/quickcrypto-provider.ts +25 -84
  43. package/src/crypto/providers/registry.ts +14 -9
  44. package/src/crypto/providers/webcrypto-provider.ts +28 -43
  45. package/dist/chunk-32OWUOZ3.js.map +0 -1
  46. package/dist/chunk-A6FLEJ7R.cjs +0 -62
  47. package/dist/chunk-A6FLEJ7R.cjs.map +0 -1
  48. package/dist/chunk-LELPCIE7.js.map +0 -1
  49. package/dist/chunk-MCZG7QEM.cjs.map +0 -1
  50. package/dist/chunk-TCVKC227.js +0 -56
  51. package/dist/chunk-TCVKC227.js.map +0 -1
  52. package/dist/chunk-VXLUSU5B.cjs.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/wallet-messages.ts","../src/types/client-messages.ts","../src/types/relay-messages.ts","../src/utils/public-keys.ts","../src/utils/url-encoding.ts","../src/utils/url-decoding.ts","../src/utils/wallet-session-claim.ts","../src/utils/client-session-claim.ts","../src/utils/index.ts","../package.json","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Wallet message types for BananaLink protocol v2.0\n * These types define the communication between wallets and the relay server\n */\n\nimport type { EncryptedPayload } from './discovery';\nimport type { DAppMetadata, SessionConfig } from './core';\nimport type { CloseSessionPayload } from './client-messages';\nimport type {\n RequestFulfilledPayload,\n RequestRejectedPayload,\n} from './post-auth-operations';\n\n/**\n * Wallet session claim credential for claiming and reconnection\n * NEVER forwarded to dApp - relay server only\n */\nexport interface WalletSessionClaim {\n /**\n * Unique nonce for this session claim\n * - Generated once by wallet when claiming session\n * - Stored locally by wallet for reconnection\n * - Used by relay to validate session ownership\n * - Different for each session (no cross-session tracking)\n */\n sessionNonce: string;\n\n /** Claim timestamp (used for replay attack prevention) */\n timestamp: number;\n}\n\n/**\n * Wallet message envelope structure\n * All wallet-to-relay messages use this envelope\n */\nexport interface WalletMessageEnvelope {\n /** Session identifier */\n sessionId: string;\n\n /** Wallet session claim credential - ONLY visible to relay server */\n walletSessionClaim: WalletSessionClaim;\n\n /** Actual message payload */\n payload: WalletMessagePayload;\n}\n\n/**\n * Claim session payload\n * Used to claim exclusive ownership of a session\n */\nexport interface ClaimSessionPayload {\n type: 'claim_session';\n /** Wallet's public key for ECDH key exchange in format \"algorithm:base64_public_key\" (e.g., \"AES-GCM:...\") */\n walletPublicKey: string;\n}\n\n/**\n * Prefetch metadata payload\n * Used to retrieve dApp metadata for user approval\n */\nexport interface PrefetchMetadataPayload {\n type: 'prefetch_metadata';\n}\n\n/**\n * Connection rejected payload\n * Notifies dApp that user rejected connection\n */\nexport interface ConnectionRejectedPayload {\n type: 'connection_rejected';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Authenticate connection payload\n * Completes authentication with signed message\n */\nexport interface AuthenticateConnectionPayload {\n type: 'authenticate_connection';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Wallet reconnect payload\n * Used to reconnect after network interruption\n */\nexport interface WalletReconnectPayload {\n type: 'wallet_reconnect';\n}\n\n/**\n * Union type for all wallet message payloads\n */\nexport type WalletMessagePayload =\n // Connection flow payloads\n | ClaimSessionPayload\n | PrefetchMetadataPayload\n | ConnectionRejectedPayload\n | AuthenticateConnectionPayload\n | WalletReconnectPayload\n | CloseSessionPayload\n // Post-authentication operation payloads (v2.1+)\n | RequestFulfilledPayload\n | RequestRejectedPayload;\n\n/**\n * Decrypted rejection data (visible only to dApp after decryption)\n */\nexport interface RejectionData {\n reason?: string;\n timestamp: number;\n}\n\n/**\n * Decrypted authentication data (visible only to dApp after decryption)\n */\nexport interface AuthenticationData {\n /** Wallet address */\n address: string;\n\n /** Signature of the SIWE message */\n signature: string;\n\n /** Full SIWE message that was signed */\n message: string;\n\n /** Chain ID (EIP-155) */\n chainId: number;\n\n /** Network identifier (e.g., \"ethereum\", \"polygon\") */\n network?: string;\n\n /** Signing algorithm (e.g., \"ECDSA\", \"EdDSA\") */\n signingAlgo?: string;\n\n /** Optional wallet metadata */\n walletMetadata?: WalletMetadata;\n}\n\n/**\n * Wallet metadata\n */\nexport interface WalletMetadata {\n /** Wallet name */\n name: string;\n\n /** Wallet version */\n version?: string;\n\n /** Wallet icon URL */\n icon?: string;\n\n /** Wallet description */\n description?: string;\n\n /** Wallet website URL */\n url?: string;\n\n /** Wallet provider type */\n provider?: string;\n}\n\n/**\n * Messages sent from relay to dApp (session claim stripped)\n */\n\n/**\n * Wallet handshake message\n * Initiates cryptographic handshake by sharing wallet's public key\n * and notifying dApp that wallet is reviewing connection\n */\nexport interface WalletHandshakeMessage {\n type: 'wallet_handshake';\n status: 'reviewing';\n /** Wallet's public key in format \"algorithm:base64_public_key\" (e.g., \"AES-GCM:...\") */\n walletPublicKey: string;\n timestamp: number;\n}\n\n/**\n * Connection rejected message\n * Forwards rejection to dApp (encrypted)\n */\nexport interface ConnectionRejectedMessage {\n type: 'connection_rejected';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Connection authenticated message\n * Forwards authentication data to dApp (encrypted)\n */\nexport interface ConnectionAuthenticatedMessage {\n type: 'connection_authenticated';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Prefetch metadata response\n * Returns dApp metadata to wallet\n */\nexport interface PrefetchMetadataResponse {\n dappMetadata: DAppMetadata;\n sessionConfig?: SessionConfig;\n}\n\n/**\n * Union type for relay-to-dApp messages\n */\nexport type RelayToDAppMessage =\n | WalletHandshakeMessage\n | ConnectionRejectedMessage\n | ConnectionAuthenticatedMessage;\n\n/**\n * Type guards for wallet messages\n */\nexport function isClaimSessionPayload(payload: WalletMessagePayload): payload is ClaimSessionPayload {\n return payload?.type === 'claim_session';\n}\n\nexport function isPrefetchMetadataPayload(payload: WalletMessagePayload): payload is PrefetchMetadataPayload {\n return payload?.type === 'prefetch_metadata';\n}\n\nexport function isConnectionRejectedPayload(payload: WalletMessagePayload): payload is ConnectionRejectedPayload {\n return payload?.type === 'connection_rejected';\n}\n\nexport function isAuthenticateConnectionPayload(payload: WalletMessagePayload): payload is AuthenticateConnectionPayload {\n return payload?.type === 'authenticate_connection';\n}\n\nexport function isWalletReconnectPayload(payload: WalletMessagePayload): payload is WalletReconnectPayload {\n return payload?.type === 'wallet_reconnect';\n}\n\n/**\n * Type guards for relay-to-dApp messages\n */\nexport function isWalletHandshakeMessage(message: RelayToDAppMessage): message is WalletHandshakeMessage {\n return message?.type === 'wallet_handshake';\n}\n\nexport function isConnectionRejectedMessage(message: RelayToDAppMessage): message is ConnectionRejectedMessage {\n return message?.type === 'connection_rejected';\n}\n\nexport function isConnectionAuthenticatedMessage(message: RelayToDAppMessage): message is ConnectionAuthenticatedMessage {\n return message?.type === 'connection_authenticated';\n}\n","/**\n * Client message types for BananaLink protocol v2.0\n * These types define the communication between dApp clients and the relay server\n */\n\nimport type {\n SignMessageRequestPayload,\n SignTypedDataRequestPayload,\n SignTransactionRequestPayload,\n} from './post-auth-operations';\n\n/**\n * Client session claim credential for authentication and reconnection\n * Stored by client, validated by relay server\n */\nexport interface ClientSessionClaim {\n /**\n * Unique nonce for this client session\n * - Generated once by client during session creation\n * - Stored locally by client for reconnection\n * - Used by relay to validate client ownership\n * - Different for each session\n */\n claimNonce: string;\n\n /** Claim generation timestamp */\n timestamp: number;\n}\n\n/**\n * Client reconnect payload\n * Used to reconnect after network interruption\n */\nexport interface ClientReconnectPayload {\n type: 'client_reconnect';\n}\n\n/**\n * Close session payload\n * Used to gracefully close a session (bidirectional)\n */\nexport interface CloseSessionPayload {\n type: 'close_session';\n /** Optional reason for closing the session */\n reason?: string;\n}\n\n/**\n * Union type for all client message payloads\n */\nexport type ClientMessagePayload =\n // Session management payloads\n | ClientReconnectPayload\n | CloseSessionPayload\n // Post-authentication operation request payloads (v2.1+)\n | SignMessageRequestPayload\n | SignTypedDataRequestPayload\n | SignTransactionRequestPayload;\n\n/**\n * Client message envelope structure\n * All client-to-relay messages use this envelope\n */\nexport interface ClientMessageEnvelope {\n /** Session identifier */\n sessionId: string;\n\n /** Client session claim - validated by relay server */\n clientSessionClaim: ClientSessionClaim;\n\n /** Actual message payload */\n payload: ClientMessagePayload;\n}\n\n/**\n * Type guards for client messages\n */\nexport function isClientReconnectPayload(payload: ClientMessagePayload): payload is ClientReconnectPayload {\n return payload?.type === 'client_reconnect';\n}\n\nexport function isCloseSessionPayload(payload: ClientMessagePayload): payload is CloseSessionPayload {\n return payload?.type === 'close_session';\n}\n","/**\n * Relay notification message types for BananaLink protocol v2.0\n * These are messages sent from relay server to clients/wallets\n */\n\n/**\n * Session closed acknowledgment\n * Sent to acknowledge a close_session request\n */\nexport interface SessionClosedAck {\n type: 'session_closed_ack';\n timestamp: number;\n}\n\n/**\n * Session closed notification\n * Sent to notify the other party that peer closed the session\n */\nexport interface SessionClosedNotification {\n type: 'session_closed_notification';\n /** Which party closed the session */\n closedBy: 'client' | 'wallet';\n /** Optional reason for closure */\n reason?: string;\n timestamp: number;\n}\n\n/**\n * Reconnected confirmation message\n * Sent after successful reconnection\n */\nexport interface ReconnectedMessage {\n type: 'reconnected';\n /** Number of messages that were queued during disconnection */\n queuedMessages: number;\n timestamp: number;\n}\n\n/**\n * Union type for relay notification messages\n */\nexport type RelayNotificationMessage =\n | SessionClosedAck\n | SessionClosedNotification\n | ReconnectedMessage;\n\n/**\n * Type guards for relay notification messages\n */\nexport function isSessionClosedAck(message: RelayNotificationMessage): message is SessionClosedAck {\n return message?.type === 'session_closed_ack';\n}\n\nexport function isSessionClosedNotification(message: RelayNotificationMessage): message is SessionClosedNotification {\n return message?.type === 'session_closed_notification';\n}\n\nexport function isReconnectedMessage(message: RelayNotificationMessage): message is ReconnectedMessage {\n return message?.type === 'reconnected';\n}\n","/**\n * Public key compression utilities for compact URL encoding\n *\n * These utilities convert public keys between standard base64 format\n * and compact base64url format for use in QR codes and URLs.\n */\n\n/**\n * Compress a public key for compact URLs\n * Removes AES-GCM: prefix and uses base64url without padding\n *\n * @param publicKey - Public key in format \"AES-GCM:base64string\" or \"base64string\"\n * @returns Compressed public key in base64url format without padding\n */\nexport function compressPublicKey(publicKey: string): string {\n // Remove AES-GCM: prefix if present\n const keyWithoutPrefix = publicKey.startsWith('AES-GCM:')\n ? publicKey.slice(8)\n : publicKey;\n\n // Convert base64 to base64url (replace + with -, / with _, remove padding)\n return keyWithoutPrefix\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Decompress a public key from compact format\n * Adds back AES-GCM: prefix and restores base64 padding\n *\n * @param compressedKey - Compressed public key in base64url format\n * @returns Public key in format \"AES-GCM:base64string\"\n */\nexport function decompressPublicKey(compressedKey: string): string {\n // Convert base64url back to base64\n let base64Key = compressedKey\n .replace(/-/g, '+')\n .replace(/_/g, '/');\n\n // Add padding if needed\n const padding = base64Key.length % 4;\n if (padding > 0) {\n base64Key += '='.repeat(4 - padding);\n }\n\n // Add AES-GCM prefix if not already present\n return base64Key.startsWith('AES-GCM:') ? base64Key : `AES-GCM:${base64Key}`;\n}\n","import type { QRPayload } from '../types/discovery';\nimport { DEEPLINK_SCHEME } from '../constants';\nimport { compressPublicKey } from './public-keys';\n\n/**\n * Provider shortcodes for compact URLs\n */\nconst PROVIDER_SHORTCODES: Record<string, string> = {\n 'uwebsockets': 'u', // Legacy - API may still return this\n 'websocket': 'w',\n 'pusher': 'p',\n 'ably': 'a',\n};\n\n/**\n * Production relay URLs that should be omitted in compact format (most common case)\n */\nconst PRODUCTION_RELAY_URLS = [\n 'wss://relay.banana.link/v1',\n 'https://relay.banana.link/v1',\n];\n\n/**\n * Environment shortcodes for non-production relay URLs\n */\nconst RELAY_SHORTCODES: Record<string, string> = {\n 'wss://relay.dev.banana.link/v1': 'd',\n 'https://relay.dev.banana.link/v1': 'd',\n 'wss://relay.staging.banana.link/v1': 's', // Future staging environment\n 'https://relay.staging.banana.link/v1': 's',\n};\n\n/**\n * Safely encode a URL parameter value\n * Uses encodeURIComponent to handle special characters like +, /, =\n */\nexport function encodeUrlParameter(value: string): string {\n return encodeURIComponent(value);\n}\n\n/**\n * Build a query string with properly encoded parameters\n */\nexport function buildQueryString(params: Record<string, string | undefined>): string {\n const pairs: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n pairs.push(`${encodeUrlParameter(key)}=${encodeUrlParameter(value)}`);\n }\n }\n\n return pairs.join('&');\n}\n\n/**\n * Create a compact deep link URL with shortened parameters\n * Uses single-letter parameters to minimize QR code size\n */\nexport function encodeCompactConnectionString(payload: QRPayload): string {\n const params: Record<string, string | undefined> = {\n s: payload.sessionId, // sessionId -> s\n k: compressPublicKey(payload.publicKey), // publicKey -> k (compressed)\n };\n\n // Add optional parameters with shortcodes\n if (payload.providerId) {\n params.p = PROVIDER_SHORTCODES[payload.providerId] || payload.providerId;\n }\n\n // Handle relay URL compression:\n // - Production: omit entirely (most common case)\n // - Development/Staging: use shortcode (r=d, r=s)\n // - Custom: use full URL\n if (payload.relayUrl) {\n if (PRODUCTION_RELAY_URLS.includes(payload.relayUrl)) {\n // Production relay - omit parameter entirely for maximum compression\n // This will be the most common case, so QR codes will be smallest\n } else if (RELAY_SHORTCODES[payload.relayUrl]) {\n // Known environment (dev/staging) - use shortcode\n params.r = RELAY_SHORTCODES[payload.relayUrl];\n } else {\n // Custom relay URL - include full URL\n params.r = payload.relayUrl;\n }\n }\n\n const queryString = buildQueryString(params);\n return `${DEEPLINK_SCHEME}://connect?${queryString}`;\n}\n\n/**\n * Create a deep link URL with properly encoded parameters\n * Uses full parameter names for readability\n */\nexport function encodeConnectionString(payload: QRPayload): string {\n const params: Record<string, string | undefined> = {\n sessionId: payload.sessionId,\n publicKey: payload.publicKey,\n };\n\n // Add optional parameters\n if (payload.providerId) {\n params.providerId = payload.providerId;\n }\n\n if (payload.relayUrl) {\n params.relay = payload.relayUrl;\n }\n\n const queryString = buildQueryString(params);\n return `${DEEPLINK_SCHEME}://connect?${queryString}`;\n}\n\n/**\n * Create a universal link (HTTPS) with properly encoded parameters\n */\nexport function encodeUniversalLink(payload: QRPayload, options: {\n baseUrl?: string;\n fallbackUrl?: string;\n} = {}): string {\n const {\n baseUrl = 'https://banana.link',\n fallbackUrl = 'https://banana.link/download',\n } = options;\n\n const params: Record<string, string | undefined> = {\n sessionId: payload.sessionId,\n key: payload.publicKey, // Use 'key' instead of 'publicKey' for universal links\n fallback: fallbackUrl,\n };\n\n // Add optional parameters\n if (payload.providerId) {\n params.provider = payload.providerId;\n }\n\n if (payload.relayUrl) {\n params.relay = payload.relayUrl;\n }\n\n const queryString = buildQueryString(params);\n return `${baseUrl}/connect?${queryString}`;\n}\n","import type { QRPayload } from '../types/discovery';\nimport { decompressPublicKey } from './public-keys';\n\n/**\n * Provider shortcodes reverse mapping for compact URL decoding\n */\nconst PROVIDER_SHORTCODES_REVERSE: Record<string, string> = {\n 'u': 'websocket', // Decode legacy 'u' to new 'websocket' name\n 'w': 'websocket',\n 'p': 'pusher',\n 'a': 'ably',\n};\n\n/**\n * Environment shortcodes reverse mapping for relay URL decoding\n */\nconst RELAY_SHORTCODES_REVERSE: Record<string, string> = {\n 'd': 'wss://relay.dev.banana.link/v1',\n 's': 'wss://relay.staging.banana.link/v1',\n};\n\n/**\n * Safely decode a URL parameter value\n * Uses decodeURIComponent to restore special characters\n */\nexport function decodeUrlParameter(value: string): string {\n return decodeURIComponent(value);\n}\n\n/**\n * Parse a query string with properly decoded parameters\n */\nexport function parseQueryString(query: string): Record<string, string> {\n const params: Record<string, string> = {};\n\n // Remove leading ? if present\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n\n if (!cleanQuery) {\n return params;\n }\n\n for (const pair of cleanQuery.split('&')) {\n const [key, ...valueParts] = pair.split('=');\n if (key) {\n const value = valueParts.join('='); // Handle values that contain =\n params[decodeUrlParameter(key)] = decodeUrlParameter(value);\n }\n }\n\n return params;\n}\n\n/**\n * Parse a connection string and extract the QRPayload with proper decoding\n * Supports both full format and compact format\n */\nexport function decodeConnectionString(connectionString: string): QRPayload {\n let url: URL;\n\n try {\n url = new URL(connectionString);\n } catch {\n throw new Error(`Invalid connection string format: ${connectionString}`);\n }\n\n // Parse query parameters using our safe decoder\n const params = parseQueryString(url.search);\n\n // Support both compact and full parameter formats\n const sessionId = params.sessionId || params.s; // full or compact\n let publicKey = params.publicKey || params.key || params.k; // full, universal, or compact\n let providerId = params.providerId || params.provider || params.p; // full, alt, or compact\n let relayUrl = params.relay || params.r; // full or compact\n\n if (!sessionId || !publicKey) {\n throw new Error('Missing required parameters: sessionId and publicKey');\n }\n\n // If we have a compact format public key (params.k), decompress it\n if (params.k && !params.publicKey && !params.key) {\n publicKey = decompressPublicKey(params.k);\n }\n\n // If we have a compact format provider, expand it\n if (params.p && !params.providerId && !params.provider) {\n providerId = PROVIDER_SHORTCODES_REVERSE[params.p] || params.p;\n }\n\n // Handle relay URL decompression:\n // - No relay parameter = production (default)\n // - Shortcode (d, s) = expand to full environment URL\n // - Full URL = use as-is\n if (!relayUrl) {\n // No relay parameter means production (most common case)\n relayUrl = 'wss://relay.banana.link/v1';\n } else if (RELAY_SHORTCODES_REVERSE[relayUrl]) {\n // Environment shortcode - expand to full URL\n relayUrl = RELAY_SHORTCODES_REVERSE[relayUrl];\n }\n // else: already a full URL, use as-is\n\n // Ensure public key has AES-GCM prefix for backward compatibility\n if (publicKey && !publicKey.startsWith('AES-GCM:')) {\n publicKey = `AES-GCM:${publicKey}`;\n }\n\n return {\n sessionId,\n publicKey,\n providerId: providerId || undefined,\n relayUrl: relayUrl || undefined,\n };\n}\n\n/**\n * Validate that a string is a valid connection string\n */\nexport function isValidConnectionString(connectionString: string): boolean {\n try {\n decodeConnectionString(connectionString);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Session claiming mechanism utilities for BananaLink protocol v2.0\n * Implements secure session ownership and reconnection logic\n */\n\nimport type { WalletSessionClaim, WalletMessageEnvelope } from '../types/wallet-messages';\n\n/**\n * Wallet session claim storage interface\n * Implementations should provide secure storage for wallet session claims\n */\nexport interface WalletSessionClaimStorage {\n store(sessionId: string, claim: WalletSessionClaim): Promise<void>;\n retrieve(sessionId: string): Promise<WalletSessionClaim | null>;\n remove(sessionId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\n/**\n * Wallet session claim manager for handling claim generation and validation\n */\nexport class WalletSessionClaimManager {\n constructor(private storage: WalletSessionClaimStorage) {}\n\n /**\n * Generate a new wallet session claim with provided nonce\n * @param sessionId - Session identifier\n * @param sessionNonce - Pre-generated cryptographically secure nonce (use @bananalink-sdk/crypto)\n * @returns Generated wallet session claim\n */\n async generateClaim(sessionId: string, sessionNonce: string): Promise<WalletSessionClaim> {\n const claim: WalletSessionClaim = {\n sessionNonce,\n timestamp: Date.now(),\n };\n\n // Store the claim for future reconnection\n await this.storage.store(sessionId, claim);\n\n return claim;\n }\n\n /**\n * Retrieve an existing wallet session claim\n * @param sessionId - Session identifier\n * @returns Stored wallet session claim or null if not found\n */\n async getClaim(sessionId: string): Promise<WalletSessionClaim | null> {\n return this.storage.retrieve(sessionId);\n }\n\n /**\n * Validate a wallet session claim for reconnection\n * @param claim - Claim to validate\n * @param storedClaim - Previously stored claim\n * @returns Validation result\n */\n validateReconnectionClaim(\n claim: WalletSessionClaim,\n storedClaim: WalletSessionClaim\n ): { valid: boolean; reason?: string } {\n // Check nonce match\n if (claim.sessionNonce !== storedClaim.sessionNonce) {\n return {\n valid: false,\n reason: 'Session nonce mismatch - invalid reconnection attempt',\n };\n }\n\n // Check timestamp validity (prevent very old reconnection attempts)\n const MAX_RECONNECTION_AGE = 24 * 60 * 60 * 1000; // 24 hours\n const claimAge = Date.now() - claim.timestamp;\n if (claimAge > MAX_RECONNECTION_AGE) {\n return {\n valid: false,\n reason: 'Session claim too old - please create a new session',\n };\n }\n\n return { valid: true };\n }\n\n /**\n * Remove a wallet session claim (on session end)\n * @param sessionId - Session identifier\n */\n async removeClaim(sessionId: string): Promise<void> {\n await this.storage.remove(sessionId);\n }\n\n /**\n * Clear all stored claims\n */\n async clearAllClaims(): Promise<void> {\n await this.storage.clear();\n }\n}\n\n// NOTE: Nonce generation moved to @bananalink-sdk/crypto package to avoid circular dependencies\n// SDKs should use crypto.generateSessionNonce() before creating session claims\n\n/**\n * Create a wallet message envelope with wallet session claim\n * @param sessionId - Session identifier\n * @param claim - Wallet session claim\n * @param payload - Message payload\n * @returns Complete wallet message envelope\n */\nexport function createWalletMessageEnvelope(\n sessionId: string,\n claim: WalletSessionClaim,\n payload: WalletMessageEnvelope['payload']\n): WalletMessageEnvelope {\n return {\n sessionId,\n walletSessionClaim: claim,\n payload,\n };\n}\n\n/**\n * Strip wallet session claim from wallet message for forwarding to dApp\n * @param envelope - Original wallet message envelope\n * @returns Message without wallet session claim\n */\nexport function stripWalletSessionClaim(\n envelope: WalletMessageEnvelope\n): Omit<WalletMessageEnvelope, 'walletSessionClaim'> {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { walletSessionClaim, ...messageWithoutClaim } = envelope;\n return messageWithoutClaim;\n}\n\n/**\n * Validate session claim timestamp for replay attack prevention\n * @param timestamp - Claim timestamp\n * @param maxAge - Maximum age in milliseconds (default: 30 seconds)\n * @returns True if timestamp is within valid range\n */\nexport function validateClaimTimestamp(\n timestamp: number,\n maxAge: number = 30 * 1000\n): boolean {\n const now = Date.now();\n const age = Math.abs(now - timestamp);\n return age <= maxAge;\n}\n\n/**\n * Validate wallet message envelope\n * @param envelope - Message envelope to validate\n * @returns Validation result\n */\nexport function validateWalletMessageEnvelope(\n envelope: WalletMessageEnvelope\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required fields\n if (!envelope.sessionId) {\n errors.push('Missing session ID');\n }\n\n if (!envelope.walletSessionClaim) {\n errors.push('Missing wallet session claim');\n } else {\n // Validate claim structure\n if (!envelope.walletSessionClaim.sessionNonce) {\n errors.push('Missing session nonce in wallet session claim');\n }\n if (!envelope.walletSessionClaim.timestamp) {\n errors.push('Missing timestamp in wallet session claim');\n } else if (!validateClaimTimestamp(envelope.walletSessionClaim.timestamp)) {\n errors.push('Wallet session claim timestamp is too old or invalid');\n }\n }\n\n if (!envelope.payload) {\n errors.push('Missing message payload');\n } else if (!envelope.payload.type) {\n errors.push('Missing payload type');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Client session claim utilities for BananaLink protocol v2.0\n * Implements secure client session ownership and reconnection logic\n */\n\nimport type { ClientSessionClaim, ClientMessageEnvelope } from '../types/client-messages';\n\n/**\n * Client session claim storage interface\n * Implementations should provide secure storage for client session claims\n */\nexport interface ClientSessionClaimStorage {\n store(sessionId: string, claim: ClientSessionClaim): Promise<void>;\n retrieve(sessionId: string): Promise<ClientSessionClaim | null>;\n remove(sessionId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\n/**\n * Client session claim manager for handling claim generation and validation\n */\nexport class ClientSessionClaimManager {\n constructor(private storage: ClientSessionClaimStorage) {}\n\n /**\n * Generate a new client session claim with provided nonce\n * @param sessionId - Session identifier\n * @param claimNonce - Pre-generated cryptographically secure nonce (use @bananalink-sdk/crypto)\n * @returns Generated client session claim\n */\n async generateClaim(sessionId: string, claimNonce: string): Promise<ClientSessionClaim> {\n const claim: ClientSessionClaim = {\n claimNonce,\n timestamp: Date.now(),\n };\n\n // Store the claim for future reconnection\n await this.storage.store(sessionId, claim);\n\n return claim;\n }\n\n /**\n * Retrieve an existing client session claim\n * @param sessionId - Session identifier\n * @returns Stored client session claim or null if not found\n */\n async getClaim(sessionId: string): Promise<ClientSessionClaim | null> {\n return this.storage.retrieve(sessionId);\n }\n\n /**\n * Validate a client session claim for reconnection\n * @param claim - Claim to validate\n * @param storedClaim - Previously stored claim\n * @returns Validation result\n */\n validateReconnectionClaim(\n claim: ClientSessionClaim,\n storedClaim: ClientSessionClaim\n ): { valid: boolean; reason?: string } {\n // Check nonce match\n if (claim.claimNonce !== storedClaim.claimNonce) {\n return {\n valid: false,\n reason: 'Client claim nonce mismatch - invalid reconnection attempt',\n };\n }\n\n // Check timestamp validity (prevent very old reconnection attempts)\n const MAX_RECONNECTION_AGE = 24 * 60 * 60 * 1000; // 24 hours\n const claimAge = Date.now() - claim.timestamp;\n if (claimAge > MAX_RECONNECTION_AGE) {\n return {\n valid: false,\n reason: 'Client session claim too old - please create a new session',\n };\n }\n\n return { valid: true };\n }\n\n /**\n * Remove a client session claim (on session end)\n * @param sessionId - Session identifier\n */\n async removeClaim(sessionId: string): Promise<void> {\n await this.storage.remove(sessionId);\n }\n\n /**\n * Clear all stored claims\n */\n async clearAllClaims(): Promise<void> {\n await this.storage.clear();\n }\n}\n\n// NOTE: Nonce generation moved to @bananalink-sdk/crypto package to avoid circular dependencies\n// SDKs should use crypto.generateClientClaimNonce() before creating client session claims\n\n/**\n * Create a client message envelope with session claim\n * @param sessionId - Session identifier\n * @param claim - Client session claim\n * @param payload - Message payload\n * @returns Complete client message envelope\n */\nexport function createClientMessageEnvelope(\n sessionId: string,\n claim: ClientSessionClaim,\n payload: ClientMessageEnvelope['payload']\n): ClientMessageEnvelope {\n return {\n sessionId,\n clientSessionClaim: claim,\n payload,\n };\n}\n\n/**\n * Strip client session claim from client message for forwarding\n * @param envelope - Original client message envelope\n * @returns Message without client session claim\n */\nexport function stripClientSessionClaim(\n envelope: ClientMessageEnvelope\n): Omit<ClientMessageEnvelope, 'clientSessionClaim'> {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { clientSessionClaim, ...messageWithoutClaim } = envelope;\n return messageWithoutClaim;\n}\n\n/**\n * Validate client session claim timestamp for replay attack prevention\n * @param timestamp - Claim timestamp\n * @param maxAge - Maximum age in milliseconds (default: 30 seconds)\n * @returns True if timestamp is within valid range\n */\nexport function validateClientClaimTimestamp(\n timestamp: number,\n maxAge: number = 30 * 1000\n): boolean {\n const now = Date.now();\n const age = Math.abs(now - timestamp);\n return age <= maxAge;\n}\n\n/**\n * Validate client message envelope\n * @param envelope - Message envelope to validate\n * @returns Validation result\n */\nexport function validateClientMessageEnvelope(\n envelope: ClientMessageEnvelope\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required fields\n if (!envelope.sessionId) {\n errors.push('Missing session ID');\n }\n\n if (!envelope.clientSessionClaim) {\n errors.push('Missing client session claim');\n } else {\n // Validate claim structure\n if (!envelope.clientSessionClaim.claimNonce) {\n errors.push('Missing claim nonce in client session claim');\n }\n if (!envelope.clientSessionClaim.timestamp) {\n errors.push('Missing timestamp in client session claim');\n } else if (!validateClientClaimTimestamp(envelope.clientSessionClaim.timestamp)) {\n errors.push('Client session claim timestamp is too old or invalid');\n }\n }\n\n if (!envelope.payload) {\n errors.push('Missing message payload');\n } else if (!envelope.payload.type) {\n errors.push('Missing payload type');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Protocol utility functions\n *\n * This module provides utility functions that are specific to the BananaLink protocol.\n * SDK-specific utilities are implemented in their respective packages.\n */\n\nimport { generateUUID } from '../crypto/utils';\n\n/**\n * Generate a cryptographically secure session ID in RFC 4122 UUID v4 format\n *\n * This function delegates to the protocol crypto layer for mobile-safe UUID generation.\n * For direct access to UUID generation, prefer importing from @bananalink-sdk/protocol/crypto.\n *\n * @returns UUID v4 string (e.g., \"550e8400-e29b-41d4-a716-446655440000\")\n *\n * @example\n * const sessionId = generateSessionId();\n * // => \"a3bb189e-8bf9-4bdc-9f16-9f48a6a1e3e7\"\n */\nexport function generateSessionId(): string {\n return generateUUID();\n}\n\n// Protocol-specific utility that might be needed across packages\nexport function isValidProtocolVersion(version: string): boolean {\n // Only support version \"1\" for now\n return version === '1';\n}\n\n// Protocol-specific session ID validation\nexport function isValidSessionId(sessionId: string): boolean {\n // Session IDs should be valid UUIDs\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n return uuidRegex.test(sessionId);\n}\n\n// Export public key compression utilities\nexport * from './public-keys';\n\n// Export URL encoding and decoding utilities\nexport * from './url-encoding';\nexport * from './url-decoding';\n\n// Note: SIWE utilities have been moved to '@bananalink-sdk/protocol/siwe'\n// For ERC-4361 message construction and validation, import from '@bananalink-sdk/protocol/siwe'\n// Type-only definitions (SIWEFields, SIWEMessageOptions) remain available from main export\n\n// Export wallet session claiming utilities\nexport * from './wallet-session-claim';\n\n// Export client session claiming utilities\nexport * from './client-session-claim';\n","{\n \"name\": \"@bananalink-sdk/protocol\",\n \"version\": \"1.2.7\",\n \"description\": \"Core protocol definitions for BananaLink. Provides TypeScript types, Zod validation schemas, cryptographic utilities, and shared constants for wallet connections.\",\n \"type\": \"module\",\n \"keywords\": [\n \"bananalink\",\n \"protocol\",\n \"types\",\n \"schemas\",\n \"validation\",\n \"cryptography\",\n \"web3\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/bananalink/bananalink/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/bananalink/bananalink.git\",\n \"directory\": \"packages/protocol\"\n },\n \"license\": \"ISC\",\n \"author\": \"BananaLink Team <team@banana.link>\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"react-native\": \"./dist/index.js\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./schemas\": {\n \"types\": \"./dist/schemas-export.d.ts\",\n \"react-native\": \"./dist/schemas-export.js\",\n \"import\": \"./dist/schemas-export.js\",\n \"require\": \"./dist/schemas-export.cjs\"\n },\n \"./validators\": {\n \"types\": \"./dist/validators-export.d.ts\",\n \"react-native\": \"./dist/validators-export.js\",\n \"import\": \"./dist/validators-export.js\",\n \"require\": \"./dist/validators-export.cjs\"\n },\n \"./validation\": {\n \"types\": \"./dist/validation-export.d.ts\",\n \"react-native\": \"./dist/validation-export.js\",\n \"import\": \"./dist/validation-export.js\",\n \"require\": \"./dist/validation-export.cjs\"\n },\n \"./siwe\": {\n \"types\": \"./dist/siwe-export.d.ts\",\n \"react-native\": \"./dist/siwe-export.js\",\n \"import\": \"./dist/siwe-export.js\",\n \"require\": \"./dist/siwe-export.cjs\"\n },\n \"./crypto\": {\n \"types\": \"./dist/crypto-export.d.ts\",\n \"react-native\": \"./dist/crypto-export.js\",\n \"import\": \"./dist/crypto-export.js\",\n \"require\": \"./dist/crypto-export.cjs\"\n },\n \"./crypto/provider/webcrypto\": {\n \"types\": \"./dist/crypto/providers/webcrypto-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/webcrypto-provider.js\",\n \"import\": \"./dist/crypto/providers/webcrypto-provider.js\",\n \"require\": \"./dist/crypto/providers/webcrypto-provider.cjs\"\n },\n \"./crypto/provider/node\": {\n \"types\": \"./dist/crypto/providers/node-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/node-provider.js\",\n \"import\": \"./dist/crypto/providers/node-provider.js\",\n \"require\": \"./dist/crypto/providers/node-provider.cjs\"\n },\n \"./crypto/provider/noble\": {\n \"types\": \"./dist/crypto/providers/noble-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/noble-provider.js\",\n \"import\": \"./dist/crypto/providers/noble-provider.js\",\n \"require\": \"./dist/crypto/providers/noble-provider.cjs\"\n },\n \"./crypto/provider/quickcrypto\": {\n \"types\": \"./dist/crypto/providers/quickcrypto-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/quickcrypto-provider.js\",\n \"import\": \"./dist/crypto/providers/quickcrypto-provider.js\",\n \"require\": \"./dist/crypto/providers/quickcrypto-provider.cjs\"\n },\n \"./testing\": {\n \"types\": \"./dist/testing.d.ts\",\n \"react-native\": \"./dist/testing.js\",\n \"import\": \"./dist/testing.js\",\n \"require\": \"./dist/testing.cjs\"\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"src\",\n \"!src/__tests__\"\n ],\n \"publishConfig\": {\n \"access\": \"restricted\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"clean\": \"rm -rf dist node_modules\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint src --ext .ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"dependencies\": {\n \"@bananalink-sdk/logger\": \"workspace:*\",\n \"@noble/ciphers\": \"^2.0.0\",\n \"@noble/curves\": \"^2.0.0\",\n \"@noble/hashes\": \"^2.0.0\",\n \"zod\": \"^3.25.67\"\n },\n \"devDependencies\": {\n \"@bananalink-sdk/eslint-config\": \"workspace:*\",\n \"@bananalink-sdk/typescript-config\": \"workspace:*\",\n \"@types/node\": \"^24.1.0\",\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"eslint\": \"^9.29.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.3\",\n \"vitest\": \"^3.2.4\"\n },\n \"peerDependencies\": {\n \"react-native-quick-crypto\": \"^0.7.0\"\n },\n \"peerDependenciesMeta\": {\n \"react-native-quick-crypto\": {\n \"optional\": true\n }\n },\n \"packageManager\": \"pnpm@10.15.1\"\n}\n","/**\n * BananaLink Protocol Package\n *\n * Core TypeScript implementation of the BananaLink protocol for dApp-to-wallet communication.\n * Provides types, schemas, constants, and utilities for implementing BananaLink clients and wallets.\n *\n * @packageDocumentation\n */\n\n// Core protocol types\nexport * from './types/core';\nexport * from './types/auth';\nexport * from './types/crypto';\nexport * from './types/discovery';\nexport * from './types/errors';\nexport * from './types/providers';\nexport * from './types/wallet-messages';\nexport * from './types/client-messages';\nexport * from './types/relay-messages';\n\n// Note: Zod validation schemas have been moved to '@bananalink-sdk/protocol/schemas'\n// For runtime validation, import from '@bananalink-sdk/protocol/schemas'\n// Type-only definitions remain available from this main export\n\n// Note: SIWE utilities have been moved to '@bananalink-sdk/protocol/siwe'\n// For ERC-4361 message construction/parsing, import from '@bananalink-sdk/protocol/siwe'\n// Export SIWE types for convenience (type-only, no runtime code)\nexport type { SIWEMessageOptions } from './utils/siwe';\n\n// Constants and utilities\nexport * from './constants';\nexport * from './utils';\n\n// Package metadata\n// Note: Version is imported from package.json to ensure consistency\nimport packageJson from '../package.json';\nexport const VERSION = packageJson.version;\nexport const PACKAGE_NAME = \"@bananalink-sdk/protocol\";\n"]}
1
+ {"version":3,"sources":["../src/types/wallet-messages.ts","../src/types/client-messages.ts","../src/types/relay-messages.ts","../src/utils/public-keys.ts","../src/utils/url-encoding.ts","../src/utils/url-decoding.ts","../src/utils/wallet-session-claim.ts","../src/utils/client-session-claim.ts","../src/utils/index.ts","../package.json","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Wallet message types for BananaLink protocol v2.0\n * These types define the communication between wallets and the relay server\n */\n\nimport type { EncryptedPayload } from './discovery';\nimport type { DAppMetadata, SessionConfig } from './core';\nimport type { CloseSessionPayload } from './client-messages';\nimport type {\n RequestFulfilledPayload,\n RequestRejectedPayload,\n} from './post-auth-operations';\n\n/**\n * Wallet session claim credential for claiming and reconnection\n * NEVER forwarded to dApp - relay server only\n */\nexport interface WalletSessionClaim {\n /**\n * Unique nonce for this session claim\n * - Generated once by wallet when claiming session\n * - Stored locally by wallet for reconnection\n * - Used by relay to validate session ownership\n * - Different for each session (no cross-session tracking)\n */\n sessionNonce: string;\n\n /** Claim timestamp (used for replay attack prevention) */\n timestamp: number;\n}\n\n/**\n * Wallet message envelope structure\n * All wallet-to-relay messages use this envelope\n */\nexport interface WalletMessageEnvelope {\n /** Session identifier */\n sessionId: string;\n\n /** Wallet session claim credential - ONLY visible to relay server */\n walletSessionClaim: WalletSessionClaim;\n\n /** Actual message payload */\n payload: WalletMessagePayload;\n}\n\n/**\n * Claim session payload\n * Used to claim exclusive ownership of a session\n */\nexport interface ClaimSessionPayload {\n type: 'claim_session';\n /** Wallet's public key for ECDH key exchange in format \"algorithm:base64_public_key\" (e.g., \"AES-GCM:...\") */\n walletPublicKey: string;\n}\n\n/**\n * Prefetch metadata payload\n * Used to retrieve dApp metadata for user approval\n */\nexport interface PrefetchMetadataPayload {\n type: 'prefetch_metadata';\n}\n\n/**\n * Connection rejected payload\n * Notifies dApp that user rejected connection\n */\nexport interface ConnectionRejectedPayload {\n type: 'connection_rejected';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Authenticate connection payload\n * Completes authentication with signed message\n */\nexport interface AuthenticateConnectionPayload {\n type: 'authenticate_connection';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Wallet reconnect payload\n * Used to reconnect after network interruption\n */\nexport interface WalletReconnectPayload {\n type: 'wallet_reconnect';\n}\n\n/**\n * Union type for all wallet message payloads\n */\nexport type WalletMessagePayload =\n // Connection flow payloads\n | ClaimSessionPayload\n | PrefetchMetadataPayload\n | ConnectionRejectedPayload\n | AuthenticateConnectionPayload\n | WalletReconnectPayload\n | CloseSessionPayload\n // Post-authentication operation payloads (v2.1+)\n | RequestFulfilledPayload\n | RequestRejectedPayload;\n\n/**\n * Decrypted rejection data (visible only to dApp after decryption)\n */\nexport interface RejectionData {\n reason?: string;\n timestamp: number;\n}\n\n/**\n * Decrypted authentication data (visible only to dApp after decryption)\n */\nexport interface AuthenticationData {\n /** Wallet address */\n address: string;\n\n /** Signature of the SIWE message */\n signature: string;\n\n /** Full SIWE message that was signed */\n message: string;\n\n /** Chain ID (EIP-155) */\n chainId: number;\n\n /** Network identifier (e.g., \"ethereum\", \"polygon\") */\n network?: string;\n\n /** Signing algorithm (e.g., \"ECDSA\", \"EdDSA\") */\n signingAlgo?: string;\n\n /** Optional wallet metadata */\n walletMetadata?: WalletMetadata;\n}\n\n/**\n * Wallet metadata\n */\nexport interface WalletMetadata {\n /** Wallet name */\n name: string;\n\n /** Wallet version */\n version?: string;\n\n /** Wallet icon URL */\n icon?: string;\n\n /** Wallet description */\n description?: string;\n\n /** Wallet website URL */\n url?: string;\n\n /** Wallet provider type */\n provider?: string;\n}\n\n/**\n * Messages sent from relay to dApp (session claim stripped)\n */\n\n/**\n * Wallet handshake message\n * Initiates cryptographic handshake by sharing wallet's public key\n * and notifying dApp that wallet is reviewing connection\n */\nexport interface WalletHandshakeMessage {\n type: 'wallet_handshake';\n status: 'reviewing';\n /** Wallet's public key in format \"algorithm:base64_public_key\" (e.g., \"AES-GCM:...\") */\n walletPublicKey: string;\n timestamp: number;\n}\n\n/**\n * Connection rejected message\n * Forwards rejection to dApp (encrypted)\n */\nexport interface ConnectionRejectedMessage {\n type: 'connection_rejected';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Connection authenticated message\n * Forwards authentication data to dApp (encrypted)\n */\nexport interface ConnectionAuthenticatedMessage {\n type: 'connection_authenticated';\n encrypted: EncryptedPayload;\n}\n\n/**\n * Prefetch metadata response\n * Returns dApp metadata to wallet\n */\nexport interface PrefetchMetadataResponse {\n dappMetadata: DAppMetadata;\n sessionConfig?: SessionConfig;\n}\n\n/**\n * Union type for relay-to-dApp messages\n */\nexport type RelayToDAppMessage =\n | WalletHandshakeMessage\n | ConnectionRejectedMessage\n | ConnectionAuthenticatedMessage;\n\n/**\n * Type guards for wallet messages\n */\nexport function isClaimSessionPayload(payload: WalletMessagePayload): payload is ClaimSessionPayload {\n return payload?.type === 'claim_session';\n}\n\nexport function isPrefetchMetadataPayload(payload: WalletMessagePayload): payload is PrefetchMetadataPayload {\n return payload?.type === 'prefetch_metadata';\n}\n\nexport function isConnectionRejectedPayload(payload: WalletMessagePayload): payload is ConnectionRejectedPayload {\n return payload?.type === 'connection_rejected';\n}\n\nexport function isAuthenticateConnectionPayload(payload: WalletMessagePayload): payload is AuthenticateConnectionPayload {\n return payload?.type === 'authenticate_connection';\n}\n\nexport function isWalletReconnectPayload(payload: WalletMessagePayload): payload is WalletReconnectPayload {\n return payload?.type === 'wallet_reconnect';\n}\n\n/**\n * Type guards for relay-to-dApp messages\n */\nexport function isWalletHandshakeMessage(message: RelayToDAppMessage): message is WalletHandshakeMessage {\n return message?.type === 'wallet_handshake';\n}\n\nexport function isConnectionRejectedMessage(message: RelayToDAppMessage): message is ConnectionRejectedMessage {\n return message?.type === 'connection_rejected';\n}\n\nexport function isConnectionAuthenticatedMessage(message: RelayToDAppMessage): message is ConnectionAuthenticatedMessage {\n return message?.type === 'connection_authenticated';\n}\n","/**\n * Client message types for BananaLink protocol v2.0\n * These types define the communication between dApp clients and the relay server\n */\n\nimport type {\n SignMessageRequestPayload,\n SignTypedDataRequestPayload,\n SignTransactionRequestPayload,\n} from './post-auth-operations';\n\n/**\n * Client session claim credential for authentication and reconnection\n * Stored by client, validated by relay server\n */\nexport interface ClientSessionClaim {\n /**\n * Unique nonce for this client session\n * - Generated once by client during session creation\n * - Stored locally by client for reconnection\n * - Used by relay to validate client ownership\n * - Different for each session\n */\n claimNonce: string;\n\n /** Claim generation timestamp */\n timestamp: number;\n}\n\n/**\n * Client reconnect payload\n * Used to reconnect after network interruption\n */\nexport interface ClientReconnectPayload {\n type: 'client_reconnect';\n}\n\n/**\n * Close session payload\n * Used to gracefully close a session (bidirectional)\n */\nexport interface CloseSessionPayload {\n type: 'close_session';\n /** Optional reason for closing the session */\n reason?: string;\n}\n\n/**\n * Union type for all client message payloads\n */\nexport type ClientMessagePayload =\n // Session management payloads\n | ClientReconnectPayload\n | CloseSessionPayload\n // Post-authentication operation request payloads (v2.1+)\n | SignMessageRequestPayload\n | SignTypedDataRequestPayload\n | SignTransactionRequestPayload;\n\n/**\n * Client message envelope structure\n * All client-to-relay messages use this envelope\n */\nexport interface ClientMessageEnvelope {\n /** Session identifier */\n sessionId: string;\n\n /** Client session claim - validated by relay server */\n clientSessionClaim: ClientSessionClaim;\n\n /** Actual message payload */\n payload: ClientMessagePayload;\n}\n\n/**\n * Type guards for client messages\n */\nexport function isClientReconnectPayload(payload: ClientMessagePayload): payload is ClientReconnectPayload {\n return payload?.type === 'client_reconnect';\n}\n\nexport function isCloseSessionPayload(payload: ClientMessagePayload): payload is CloseSessionPayload {\n return payload?.type === 'close_session';\n}\n","/**\n * Relay notification message types for BananaLink protocol v2.0\n * These are messages sent from relay server to clients/wallets\n */\n\n/**\n * Session closed acknowledgment\n * Sent to acknowledge a close_session request\n */\nexport interface SessionClosedAck {\n type: 'session_closed_ack';\n timestamp: number;\n}\n\n/**\n * Session closed notification\n * Sent to notify the other party that peer closed the session\n */\nexport interface SessionClosedNotification {\n type: 'session_closed_notification';\n /** Which party closed the session */\n closedBy: 'client' | 'wallet';\n /** Optional reason for closure */\n reason?: string;\n timestamp: number;\n}\n\n/**\n * Reconnected confirmation message\n * Sent after successful reconnection\n */\nexport interface ReconnectedMessage {\n type: 'reconnected';\n /** Number of messages that were queued during disconnection */\n queuedMessages: number;\n timestamp: number;\n}\n\n/**\n * Union type for relay notification messages\n */\nexport type RelayNotificationMessage =\n | SessionClosedAck\n | SessionClosedNotification\n | ReconnectedMessage;\n\n/**\n * Type guards for relay notification messages\n */\nexport function isSessionClosedAck(message: RelayNotificationMessage): message is SessionClosedAck {\n return message?.type === 'session_closed_ack';\n}\n\nexport function isSessionClosedNotification(message: RelayNotificationMessage): message is SessionClosedNotification {\n return message?.type === 'session_closed_notification';\n}\n\nexport function isReconnectedMessage(message: RelayNotificationMessage): message is ReconnectedMessage {\n return message?.type === 'reconnected';\n}\n","/**\n * Public key compression utilities for compact URL encoding\n *\n * These utilities convert public keys between standard base64 format\n * and compact base64url format for use in QR codes and URLs.\n */\n\n/**\n * Compress a public key for compact URLs\n * Removes AES-GCM: prefix and uses base64url without padding\n *\n * @param publicKey - Public key in format \"AES-GCM:base64string\" or \"base64string\"\n * @returns Compressed public key in base64url format without padding\n */\nexport function compressPublicKey(publicKey: string): string {\n // Remove AES-GCM: prefix if present\n const keyWithoutPrefix = publicKey.startsWith('AES-GCM:')\n ? publicKey.slice(8)\n : publicKey;\n\n // Convert base64 to base64url (replace + with -, / with _, remove padding)\n return keyWithoutPrefix\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Decompress a public key from compact format\n * Adds back AES-GCM: prefix and restores base64 padding\n *\n * @param compressedKey - Compressed public key in base64url format\n * @returns Public key in format \"AES-GCM:base64string\"\n */\nexport function decompressPublicKey(compressedKey: string): string {\n // Convert base64url back to base64\n let base64Key = compressedKey\n .replace(/-/g, '+')\n .replace(/_/g, '/');\n\n // Add padding if needed\n const padding = base64Key.length % 4;\n if (padding > 0) {\n base64Key += '='.repeat(4 - padding);\n }\n\n // Add AES-GCM prefix if not already present\n return base64Key.startsWith('AES-GCM:') ? base64Key : `AES-GCM:${base64Key}`;\n}\n","import type { QRPayload } from '../types/discovery';\nimport { DEEPLINK_SCHEME } from '../constants';\nimport { compressPublicKey } from './public-keys';\n\n/**\n * Provider shortcodes for compact URLs\n */\nconst PROVIDER_SHORTCODES: Record<string, string> = {\n 'uwebsockets': 'u', // Legacy - API may still return this\n 'websocket': 'w',\n 'pusher': 'p',\n 'ably': 'a',\n};\n\n/**\n * Production relay URLs that should be omitted in compact format (most common case)\n */\nconst PRODUCTION_RELAY_URLS = [\n 'wss://relay.banana.link/v1',\n 'https://relay.banana.link/v1',\n];\n\n/**\n * Environment shortcodes for non-production relay URLs\n */\nconst RELAY_SHORTCODES: Record<string, string> = {\n 'wss://relay.dev.banana.link/v1': 'd',\n 'https://relay.dev.banana.link/v1': 'd',\n 'wss://relay.staging.banana.link/v1': 's', // Future staging environment\n 'https://relay.staging.banana.link/v1': 's',\n};\n\n/**\n * Safely encode a URL parameter value\n * Uses encodeURIComponent to handle special characters like +, /, =\n */\nexport function encodeUrlParameter(value: string): string {\n return encodeURIComponent(value);\n}\n\n/**\n * Build a query string with properly encoded parameters\n */\nexport function buildQueryString(params: Record<string, string | undefined>): string {\n const pairs: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n pairs.push(`${encodeUrlParameter(key)}=${encodeUrlParameter(value)}`);\n }\n }\n\n return pairs.join('&');\n}\n\n/**\n * Create a compact deep link URL with shortened parameters\n * Uses single-letter parameters to minimize QR code size\n */\nexport function encodeCompactConnectionString(payload: QRPayload): string {\n const params: Record<string, string | undefined> = {\n s: payload.sessionId, // sessionId -> s\n k: compressPublicKey(payload.publicKey), // publicKey -> k (compressed)\n };\n\n // Add optional parameters with shortcodes\n if (payload.providerId) {\n params.p = PROVIDER_SHORTCODES[payload.providerId] || payload.providerId;\n }\n\n // Handle relay URL compression:\n // - Production: omit entirely (most common case)\n // - Development/Staging: use shortcode (r=d, r=s)\n // - Custom: use full URL\n if (payload.relayUrl) {\n if (PRODUCTION_RELAY_URLS.includes(payload.relayUrl)) {\n // Production relay - omit parameter entirely for maximum compression\n // This will be the most common case, so QR codes will be smallest\n } else if (RELAY_SHORTCODES[payload.relayUrl]) {\n // Known environment (dev/staging) - use shortcode\n params.r = RELAY_SHORTCODES[payload.relayUrl];\n } else {\n // Custom relay URL - include full URL\n params.r = payload.relayUrl;\n }\n }\n\n const queryString = buildQueryString(params);\n return `${DEEPLINK_SCHEME}://connect?${queryString}`;\n}\n\n/**\n * Create a deep link URL with properly encoded parameters\n * Uses full parameter names for readability\n */\nexport function encodeConnectionString(payload: QRPayload): string {\n const params: Record<string, string | undefined> = {\n sessionId: payload.sessionId,\n publicKey: payload.publicKey,\n };\n\n // Add optional parameters\n if (payload.providerId) {\n params.providerId = payload.providerId;\n }\n\n if (payload.relayUrl) {\n params.relay = payload.relayUrl;\n }\n\n const queryString = buildQueryString(params);\n return `${DEEPLINK_SCHEME}://connect?${queryString}`;\n}\n\n/**\n * Create a universal link (HTTPS) with properly encoded parameters\n */\nexport function encodeUniversalLink(payload: QRPayload, options: {\n baseUrl?: string;\n fallbackUrl?: string;\n} = {}): string {\n const {\n baseUrl = 'https://banana.link',\n fallbackUrl = 'https://banana.link/download',\n } = options;\n\n const params: Record<string, string | undefined> = {\n sessionId: payload.sessionId,\n key: payload.publicKey, // Use 'key' instead of 'publicKey' for universal links\n fallback: fallbackUrl,\n };\n\n // Add optional parameters\n if (payload.providerId) {\n params.provider = payload.providerId;\n }\n\n if (payload.relayUrl) {\n params.relay = payload.relayUrl;\n }\n\n const queryString = buildQueryString(params);\n return `${baseUrl}/connect?${queryString}`;\n}\n","import type { QRPayload } from '../types/discovery';\nimport { decompressPublicKey } from './public-keys';\n\n/**\n * Provider shortcodes reverse mapping for compact URL decoding\n */\nconst PROVIDER_SHORTCODES_REVERSE: Record<string, string> = {\n 'u': 'websocket', // Decode legacy 'u' to new 'websocket' name\n 'w': 'websocket',\n 'p': 'pusher',\n 'a': 'ably',\n};\n\n/**\n * Environment shortcodes reverse mapping for relay URL decoding\n */\nconst RELAY_SHORTCODES_REVERSE: Record<string, string> = {\n 'd': 'wss://relay.dev.banana.link/v1',\n 's': 'wss://relay.staging.banana.link/v1',\n};\n\n/**\n * Safely decode a URL parameter value\n * Uses decodeURIComponent to restore special characters\n */\nexport function decodeUrlParameter(value: string): string {\n return decodeURIComponent(value);\n}\n\n/**\n * Parse a query string with properly decoded parameters\n */\nexport function parseQueryString(query: string): Record<string, string> {\n const params: Record<string, string> = {};\n\n // Remove leading ? if present\n const cleanQuery = query.startsWith('?') ? query.slice(1) : query;\n\n if (!cleanQuery) {\n return params;\n }\n\n for (const pair of cleanQuery.split('&')) {\n const [key, ...valueParts] = pair.split('=');\n if (key) {\n const value = valueParts.join('='); // Handle values that contain =\n params[decodeUrlParameter(key)] = decodeUrlParameter(value);\n }\n }\n\n return params;\n}\n\n/**\n * Parse a connection string and extract the QRPayload with proper decoding\n * Supports both full format and compact format\n */\nexport function decodeConnectionString(connectionString: string): QRPayload {\n let url: URL;\n\n try {\n url = new URL(connectionString);\n } catch {\n throw new Error(`Invalid connection string format: ${connectionString}`);\n }\n\n // Parse query parameters using our safe decoder\n const params = parseQueryString(url.search);\n\n // Support both compact and full parameter formats\n const sessionId = params.sessionId || params.s; // full or compact\n let publicKey = params.publicKey || params.key || params.k; // full, universal, or compact\n let providerId = params.providerId || params.provider || params.p; // full, alt, or compact\n let relayUrl = params.relay || params.r; // full or compact\n\n if (!sessionId || !publicKey) {\n throw new Error('Missing required parameters: sessionId and publicKey');\n }\n\n // If we have a compact format public key (params.k), decompress it\n if (params.k && !params.publicKey && !params.key) {\n publicKey = decompressPublicKey(params.k);\n }\n\n // If we have a compact format provider, expand it\n if (params.p && !params.providerId && !params.provider) {\n providerId = PROVIDER_SHORTCODES_REVERSE[params.p] || params.p;\n }\n\n // Handle relay URL decompression:\n // - No relay parameter = production (default)\n // - Shortcode (d, s) = expand to full environment URL\n // - Full URL = use as-is\n if (!relayUrl) {\n // No relay parameter means production (most common case)\n relayUrl = 'wss://relay.banana.link/v1';\n } else if (RELAY_SHORTCODES_REVERSE[relayUrl]) {\n // Environment shortcode - expand to full URL\n relayUrl = RELAY_SHORTCODES_REVERSE[relayUrl];\n }\n // else: already a full URL, use as-is\n\n // Ensure public key has AES-GCM prefix for backward compatibility\n if (publicKey && !publicKey.startsWith('AES-GCM:')) {\n publicKey = `AES-GCM:${publicKey}`;\n }\n\n return {\n sessionId,\n publicKey,\n providerId: providerId || undefined,\n relayUrl: relayUrl || undefined,\n };\n}\n\n/**\n * Validate that a string is a valid connection string\n */\nexport function isValidConnectionString(connectionString: string): boolean {\n try {\n decodeConnectionString(connectionString);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Session claiming mechanism utilities for BananaLink protocol v2.0\n * Implements secure session ownership and reconnection logic\n */\n\nimport type { WalletSessionClaim, WalletMessageEnvelope } from '../types/wallet-messages';\n\n/**\n * Wallet session claim storage interface\n * Implementations should provide secure storage for wallet session claims\n */\nexport interface WalletSessionClaimStorage {\n store(sessionId: string, claim: WalletSessionClaim): Promise<void>;\n retrieve(sessionId: string): Promise<WalletSessionClaim | null>;\n remove(sessionId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\n/**\n * Wallet session claim manager for handling claim generation and validation\n */\nexport class WalletSessionClaimManager {\n constructor(private storage: WalletSessionClaimStorage) {}\n\n /**\n * Generate a new wallet session claim with provided nonce\n * @param sessionId - Session identifier\n * @param sessionNonce - Pre-generated cryptographically secure nonce (use @bananalink-sdk/crypto)\n * @returns Generated wallet session claim\n */\n async generateClaim(sessionId: string, sessionNonce: string): Promise<WalletSessionClaim> {\n const claim: WalletSessionClaim = {\n sessionNonce,\n timestamp: Date.now(),\n };\n\n // Store the claim for future reconnection\n await this.storage.store(sessionId, claim);\n\n return claim;\n }\n\n /**\n * Retrieve an existing wallet session claim\n * @param sessionId - Session identifier\n * @returns Stored wallet session claim or null if not found\n */\n async getClaim(sessionId: string): Promise<WalletSessionClaim | null> {\n return this.storage.retrieve(sessionId);\n }\n\n /**\n * Validate a wallet session claim for reconnection\n * @param claim - Claim to validate\n * @param storedClaim - Previously stored claim\n * @returns Validation result\n */\n validateReconnectionClaim(\n claim: WalletSessionClaim,\n storedClaim: WalletSessionClaim\n ): { valid: boolean; reason?: string } {\n // Check nonce match\n if (claim.sessionNonce !== storedClaim.sessionNonce) {\n return {\n valid: false,\n reason: 'Session nonce mismatch - invalid reconnection attempt',\n };\n }\n\n // Check timestamp validity (prevent very old reconnection attempts)\n const MAX_RECONNECTION_AGE = 24 * 60 * 60 * 1000; // 24 hours\n const claimAge = Date.now() - claim.timestamp;\n if (claimAge > MAX_RECONNECTION_AGE) {\n return {\n valid: false,\n reason: 'Session claim too old - please create a new session',\n };\n }\n\n return { valid: true };\n }\n\n /**\n * Remove a wallet session claim (on session end)\n * @param sessionId - Session identifier\n */\n async removeClaim(sessionId: string): Promise<void> {\n await this.storage.remove(sessionId);\n }\n\n /**\n * Clear all stored claims\n */\n async clearAllClaims(): Promise<void> {\n await this.storage.clear();\n }\n}\n\n// NOTE: Nonce generation moved to @bananalink-sdk/crypto package to avoid circular dependencies\n// SDKs should use crypto.generateSessionNonce() before creating session claims\n\n/**\n * Create a wallet message envelope with wallet session claim\n * @param sessionId - Session identifier\n * @param claim - Wallet session claim\n * @param payload - Message payload\n * @returns Complete wallet message envelope\n */\nexport function createWalletMessageEnvelope(\n sessionId: string,\n claim: WalletSessionClaim,\n payload: WalletMessageEnvelope['payload']\n): WalletMessageEnvelope {\n return {\n sessionId,\n walletSessionClaim: claim,\n payload,\n };\n}\n\n/**\n * Strip wallet session claim from wallet message for forwarding to dApp\n * @param envelope - Original wallet message envelope\n * @returns Message without wallet session claim\n */\nexport function stripWalletSessionClaim(\n envelope: WalletMessageEnvelope\n): Omit<WalletMessageEnvelope, 'walletSessionClaim'> {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { walletSessionClaim, ...messageWithoutClaim } = envelope;\n return messageWithoutClaim;\n}\n\n/**\n * Validate session claim timestamp for replay attack prevention\n * @param timestamp - Claim timestamp\n * @param maxAge - Maximum age in milliseconds (default: 30 seconds)\n * @returns True if timestamp is within valid range\n */\nexport function validateClaimTimestamp(\n timestamp: number,\n maxAge: number = 30 * 1000\n): boolean {\n const now = Date.now();\n const age = Math.abs(now - timestamp);\n return age <= maxAge;\n}\n\n/**\n * Validate wallet message envelope\n * @param envelope - Message envelope to validate\n * @returns Validation result\n */\nexport function validateWalletMessageEnvelope(\n envelope: WalletMessageEnvelope\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required fields\n if (!envelope.sessionId) {\n errors.push('Missing session ID');\n }\n\n if (!envelope.walletSessionClaim) {\n errors.push('Missing wallet session claim');\n } else {\n // Validate claim structure\n if (!envelope.walletSessionClaim.sessionNonce) {\n errors.push('Missing session nonce in wallet session claim');\n }\n if (!envelope.walletSessionClaim.timestamp) {\n errors.push('Missing timestamp in wallet session claim');\n } else if (!validateClaimTimestamp(envelope.walletSessionClaim.timestamp)) {\n errors.push('Wallet session claim timestamp is too old or invalid');\n }\n }\n\n if (!envelope.payload) {\n errors.push('Missing message payload');\n } else if (!envelope.payload.type) {\n errors.push('Missing payload type');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Client session claim utilities for BananaLink protocol v2.0\n * Implements secure client session ownership and reconnection logic\n */\n\nimport type { ClientSessionClaim, ClientMessageEnvelope } from '../types/client-messages';\n\n/**\n * Client session claim storage interface\n * Implementations should provide secure storage for client session claims\n */\nexport interface ClientSessionClaimStorage {\n store(sessionId: string, claim: ClientSessionClaim): Promise<void>;\n retrieve(sessionId: string): Promise<ClientSessionClaim | null>;\n remove(sessionId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\n/**\n * Client session claim manager for handling claim generation and validation\n */\nexport class ClientSessionClaimManager {\n constructor(private storage: ClientSessionClaimStorage) {}\n\n /**\n * Generate a new client session claim with provided nonce\n * @param sessionId - Session identifier\n * @param claimNonce - Pre-generated cryptographically secure nonce (use @bananalink-sdk/crypto)\n * @returns Generated client session claim\n */\n async generateClaim(sessionId: string, claimNonce: string): Promise<ClientSessionClaim> {\n const claim: ClientSessionClaim = {\n claimNonce,\n timestamp: Date.now(),\n };\n\n // Store the claim for future reconnection\n await this.storage.store(sessionId, claim);\n\n return claim;\n }\n\n /**\n * Retrieve an existing client session claim\n * @param sessionId - Session identifier\n * @returns Stored client session claim or null if not found\n */\n async getClaim(sessionId: string): Promise<ClientSessionClaim | null> {\n return this.storage.retrieve(sessionId);\n }\n\n /**\n * Validate a client session claim for reconnection\n * @param claim - Claim to validate\n * @param storedClaim - Previously stored claim\n * @returns Validation result\n */\n validateReconnectionClaim(\n claim: ClientSessionClaim,\n storedClaim: ClientSessionClaim\n ): { valid: boolean; reason?: string } {\n // Check nonce match\n if (claim.claimNonce !== storedClaim.claimNonce) {\n return {\n valid: false,\n reason: 'Client claim nonce mismatch - invalid reconnection attempt',\n };\n }\n\n // Check timestamp validity (prevent very old reconnection attempts)\n const MAX_RECONNECTION_AGE = 24 * 60 * 60 * 1000; // 24 hours\n const claimAge = Date.now() - claim.timestamp;\n if (claimAge > MAX_RECONNECTION_AGE) {\n return {\n valid: false,\n reason: 'Client session claim too old - please create a new session',\n };\n }\n\n return { valid: true };\n }\n\n /**\n * Remove a client session claim (on session end)\n * @param sessionId - Session identifier\n */\n async removeClaim(sessionId: string): Promise<void> {\n await this.storage.remove(sessionId);\n }\n\n /**\n * Clear all stored claims\n */\n async clearAllClaims(): Promise<void> {\n await this.storage.clear();\n }\n}\n\n// NOTE: Nonce generation moved to @bananalink-sdk/crypto package to avoid circular dependencies\n// SDKs should use crypto.generateClientClaimNonce() before creating client session claims\n\n/**\n * Create a client message envelope with session claim\n * @param sessionId - Session identifier\n * @param claim - Client session claim\n * @param payload - Message payload\n * @returns Complete client message envelope\n */\nexport function createClientMessageEnvelope(\n sessionId: string,\n claim: ClientSessionClaim,\n payload: ClientMessageEnvelope['payload']\n): ClientMessageEnvelope {\n return {\n sessionId,\n clientSessionClaim: claim,\n payload,\n };\n}\n\n/**\n * Strip client session claim from client message for forwarding\n * @param envelope - Original client message envelope\n * @returns Message without client session claim\n */\nexport function stripClientSessionClaim(\n envelope: ClientMessageEnvelope\n): Omit<ClientMessageEnvelope, 'clientSessionClaim'> {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { clientSessionClaim, ...messageWithoutClaim } = envelope;\n return messageWithoutClaim;\n}\n\n/**\n * Validate client session claim timestamp for replay attack prevention\n * @param timestamp - Claim timestamp\n * @param maxAge - Maximum age in milliseconds (default: 30 seconds)\n * @returns True if timestamp is within valid range\n */\nexport function validateClientClaimTimestamp(\n timestamp: number,\n maxAge: number = 30 * 1000\n): boolean {\n const now = Date.now();\n const age = Math.abs(now - timestamp);\n return age <= maxAge;\n}\n\n/**\n * Validate client message envelope\n * @param envelope - Message envelope to validate\n * @returns Validation result\n */\nexport function validateClientMessageEnvelope(\n envelope: ClientMessageEnvelope\n): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n // Check required fields\n if (!envelope.sessionId) {\n errors.push('Missing session ID');\n }\n\n if (!envelope.clientSessionClaim) {\n errors.push('Missing client session claim');\n } else {\n // Validate claim structure\n if (!envelope.clientSessionClaim.claimNonce) {\n errors.push('Missing claim nonce in client session claim');\n }\n if (!envelope.clientSessionClaim.timestamp) {\n errors.push('Missing timestamp in client session claim');\n } else if (!validateClientClaimTimestamp(envelope.clientSessionClaim.timestamp)) {\n errors.push('Client session claim timestamp is too old or invalid');\n }\n }\n\n if (!envelope.payload) {\n errors.push('Missing message payload');\n } else if (!envelope.payload.type) {\n errors.push('Missing payload type');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Protocol utility functions\n *\n * This module provides utility functions that are specific to the BananaLink protocol.\n * SDK-specific utilities are implemented in their respective packages.\n */\n\nimport { generateUUID } from '../crypto/utils';\n\n/**\n * Generate a cryptographically secure session ID in RFC 4122 UUID v4 format\n *\n * This function delegates to the protocol crypto layer for mobile-safe UUID generation.\n * For direct access to UUID generation, prefer importing from @bananalink-sdk/protocol/crypto.\n *\n * @returns UUID v4 string (e.g., \"550e8400-e29b-41d4-a716-446655440000\")\n *\n * @example\n * const sessionId = generateSessionId();\n * // => \"a3bb189e-8bf9-4bdc-9f16-9f48a6a1e3e7\"\n */\nexport function generateSessionId(): string {\n return generateUUID();\n}\n\n// Protocol-specific utility that might be needed across packages\nexport function isValidProtocolVersion(version: string): boolean {\n // Only support version \"1\" for now\n return version === '1';\n}\n\n// Protocol-specific session ID validation\nexport function isValidSessionId(sessionId: string): boolean {\n // Session IDs should be valid UUIDs\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n return uuidRegex.test(sessionId);\n}\n\n// Export public key compression utilities\nexport * from './public-keys';\n\n// Export URL encoding and decoding utilities\nexport * from './url-encoding';\nexport * from './url-decoding';\n\n// Note: SIWE utilities have been moved to '@bananalink-sdk/protocol/siwe'\n// For ERC-4361 message construction and validation, import from '@bananalink-sdk/protocol/siwe'\n// Type-only definitions (SIWEFields, SIWEMessageOptions) remain available from main export\n\n// Export wallet session claiming utilities\nexport * from './wallet-session-claim';\n\n// Export client session claiming utilities\nexport * from './client-session-claim';\n","{\n \"name\": \"@bananalink-sdk/protocol\",\n \"version\": \"1.2.8\",\n \"description\": \"Core protocol definitions for BananaLink. Provides TypeScript types, Zod validation schemas, cryptographic utilities, and shared constants for wallet connections.\",\n \"type\": \"module\",\n \"keywords\": [\n \"bananalink\",\n \"protocol\",\n \"types\",\n \"schemas\",\n \"validation\",\n \"cryptography\",\n \"web3\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/bananalink/bananalink/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/bananalink/bananalink.git\",\n \"directory\": \"packages/protocol\"\n },\n \"license\": \"ISC\",\n \"author\": \"BananaLink Team <team@banana.link>\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"react-native\": \"./dist/index.js\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./schemas\": {\n \"types\": \"./dist/schemas-export.d.ts\",\n \"react-native\": \"./dist/schemas-export.js\",\n \"import\": \"./dist/schemas-export.js\",\n \"require\": \"./dist/schemas-export.cjs\"\n },\n \"./validators\": {\n \"types\": \"./dist/validators-export.d.ts\",\n \"react-native\": \"./dist/validators-export.js\",\n \"import\": \"./dist/validators-export.js\",\n \"require\": \"./dist/validators-export.cjs\"\n },\n \"./validation\": {\n \"types\": \"./dist/validation-export.d.ts\",\n \"react-native\": \"./dist/validation-export.js\",\n \"import\": \"./dist/validation-export.js\",\n \"require\": \"./dist/validation-export.cjs\"\n },\n \"./siwe\": {\n \"types\": \"./dist/siwe-export.d.ts\",\n \"react-native\": \"./dist/siwe-export.js\",\n \"import\": \"./dist/siwe-export.js\",\n \"require\": \"./dist/siwe-export.cjs\"\n },\n \"./crypto\": {\n \"types\": \"./dist/crypto-export.d.ts\",\n \"react-native\": \"./dist/crypto-export.js\",\n \"import\": \"./dist/crypto-export.js\",\n \"require\": \"./dist/crypto-export.cjs\"\n },\n \"./crypto/provider/webcrypto\": {\n \"types\": \"./dist/crypto/providers/webcrypto-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/webcrypto-provider.js\",\n \"import\": \"./dist/crypto/providers/webcrypto-provider.js\",\n \"require\": \"./dist/crypto/providers/webcrypto-provider.cjs\"\n },\n \"./crypto/provider/node\": {\n \"types\": \"./dist/crypto/providers/node-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/node-provider.js\",\n \"import\": \"./dist/crypto/providers/node-provider.js\",\n \"require\": \"./dist/crypto/providers/node-provider.cjs\"\n },\n \"./crypto/provider/noble\": {\n \"types\": \"./dist/crypto/providers/noble-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/noble-provider.js\",\n \"import\": \"./dist/crypto/providers/noble-provider.js\",\n \"require\": \"./dist/crypto/providers/noble-provider.cjs\"\n },\n \"./crypto/provider/quickcrypto\": {\n \"types\": \"./dist/crypto/providers/quickcrypto-provider.d.ts\",\n \"react-native\": \"./dist/crypto/providers/quickcrypto-provider.js\",\n \"import\": \"./dist/crypto/providers/quickcrypto-provider.js\",\n \"require\": \"./dist/crypto/providers/quickcrypto-provider.cjs\"\n },\n \"./testing\": {\n \"types\": \"./dist/testing.d.ts\",\n \"react-native\": \"./dist/testing.js\",\n \"import\": \"./dist/testing.js\",\n \"require\": \"./dist/testing.cjs\"\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\n \"dist\",\n \"src\",\n \"!src/__tests__\"\n ],\n \"publishConfig\": {\n \"access\": \"restricted\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"clean\": \"rm -rf dist node_modules\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint src --ext .ts\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"dependencies\": {\n \"@bananalink-sdk/logger\": \"workspace:*\",\n \"@noble/ciphers\": \"^2.0.0\",\n \"@noble/curves\": \"^2.0.0\",\n \"@noble/hashes\": \"^2.0.0\",\n \"zod\": \"^3.25.67\"\n },\n \"devDependencies\": {\n \"@bananalink-sdk/eslint-config\": \"workspace:*\",\n \"@bananalink-sdk/typescript-config\": \"workspace:*\",\n \"@types/node\": \"^24.1.0\",\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"eslint\": \"^9.29.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.8.3\",\n \"vitest\": \"^3.2.4\"\n },\n \"peerDependencies\": {\n \"react-native-quick-crypto\": \"^0.7.0\"\n },\n \"peerDependenciesMeta\": {\n \"react-native-quick-crypto\": {\n \"optional\": true\n }\n },\n \"packageManager\": \"pnpm@10.15.1\"\n}\n","/**\n * BananaLink Protocol Package\n *\n * Core TypeScript implementation of the BananaLink protocol for dApp-to-wallet communication.\n * Provides types, schemas, constants, and utilities for implementing BananaLink clients and wallets.\n *\n * @packageDocumentation\n */\n\n// Core protocol types\nexport * from './types/core';\nexport * from './types/auth';\nexport * from './types/crypto';\nexport * from './types/discovery';\nexport * from './types/errors';\nexport * from './types/providers';\nexport * from './types/wallet-messages';\nexport * from './types/client-messages';\nexport * from './types/relay-messages';\n\n// Note: Zod validation schemas have been moved to '@bananalink-sdk/protocol/schemas'\n// For runtime validation, import from '@bananalink-sdk/protocol/schemas'\n// Type-only definitions remain available from this main export\n\n// Note: SIWE utilities have been moved to '@bananalink-sdk/protocol/siwe'\n// For ERC-4361 message construction/parsing, import from '@bananalink-sdk/protocol/siwe'\n// Export SIWE types for convenience (type-only, no runtime code)\nexport type { SIWEMessageOptions } from './utils/siwe';\n\n// Constants and utilities\nexport * from './constants';\nexport * from './utils';\n\n// Package metadata\n// Note: Version is imported from package.json to ensure consistency\nimport packageJson from '../package.json';\nexport const VERSION = packageJson.version;\nexport const PACKAGE_NAME = \"@bananalink-sdk/protocol\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananalink-sdk/protocol",
3
- "version": "1.2.8",
3
+ "version": "1.3.0",
4
4
  "description": "Core protocol definitions for BananaLink. Provides TypeScript types, Zod validation schemas, cryptographic utilities, and shared constants for wallet connections.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -6,7 +6,6 @@ import { hmac } from '@noble/hashes/hmac.js';
6
6
  import { sha256 } from '@noble/hashes/sha2.js';
7
7
  import type { Logger } from '@bananalink-sdk/logger';
8
8
  import type { CryptoProvider, CryptoKeyLike, ProviderKeyPair } from '../../types/crypto-provider';
9
- import { registerCryptoProvider } from './registry';
10
9
 
11
10
  /**
12
11
  * Noble library implementation of CryptoKeyLike
@@ -17,7 +16,7 @@ class NobleKey implements CryptoKeyLike {
17
16
  public readonly type: 'public' | 'private' | 'secret',
18
17
  public readonly algorithm: string,
19
18
  public readonly extractable: boolean = true,
20
- public readonly usages: readonly string[] = []
19
+ public readonly usages: readonly string[] = [],
21
20
  ) {}
22
21
  }
23
22
 
@@ -46,7 +45,7 @@ export class NobleCryptoProvider implements CryptoProvider {
46
45
  const publicKeyUncompressed = p256.getPublicKey(privateKeyBytes, false); // false = uncompressed
47
46
 
48
47
  this.logger?.debug('Key pair generation completed', {
49
- publicKeyLength: publicKeyUncompressed.length
48
+ publicKeyLength: publicKeyUncompressed.length,
50
49
  });
51
50
 
52
51
  return Promise.resolve({
@@ -57,8 +56,8 @@ export class NobleCryptoProvider implements CryptoProvider {
57
56
  this.logger?.error('Key pair generation failed', {
58
57
  error: {
59
58
  message: error instanceof Error ? error.message : String(error),
60
- stack: error instanceof Error ? error.stack : undefined
61
- }
59
+ stack: error instanceof Error ? error.stack : undefined,
60
+ },
62
61
  });
63
62
  throw error;
64
63
  }
@@ -72,7 +71,9 @@ export class NobleCryptoProvider implements CryptoProvider {
72
71
  if (nobleKey.type !== 'public') {
73
72
  throw new Error('Expected public key');
74
73
  }
75
- return Promise.resolve(nobleKey.data.buffer.slice(nobleKey.data.byteOffset, nobleKey.data.byteOffset + nobleKey.data.byteLength));
74
+ return Promise.resolve(
75
+ nobleKey.data.buffer.slice(nobleKey.data.byteOffset, nobleKey.data.byteOffset + nobleKey.data.byteLength),
76
+ );
76
77
  }
77
78
 
78
79
  /**
@@ -83,7 +84,9 @@ export class NobleCryptoProvider implements CryptoProvider {
83
84
  if (nobleKey.type !== 'private') {
84
85
  throw new Error('Expected private key');
85
86
  }
86
- return Promise.resolve(nobleKey.data.buffer.slice(nobleKey.data.byteOffset, nobleKey.data.byteOffset + nobleKey.data.byteLength));
87
+ return Promise.resolve(
88
+ nobleKey.data.buffer.slice(nobleKey.data.byteOffset, nobleKey.data.byteOffset + nobleKey.data.byteLength),
89
+ );
87
90
  }
88
91
 
89
92
  /**
@@ -95,8 +98,12 @@ export class NobleCryptoProvider implements CryptoProvider {
95
98
  // Debug logging
96
99
  this.logger?.debug('importPublicKey called', {
97
100
  keyLength: keyBytes.length,
98
- keyBytesFirst20: Array.from(keyBytes.slice(0, 20)).map(b => b.toString(16).padStart(2, '0')).join(' '),
99
- keyBytesHex: Array.from(keyBytes).map(b => b.toString(16).padStart(2, '0')).join('')
101
+ keyBytesFirst20: Array.from(keyBytes.slice(0, 20))
102
+ .map((b) => b.toString(16).padStart(2, '0'))
103
+ .join(' '),
104
+ keyBytesHex: Array.from(keyBytes)
105
+ .map((b) => b.toString(16).padStart(2, '0'))
106
+ .join(''),
100
107
  });
101
108
 
102
109
  // Validate public key using Noble's validation
@@ -107,7 +114,7 @@ export class NobleCryptoProvider implements CryptoProvider {
107
114
  if (keyBytes.length === 65) {
108
115
  // Already in uncompressed format (0x04 + 32 + 32)
109
116
  this.logger?.debug('Processing 65-byte key', {
110
- firstByte: `0x${keyBytes[0].toString(16)}`
117
+ firstByte: `0x${keyBytes[0].toString(16)}`,
111
118
  });
112
119
  if (keyBytes[0] !== 0x04) {
113
120
  throw new Error(`Expected uncompressed key (0x04 prefix), got 0x${keyBytes[0].toString(16)}`);
@@ -117,7 +124,7 @@ export class NobleCryptoProvider implements CryptoProvider {
117
124
  // Raw format (32 + 32) - needs 0x04 prefix for Noble
118
125
  // This is the WebCrypto export format
119
126
  this.logger?.debug('Processing 64-byte key', {
120
- action: 'adding 0x04 prefix'
127
+ action: 'adding 0x04 prefix',
121
128
  });
122
129
  processedKeyBytes = new Uint8Array(65);
123
130
  processedKeyBytes[0] = 0x04; // Uncompressed point indicator
@@ -128,25 +135,27 @@ export class NobleCryptoProvider implements CryptoProvider {
128
135
 
129
136
  this.logger?.debug('Key processing completed', {
130
137
  processedLength: processedKeyBytes.length,
131
- processedFirst20: Array.from(processedKeyBytes.slice(0, 20)).map(b => b.toString(16).padStart(2, '0')).join(' ')
138
+ processedFirst20: Array.from(processedKeyBytes.slice(0, 20))
139
+ .map((b) => b.toString(16).padStart(2, '0'))
140
+ .join(' '),
132
141
  });
133
142
 
134
143
  // Validate using Noble's validation
135
144
  const isValid = p256.utils.isValidPublicKey(processedKeyBytes, false); // false = allow uncompressed
136
145
  this.logger?.debug('Noble key validation completed', {
137
- isValid
146
+ isValid,
138
147
  });
139
148
 
140
149
  if (!isValid) {
141
150
  // Try additional debugging
142
151
  this.logger?.debug('Key validation failed, trying alternative approaches', {
143
- originalValidation: false
152
+ originalValidation: false,
144
153
  });
145
154
 
146
155
  // Try with compressed format check
147
156
  const isValidCompressed = p256.utils.isValidPublicKey(processedKeyBytes, true);
148
157
  this.logger?.debug('Alternative validation attempted', {
149
- compressedFormatValid: isValidCompressed
158
+ compressedFormatValid: isValidCompressed,
150
159
  });
151
160
 
152
161
  throw new Error('Key failed Noble validation');
@@ -157,8 +166,8 @@ export class NobleCryptoProvider implements CryptoProvider {
157
166
  this.logger?.error('Public key import failed', {
158
167
  error: {
159
168
  message: error instanceof Error ? error.message : String(error),
160
- stack: error instanceof Error ? error.stack : undefined
161
- }
169
+ stack: error instanceof Error ? error.stack : undefined,
170
+ },
162
171
  });
163
172
  throw new Error(`Invalid P-256 public key: ${String(error)}`);
164
173
  }
@@ -194,14 +203,14 @@ export class NobleCryptoProvider implements CryptoProvider {
194
203
  if (privKey.type !== 'private') {
195
204
  const error = new Error('Expected private key');
196
205
  this.logger?.error('Shared secret derivation failed - invalid private key type', {
197
- actualType: privKey.type
206
+ actualType: privKey.type,
198
207
  });
199
208
  throw error;
200
209
  }
201
210
  if (pubKey.type !== 'public') {
202
211
  const error = new Error('Expected public key');
203
212
  this.logger?.error('Shared secret derivation failed - invalid public key type', {
204
- actualType: pubKey.type
213
+ actualType: pubKey.type,
205
214
  });
206
215
  throw error;
207
216
  }
@@ -213,7 +222,7 @@ export class NobleCryptoProvider implements CryptoProvider {
213
222
  const xCoordinate = sharedSecret.slice(1, 33); // Skip 0x04 prefix, take next 32 bytes
214
223
 
215
224
  this.logger?.debug('Shared secret derivation completed', {
216
- sharedSecretLength: xCoordinate.length
225
+ sharedSecretLength: xCoordinate.length,
217
226
  });
218
227
 
219
228
  return Promise.resolve(new NobleKey(xCoordinate, 'secret', 'AES-GCM', true, ['encrypt', 'decrypt']));
@@ -221,8 +230,8 @@ export class NobleCryptoProvider implements CryptoProvider {
221
230
  this.logger?.error('Shared secret derivation failed', {
222
231
  error: {
223
232
  message: error instanceof Error ? error.message : String(error),
224
- stack: error instanceof Error ? error.stack : undefined
225
- }
233
+ stack: error instanceof Error ? error.stack : undefined,
234
+ },
226
235
  });
227
236
  throw error;
228
237
  }
@@ -258,7 +267,7 @@ export class NobleCryptoProvider implements CryptoProvider {
258
267
  encrypt(key: CryptoKeyLike, data: ArrayBuffer, iv: ArrayBuffer): Promise<ArrayBuffer> {
259
268
  this.logger?.debug('Encrypting data with AES-GCM using Noble', {
260
269
  dataSize: data.byteLength,
261
- ivSize: iv.byteLength
270
+ ivSize: iv.byteLength,
262
271
  });
263
272
 
264
273
  const secretKey = key as NobleKey;
@@ -266,7 +275,7 @@ export class NobleCryptoProvider implements CryptoProvider {
266
275
  if (secretKey.type !== 'secret') {
267
276
  const error = new Error('Expected secret key');
268
277
  this.logger?.error('Encryption failed - invalid key type', {
269
- actualType: secretKey.type
278
+ actualType: secretKey.type,
270
279
  });
271
280
  throw error;
272
281
  }
@@ -276,16 +285,18 @@ export class NobleCryptoProvider implements CryptoProvider {
276
285
  const ciphertext = aesGcm.encrypt(new Uint8Array(data));
277
286
 
278
287
  this.logger?.debug('Encryption completed', {
279
- ciphertextSize: ciphertext.byteLength
288
+ ciphertextSize: ciphertext.byteLength,
280
289
  });
281
290
 
282
- return Promise.resolve(ciphertext.buffer.slice(ciphertext.byteOffset, ciphertext.byteOffset + ciphertext.byteLength));
291
+ return Promise.resolve(
292
+ ciphertext.buffer.slice(ciphertext.byteOffset, ciphertext.byteOffset + ciphertext.byteLength),
293
+ );
283
294
  } catch (error) {
284
295
  this.logger?.error('Encryption failed', {
285
296
  error: {
286
297
  message: error instanceof Error ? error.message : String(error),
287
- stack: error instanceof Error ? error.stack : undefined
288
- }
298
+ stack: error instanceof Error ? error.stack : undefined,
299
+ },
289
300
  });
290
301
  throw error;
291
302
  }
@@ -297,7 +308,7 @@ export class NobleCryptoProvider implements CryptoProvider {
297
308
  decrypt(key: CryptoKeyLike, data: ArrayBuffer, iv: ArrayBuffer): Promise<ArrayBuffer> {
298
309
  this.logger?.debug('Decrypting data with AES-GCM using Noble', {
299
310
  dataSize: data.byteLength,
300
- ivSize: iv.byteLength
311
+ ivSize: iv.byteLength,
301
312
  });
302
313
 
303
314
  const secretKey = key as NobleKey;
@@ -305,7 +316,7 @@ export class NobleCryptoProvider implements CryptoProvider {
305
316
  if (secretKey.type !== 'secret') {
306
317
  const error = new Error('Expected secret key');
307
318
  this.logger?.error('Decryption failed - invalid key type', {
308
- actualType: secretKey.type
319
+ actualType: secretKey.type,
309
320
  });
310
321
  throw error;
311
322
  }
@@ -315,7 +326,7 @@ export class NobleCryptoProvider implements CryptoProvider {
315
326
  const plaintext = aesGcm.decrypt(new Uint8Array(data));
316
327
 
317
328
  this.logger?.debug('Decryption completed', {
318
- plaintextSize: plaintext.byteLength
329
+ plaintextSize: plaintext.byteLength,
319
330
  });
320
331
 
321
332
  return Promise.resolve(plaintext.buffer.slice(plaintext.byteOffset, plaintext.byteOffset + plaintext.byteLength));
@@ -323,8 +334,8 @@ export class NobleCryptoProvider implements CryptoProvider {
323
334
  this.logger?.error('Decryption failed', {
324
335
  error: {
325
336
  message: error instanceof Error ? error.message : String(error),
326
- stack: error instanceof Error ? error.stack : undefined
327
- }
337
+ stack: error instanceof Error ? error.stack : undefined,
338
+ },
328
339
  });
329
340
  throw error;
330
341
  }
@@ -374,19 +385,3 @@ export class NobleCryptoProvider implements CryptoProvider {
374
385
  }
375
386
  }
376
387
  }
377
-
378
- /**
379
- * Self-register Noble provider on import
380
- * This allows the provider to be available when explicitly imported
381
- */
382
- registerCryptoProvider('noble', (logger) => new NobleCryptoProvider(logger));
383
-
384
- // TypeScript module augmentation to track this provider is available
385
- declare global {
386
- // eslint-disable-next-line @typescript-eslint/no-namespace
387
- namespace BananaLink {
388
- interface RegisteredCryptoProviders {
389
- noble: true;
390
- }
391
- }
392
- }