@unicitylabs/sphere-sdk 0.1.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.
- package/LICENSE +21 -0
- package/README.md +1112 -0
- package/dist/core/index.cjs +7042 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +2548 -0
- package/dist/core/index.d.ts +2548 -0
- package/dist/core/index.js +6946 -0
- package/dist/core/index.js.map +1 -0
- package/dist/impl/browser/index.cjs +7853 -0
- package/dist/impl/browser/index.cjs.map +1 -0
- package/dist/impl/browser/index.d.cts +3016 -0
- package/dist/impl/browser/index.d.ts +3016 -0
- package/dist/impl/browser/index.js +7841 -0
- package/dist/impl/browser/index.js.map +1 -0
- package/dist/impl/nodejs/index.cjs +1767 -0
- package/dist/impl/nodejs/index.cjs.map +1 -0
- package/dist/impl/nodejs/index.d.cts +1091 -0
- package/dist/impl/nodejs/index.d.ts +1091 -0
- package/dist/impl/nodejs/index.js +1722 -0
- package/dist/impl/nodejs/index.js.map +1 -0
- package/dist/index.cjs +7647 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10533 -0
- package/dist/index.d.ts +10533 -0
- package/dist/index.js +7523 -0
- package/dist/index.js.map +1 -0
- package/dist/l1/index.cjs +1545 -0
- package/dist/l1/index.cjs.map +1 -0
- package/dist/l1/index.d.cts +705 -0
- package/dist/l1/index.d.ts +705 -0
- package/dist/l1/index.js +1455 -0
- package/dist/l1/index.js.map +1 -0
- package/package.json +140 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../impl/nodejs/index.ts","../../../impl/nodejs/storage/FileStorageProvider.ts","../../../impl/nodejs/storage/FileTokenStorageProvider.ts","../../../impl/nodejs/transport/index.ts","../../../transport/NostrTransportProvider.ts","../../../transport/websocket.ts","../../../constants.ts","../../../impl/nodejs/oracle/index.ts","../../../oracle/UnicityAggregatorProvider.ts","../../../impl/shared/resolvers.ts"],"sourcesContent":["/**\n * Node.js Implementation\n * Providers for CLI/Node.js usage\n */\n\n// Storage\nexport * from './storage';\n\n// Transport\nexport * from './transport';\n\n// Oracle\nexport * from './oracle';\n\n// Re-export shared types for convenience\nexport type {\n BaseTransportConfig,\n BaseOracleConfig,\n L1Config,\n BaseProviders,\n} from '../shared';\n\n// =============================================================================\n// Convenience Factory\n// =============================================================================\n\nimport { createFileStorageProvider, createFileTokenStorageProvider } from './storage';\nimport { createNostrTransportProvider } from './transport';\nimport { createUnicityAggregatorProvider } from './oracle';\nimport type { StorageProvider, TokenStorageProvider, TxfStorageDataBase } from '../../storage';\nimport type { TransportProvider } from '../../transport';\nimport type { OracleProvider } from '../../oracle';\nimport type { NetworkType } from '../../constants';\nimport {\n type BaseTransportConfig,\n type BaseOracleConfig,\n type L1Config,\n type NodeOracleExtensions,\n resolveTransportConfig,\n resolveOracleConfig,\n resolveL1Config,\n} from '../shared';\n\n// =============================================================================\n// Node.js-Specific Configuration Extensions\n// =============================================================================\n\n/**\n * Node.js transport configuration\n * Same as base (no Node.js-specific extensions)\n */\nexport type NodeTransportConfig = BaseTransportConfig;\n\n/**\n * Node.js oracle configuration\n * Extends base with trustBasePath for file-based trust base\n */\nexport type NodeOracleConfig = BaseOracleConfig & NodeOracleExtensions;\n\n/**\n * Node.js L1 configuration\n * Same as base\n */\nexport type NodeL1Config = L1Config;\n\n// =============================================================================\n// Node.js Providers Configuration\n// =============================================================================\n\nexport interface NodeProvidersConfig {\n /** Network preset: mainnet, testnet, or dev */\n network?: NetworkType;\n /** Directory for wallet data storage */\n dataDir?: string;\n /** Directory for token files */\n tokensDir?: string;\n /** Transport (Nostr) configuration */\n transport?: NodeTransportConfig;\n /** Oracle (Aggregator) configuration */\n oracle?: NodeOracleConfig;\n /** L1 (ALPHA blockchain) configuration */\n l1?: NodeL1Config;\n}\n\nexport interface NodeProviders {\n storage: StorageProvider;\n tokenStorage: TokenStorageProvider<TxfStorageDataBase>;\n transport: TransportProvider;\n oracle: OracleProvider;\n /** L1 configuration (for passing to Sphere.init) */\n l1?: L1Config;\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Create all Node.js providers with default configuration\n *\n * @example\n * ```ts\n * // Simple - testnet with defaults\n * const providers = createNodeProviders({\n * network: 'testnet',\n * tokensDir: './tokens',\n * });\n *\n * // Full configuration\n * const providers = createNodeProviders({\n * network: 'testnet',\n * dataDir: './wallet-data',\n * tokensDir: './tokens',\n * transport: {\n * additionalRelays: ['wss://my-relay.com'],\n * debug: true,\n * },\n * oracle: {\n * apiKey: 'my-api-key',\n * trustBasePath: './trustbase.json',\n * },\n * l1: {\n * enableVesting: true,\n * },\n * });\n *\n * // Use with Sphere.init\n * const { sphere } = await Sphere.init({\n * ...providers,\n * autoGenerate: true,\n * });\n * ```\n */\nexport function createNodeProviders(config?: NodeProvidersConfig): NodeProviders {\n const network = config?.network ?? 'mainnet';\n\n // Resolve configurations using shared utilities\n const transportConfig = resolveTransportConfig(network, config?.transport);\n const oracleConfig = resolveOracleConfig(network, config?.oracle);\n const l1Config = resolveL1Config(network, config?.l1);\n\n return {\n storage: createFileStorageProvider({\n dataDir: config?.dataDir ?? './sphere-data',\n }),\n tokenStorage: createFileTokenStorageProvider({\n tokensDir: config?.tokensDir ?? './sphere-tokens',\n }),\n transport: createNostrTransportProvider({\n relays: transportConfig.relays,\n timeout: transportConfig.timeout,\n autoReconnect: transportConfig.autoReconnect,\n debug: transportConfig.debug,\n }),\n oracle: createUnicityAggregatorProvider({\n url: oracleConfig.url,\n apiKey: oracleConfig.apiKey,\n timeout: oracleConfig.timeout,\n trustBasePath: oracleConfig.trustBasePath,\n skipVerification: oracleConfig.skipVerification,\n debug: oracleConfig.debug,\n }),\n l1: l1Config,\n };\n}\n","/**\n * File Storage Provider for Node.js\n * Stores wallet data in JSON files\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { StorageProvider } from '../../../storage';\nimport type { FullIdentity, ProviderStatus } from '../../../types';\n\nexport interface FileStorageProviderConfig {\n /** Directory to store wallet data */\n dataDir: string;\n /** File name for key-value data (default: 'wallet.json') */\n fileName?: string;\n}\n\nexport class FileStorageProvider implements StorageProvider {\n readonly id = 'file-storage';\n readonly name = 'File Storage';\n readonly type = 'local' as const;\n\n private dataDir: string;\n private filePath: string;\n private data: Record<string, string> = {};\n private status: ProviderStatus = 'disconnected';\n private _identity: FullIdentity | null = null;\n\n constructor(config: FileStorageProviderConfig | string) {\n if (typeof config === 'string') {\n this.dataDir = config;\n this.filePath = path.join(config, 'wallet.json');\n } else {\n this.dataDir = config.dataDir;\n this.filePath = path.join(config.dataDir, config.fileName ?? 'wallet.json');\n }\n }\n\n setIdentity(identity: FullIdentity): void {\n this._identity = identity;\n }\n\n getIdentity(): FullIdentity | null {\n return this._identity;\n }\n\n async connect(): Promise<void> {\n // Ensure directory exists\n if (!fs.existsSync(this.dataDir)) {\n fs.mkdirSync(this.dataDir, { recursive: true });\n }\n\n // Load existing data\n if (fs.existsSync(this.filePath)) {\n try {\n const content = fs.readFileSync(this.filePath, 'utf-8');\n this.data = JSON.parse(content);\n } catch {\n this.data = {};\n }\n }\n\n this.status = 'connected';\n }\n\n async disconnect(): Promise<void> {\n await this.save();\n this.status = 'disconnected';\n }\n\n isConnected(): boolean {\n return this.status === 'connected';\n }\n\n getStatus(): ProviderStatus {\n return this.status;\n }\n\n async get(key: string): Promise<string | null> {\n return this.data[key] ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.data[key] = value;\n await this.save();\n }\n\n async remove(key: string): Promise<void> {\n delete this.data[key];\n await this.save();\n }\n\n async has(key: string): Promise<boolean> {\n return key in this.data;\n }\n\n async keys(prefix?: string): Promise<string[]> {\n const allKeys = Object.keys(this.data);\n if (prefix) {\n return allKeys.filter((k) => k.startsWith(prefix));\n }\n return allKeys;\n }\n\n async clear(prefix?: string): Promise<void> {\n if (prefix) {\n const keysToDelete = Object.keys(this.data).filter((k) => k.startsWith(prefix));\n for (const key of keysToDelete) {\n delete this.data[key];\n }\n } else {\n this.data = {};\n }\n await this.save();\n }\n\n private async save(): Promise<void> {\n // Ensure directory exists before writing\n if (!fs.existsSync(this.dataDir)) {\n fs.mkdirSync(this.dataDir, { recursive: true });\n }\n fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2));\n }\n}\n\nexport function createFileStorageProvider(config: FileStorageProviderConfig | string): FileStorageProvider {\n return new FileStorageProvider(config);\n}\n","/**\n * File Token Storage Provider for Node.js\n * Stores tokens as individual JSON files\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { TokenStorageProvider, TxfStorageDataBase, SyncResult, SaveResult, LoadResult } from '../../../storage';\nimport type { FullIdentity, ProviderStatus } from '../../../types';\n\nexport interface FileTokenStorageConfig {\n /** Directory to store token files */\n tokensDir: string;\n}\n\nexport class FileTokenStorageProvider implements TokenStorageProvider<TxfStorageDataBase> {\n readonly id = 'file-token-storage';\n readonly name = 'File Token Storage';\n readonly type = 'local' as const;\n\n private tokensDir: string;\n private status: ProviderStatus = 'disconnected';\n private identity: FullIdentity | null = null;\n\n constructor(config: FileTokenStorageConfig | string) {\n this.tokensDir = typeof config === 'string' ? config : config.tokensDir;\n }\n\n setIdentity(identity: FullIdentity): void {\n this.identity = identity;\n }\n\n async initialize(): Promise<boolean> {\n if (!fs.existsSync(this.tokensDir)) {\n fs.mkdirSync(this.tokensDir, { recursive: true });\n }\n this.status = 'connected';\n return true;\n }\n\n async shutdown(): Promise<void> {\n this.status = 'disconnected';\n }\n\n async connect(): Promise<void> {\n await this.initialize();\n }\n\n async disconnect(): Promise<void> {\n this.status = 'disconnected';\n }\n\n isConnected(): boolean {\n return this.status === 'connected';\n }\n\n getStatus(): ProviderStatus {\n return this.status;\n }\n\n async load(): Promise<LoadResult<TxfStorageDataBase>> {\n const data: TxfStorageDataBase = {\n _meta: {\n version: 1,\n address: this.identity?.address ?? '',\n formatVersion: '2.0',\n updatedAt: Date.now(),\n },\n };\n\n try {\n const files = fs.readdirSync(this.tokensDir).filter(f => f.endsWith('.json') && f !== '_meta.json');\n\n for (const file of files) {\n try {\n const content = fs.readFileSync(path.join(this.tokensDir, file), 'utf-8');\n const token = JSON.parse(content);\n const key = `_${path.basename(file, '.json')}` as `_${string}`;\n data[key] = token;\n } catch {\n // Skip invalid files\n }\n }\n\n return {\n success: true,\n data,\n source: 'local',\n timestamp: Date.now(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n source: 'local',\n timestamp: Date.now(),\n };\n }\n }\n\n async save(data: TxfStorageDataBase): Promise<SaveResult> {\n try {\n // Save meta\n fs.writeFileSync(\n path.join(this.tokensDir, '_meta.json'),\n JSON.stringify(data._meta, null, 2)\n );\n\n // Save each token\n for (const [key, value] of Object.entries(data)) {\n if (key.startsWith('_') && key !== '_meta' && key !== '_tombstones' && key !== '_outbox' && key !== '_sent' && key !== '_invalid') {\n const tokenId = key.slice(1);\n fs.writeFileSync(\n path.join(this.tokensDir, `${tokenId}.json`),\n JSON.stringify(value, null, 2)\n );\n }\n }\n\n // Handle tombstones - delete files\n if (data._tombstones) {\n for (const tombstone of data._tombstones) {\n const filePath = path.join(this.tokensDir, `${tombstone.tokenId}.json`);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n }\n }\n\n return {\n success: true,\n timestamp: Date.now(),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n timestamp: Date.now(),\n };\n }\n }\n\n async sync(localData: TxfStorageDataBase): Promise<SyncResult<TxfStorageDataBase>> {\n // For file storage, just save and return\n const saveResult = await this.save(localData);\n return {\n success: saveResult.success,\n merged: localData,\n added: 0,\n removed: 0,\n conflicts: 0,\n error: saveResult.error,\n };\n }\n\n async deleteToken(tokenId: string): Promise<void> {\n const filePath = path.join(this.tokensDir, `${tokenId}.json`);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n }\n\n async saveToken(tokenId: string, tokenData: unknown): Promise<void> {\n fs.writeFileSync(\n path.join(this.tokensDir, `${tokenId}.json`),\n JSON.stringify(tokenData, null, 2)\n );\n }\n\n async getToken(tokenId: string): Promise<unknown | null> {\n const filePath = path.join(this.tokensDir, `${tokenId}.json`);\n if (!fs.existsSync(filePath)) {\n return null;\n }\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n }\n\n async listTokenIds(): Promise<string[]> {\n const files = fs.readdirSync(this.tokensDir).filter(f => f.endsWith('.json') && f !== '_meta.json');\n return files.map(f => path.basename(f, '.json'));\n }\n}\n\nexport function createFileTokenStorageProvider(config: FileTokenStorageConfig | string): FileTokenStorageProvider {\n return new FileTokenStorageProvider(config);\n}\n","/**\n * Node.js Transport Exports\n * Re-exports shared transport with Node.js WebSocket\n */\n\nimport WebSocket from 'ws';\n\nimport {\n NostrTransportProvider,\n type NostrTransportProviderConfig,\n} from '../../../transport/NostrTransportProvider';\nimport type { IWebSocket, WebSocketFactory } from '../../../transport/websocket';\n\n// Re-export shared types\nexport {\n NostrTransportProvider,\n type NostrTransportProviderConfig,\n} from '../../../transport/NostrTransportProvider';\n\nexport type { IWebSocket, WebSocketFactory } from '../../../transport/websocket';\n\n// =============================================================================\n// Node.js WebSocket Factory\n// =============================================================================\n\n/**\n * Create WebSocket factory for Node.js using 'ws' package\n */\nexport function createNodeWebSocketFactory(): WebSocketFactory {\n return (url: string): IWebSocket => {\n return new WebSocket(url) as IWebSocket;\n };\n}\n\n// =============================================================================\n// Node.js Factory\n// =============================================================================\n\n/**\n * Create NostrTransportProvider with Node.js WebSocket\n */\nexport function createNostrTransportProvider(\n config: Omit<NostrTransportProviderConfig, 'createWebSocket'>\n): NostrTransportProvider {\n return new NostrTransportProvider({\n ...config,\n createWebSocket: createNodeWebSocketFactory(),\n });\n}\n","/**\n * Nostr Transport Provider\n * Platform-independent implementation using Nostr protocol for P2P messaging\n *\n * Uses @unicitylabs/nostr-js-sdk for:\n * - Real secp256k1 event signing\n * - NIP-04 encryption/decryption\n * - Event ID calculation\n *\n * WebSocket is injected via factory for cross-platform support\n */\n\nimport { Buffer } from 'buffer';\nimport {\n NostrKeyManager,\n NIP04,\n Event as NostrEventClass,\n hashNametag,\n} from '@unicitylabs/nostr-js-sdk';\nimport type { ProviderStatus, FullIdentity } from '../types';\nimport type {\n TransportProvider,\n MessageHandler,\n TokenTransferHandler,\n BroadcastHandler,\n PaymentRequestHandler,\n PaymentRequestResponseHandler,\n IncomingMessage,\n IncomingTokenTransfer,\n IncomingBroadcast,\n IncomingPaymentRequest,\n IncomingPaymentRequestResponse,\n TokenTransferPayload,\n PaymentRequestPayload,\n PaymentRequestResponsePayload,\n TransportEvent,\n TransportEventCallback,\n} from './transport-provider';\nimport type { IWebSocket, IMessageEvent, WebSocketFactory, UUIDGenerator } from './websocket';\nimport { WebSocketReadyState, defaultUUIDGenerator } from './websocket';\nimport {\n DEFAULT_NOSTR_RELAYS,\n NOSTR_EVENT_KINDS,\n TIMEOUTS,\n} from '../constants';\n\n// =============================================================================\n// Configuration\n// =============================================================================\n\nexport interface NostrTransportProviderConfig {\n /** Nostr relay URLs */\n relays?: string[];\n /** Connection timeout (ms) */\n timeout?: number;\n /** Auto-reconnect on disconnect */\n autoReconnect?: boolean;\n /** Reconnect delay (ms) */\n reconnectDelay?: number;\n /** Max reconnect attempts */\n maxReconnectAttempts?: number;\n /** Enable debug logging */\n debug?: boolean;\n /** WebSocket factory (required for platform support) */\n createWebSocket: WebSocketFactory;\n /** UUID generator (optional, defaults to crypto.randomUUID) */\n generateUUID?: UUIDGenerator;\n}\n\n// Alias for backward compatibility\nconst EVENT_KINDS = NOSTR_EVENT_KINDS;\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\nexport class NostrTransportProvider implements TransportProvider {\n readonly id = 'nostr';\n readonly name = 'Nostr Transport';\n readonly type = 'p2p' as const;\n readonly description = 'P2P messaging via Nostr protocol';\n\n private config: Required<Omit<NostrTransportProviderConfig, 'createWebSocket' | 'generateUUID'>> & {\n createWebSocket: WebSocketFactory;\n generateUUID: UUIDGenerator;\n };\n private identity: FullIdentity | null = null;\n private keyManager: NostrKeyManager | null = null;\n private status: ProviderStatus = 'disconnected';\n\n // WebSocket connections to relays\n private connections: Map<string, IWebSocket> = new Map();\n private reconnectAttempts: Map<string, number> = new Map();\n\n // Event handlers\n private messageHandlers: Set<MessageHandler> = new Set();\n private transferHandlers: Set<TokenTransferHandler> = new Set();\n private paymentRequestHandlers: Set<PaymentRequestHandler> = new Set();\n private paymentRequestResponseHandlers: Set<PaymentRequestResponseHandler> = new Set();\n private broadcastHandlers: Map<string, Set<BroadcastHandler>> = new Map();\n private eventCallbacks: Set<TransportEventCallback> = new Set();\n\n // Subscriptions\n private subscriptions: Map<string, string[]> = new Map(); // subId -> relays\n\n constructor(config: NostrTransportProviderConfig) {\n this.config = {\n relays: config.relays ?? [...DEFAULT_NOSTR_RELAYS],\n timeout: config.timeout ?? TIMEOUTS.WEBSOCKET_CONNECT,\n autoReconnect: config.autoReconnect ?? true,\n reconnectDelay: config.reconnectDelay ?? TIMEOUTS.NOSTR_RECONNECT_DELAY,\n maxReconnectAttempts: config.maxReconnectAttempts ?? TIMEOUTS.MAX_RECONNECT_ATTEMPTS,\n debug: config.debug ?? false,\n createWebSocket: config.createWebSocket,\n generateUUID: config.generateUUID ?? defaultUUIDGenerator,\n };\n }\n\n // ===========================================================================\n // BaseProvider Implementation\n // ===========================================================================\n\n async connect(): Promise<void> {\n if (this.status === 'connected') return;\n\n this.status = 'connecting';\n\n try {\n // Connect to all relays in parallel\n const connectPromises = this.config.relays.map((relay) =>\n this.connectToRelay(relay)\n );\n\n await Promise.allSettled(connectPromises);\n\n // Need at least one successful connection\n if (this.connections.size === 0) {\n throw new Error('Failed to connect to any relay');\n }\n\n this.status = 'connected';\n this.emitEvent({ type: 'transport:connected', timestamp: Date.now() });\n this.log('Connected to', this.connections.size, 'relays');\n\n // Set up subscriptions\n if (this.identity) {\n this.subscribeToEvents();\n }\n } catch (error) {\n this.status = 'error';\n throw error;\n }\n }\n\n async disconnect(): Promise<void> {\n for (const [url, ws] of this.connections) {\n ws.close();\n this.connections.delete(url);\n }\n\n this.subscriptions.clear();\n this.status = 'disconnected';\n this.emitEvent({ type: 'transport:disconnected', timestamp: Date.now() });\n this.log('Disconnected from all relays');\n }\n\n isConnected(): boolean {\n return this.status === 'connected' && this.connections.size > 0;\n }\n\n getStatus(): ProviderStatus {\n return this.status;\n }\n\n // ===========================================================================\n // Dynamic Relay Management\n // ===========================================================================\n\n /**\n * Get list of configured relay URLs\n */\n getRelays(): string[] {\n return [...this.config.relays];\n }\n\n /**\n * Get list of currently connected relay URLs\n */\n getConnectedRelays(): string[] {\n return Array.from(this.connections.keys());\n }\n\n /**\n * Add a new relay dynamically\n * Will connect immediately if provider is already connected\n */\n async addRelay(relayUrl: string): Promise<boolean> {\n // Check if already configured\n if (this.config.relays.includes(relayUrl)) {\n this.log('Relay already configured:', relayUrl);\n return false;\n }\n\n // Add to config\n this.config.relays.push(relayUrl);\n\n // Connect if provider is connected\n if (this.status === 'connected') {\n try {\n await this.connectToRelay(relayUrl);\n this.log('Added and connected to relay:', relayUrl);\n this.emitEvent({\n type: 'transport:relay_added',\n timestamp: Date.now(),\n data: { relay: relayUrl, connected: true },\n });\n return true;\n } catch (error) {\n this.log('Failed to connect to new relay:', relayUrl, error);\n this.emitEvent({\n type: 'transport:relay_added',\n timestamp: Date.now(),\n data: { relay: relayUrl, connected: false, error: String(error) },\n });\n return false;\n }\n }\n\n this.emitEvent({\n type: 'transport:relay_added',\n timestamp: Date.now(),\n data: { relay: relayUrl, connected: false },\n });\n return true;\n }\n\n /**\n * Remove a relay dynamically\n * Will disconnect from the relay if connected\n */\n async removeRelay(relayUrl: string): Promise<boolean> {\n const index = this.config.relays.indexOf(relayUrl);\n if (index === -1) {\n this.log('Relay not found:', relayUrl);\n return false;\n }\n\n // Remove from config\n this.config.relays.splice(index, 1);\n\n // Disconnect if connected\n const ws = this.connections.get(relayUrl);\n if (ws) {\n ws.close();\n this.connections.delete(relayUrl);\n this.reconnectAttempts.delete(relayUrl);\n this.log('Removed and disconnected from relay:', relayUrl);\n }\n\n this.emitEvent({\n type: 'transport:relay_removed',\n timestamp: Date.now(),\n data: { relay: relayUrl },\n });\n\n // Check if we still have connections\n if (this.connections.size === 0 && this.status === 'connected') {\n this.status = 'error';\n this.emitEvent({\n type: 'transport:error',\n timestamp: Date.now(),\n data: { error: 'No connected relays remaining' },\n });\n }\n\n return true;\n }\n\n /**\n * Check if a relay is configured\n */\n hasRelay(relayUrl: string): boolean {\n return this.config.relays.includes(relayUrl);\n }\n\n /**\n * Check if a relay is currently connected\n */\n isRelayConnected(relayUrl: string): boolean {\n const ws = this.connections.get(relayUrl);\n return ws !== undefined && ws.readyState === WebSocketReadyState.OPEN;\n }\n\n // ===========================================================================\n // TransportProvider Implementation\n // ===========================================================================\n\n setIdentity(identity: FullIdentity): void {\n this.identity = identity;\n\n // Create NostrKeyManager from private key\n const secretKey = Buffer.from(identity.privateKey, 'hex');\n this.keyManager = NostrKeyManager.fromPrivateKey(secretKey);\n\n // Use Nostr-format pubkey (32 bytes / 64 hex chars) from keyManager\n const nostrPubkey = this.keyManager.getPublicKeyHex();\n this.log('Identity set, Nostr pubkey:', nostrPubkey.slice(0, 16) + '...');\n\n // Re-subscribe if already connected\n if (this.isConnected()) {\n this.subscribeToEvents();\n }\n }\n\n /**\n * Get the Nostr-format public key (32 bytes / 64 hex chars)\n * This is the x-coordinate only, without the 02/03 prefix.\n */\n getNostrPubkey(): string {\n if (!this.keyManager) {\n throw new Error('KeyManager not initialized - call setIdentity first');\n }\n return this.keyManager.getPublicKeyHex();\n }\n\n async sendMessage(recipientPubkey: string, content: string): Promise<string> {\n this.ensureReady();\n\n // Create NIP-04 encrypted DM event\n const event = await this.createEncryptedEvent(\n EVENT_KINDS.DIRECT_MESSAGE,\n content,\n [['p', recipientPubkey]]\n );\n\n await this.publishEvent(event);\n\n this.emitEvent({\n type: 'message:sent',\n timestamp: Date.now(),\n data: { recipient: recipientPubkey },\n });\n\n return event.id;\n }\n\n onMessage(handler: MessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n async sendTokenTransfer(\n recipientPubkey: string,\n payload: TokenTransferPayload\n ): Promise<string> {\n this.ensureReady();\n\n // Create encrypted token transfer event\n // Content must have \"token_transfer:\" prefix for nostr-js-sdk compatibility\n const content = 'token_transfer:' + JSON.stringify(payload);\n const event = await this.createEncryptedEvent(\n EVENT_KINDS.TOKEN_TRANSFER,\n content,\n [\n ['p', recipientPubkey],\n ['d', 'token-transfer'],\n ['type', 'token_transfer'],\n ]\n );\n\n await this.publishEvent(event);\n\n this.emitEvent({\n type: 'transfer:sent',\n timestamp: Date.now(),\n data: { recipient: recipientPubkey },\n });\n\n return event.id;\n }\n\n onTokenTransfer(handler: TokenTransferHandler): () => void {\n this.transferHandlers.add(handler);\n return () => this.transferHandlers.delete(handler);\n }\n\n async sendPaymentRequest(\n recipientPubkey: string,\n payload: PaymentRequestPayload\n ): Promise<string> {\n this.ensureReady();\n\n const requestId = this.config.generateUUID();\n const amount = typeof payload.amount === 'bigint' ? payload.amount.toString() : payload.amount;\n\n // Build request content matching nostr-js-sdk format\n const requestContent = {\n requestId,\n amount,\n coinId: payload.coinId,\n message: payload.message,\n recipientNametag: payload.recipientNametag,\n deadline: Date.now() + 5 * 60 * 1000, // 5 minutes default\n };\n\n // Content must have \"payment_request:\" prefix for nostr-js-sdk compatibility\n const content = 'payment_request:' + JSON.stringify(requestContent);\n\n // Build tags matching nostr-js-sdk format\n const tags: string[][] = [\n ['p', recipientPubkey],\n ['type', 'payment_request'],\n ['amount', amount],\n ];\n if (payload.recipientNametag) {\n tags.push(['recipient', payload.recipientNametag]);\n }\n\n const event = await this.createEncryptedEvent(\n EVENT_KINDS.PAYMENT_REQUEST,\n content,\n tags\n );\n\n await this.publishEvent(event);\n\n this.log('Sent payment request:', event.id);\n\n return event.id;\n }\n\n onPaymentRequest(handler: PaymentRequestHandler): () => void {\n this.paymentRequestHandlers.add(handler);\n return () => this.paymentRequestHandlers.delete(handler);\n }\n\n async sendPaymentRequestResponse(\n recipientPubkey: string,\n payload: PaymentRequestResponsePayload\n ): Promise<string> {\n this.ensureReady();\n\n // Build response content\n const responseContent = {\n requestId: payload.requestId,\n responseType: payload.responseType,\n message: payload.message,\n transferId: payload.transferId,\n };\n\n // Create encrypted payment request response event\n // Content must have \"payment_response:\" prefix for nostr-js-sdk compatibility\n const content = 'payment_response:' + JSON.stringify(responseContent);\n const event = await this.createEncryptedEvent(\n EVENT_KINDS.PAYMENT_REQUEST_RESPONSE,\n content,\n [\n ['p', recipientPubkey],\n ['e', payload.requestId], // Reference to original request\n ['d', 'payment-request-response'],\n ['type', 'payment_response'],\n ]\n );\n\n await this.publishEvent(event);\n\n this.log('Sent payment request response:', event.id, 'type:', payload.responseType);\n\n return event.id;\n }\n\n onPaymentRequestResponse(handler: PaymentRequestResponseHandler): () => void {\n this.paymentRequestResponseHandlers.add(handler);\n return () => this.paymentRequestResponseHandlers.delete(handler);\n }\n\n async resolveNametag(nametag: string): Promise<string | null> {\n this.ensureReady();\n\n // Query for nametag binding events using hashed nametag (privacy-preserving)\n // Try both '#d' and '#t' filters for compatibility with nostr-js-sdk\n const hashedNametag = hashNametag(nametag);\n\n // First try '#t' tag (nostr-js-sdk format)\n let events = await this.queryEvents({\n kinds: [EVENT_KINDS.NAMETAG_BINDING],\n '#t': [hashedNametag],\n limit: 1,\n });\n\n // Fallback to '#d' tag (legacy format)\n if (events.length === 0) {\n events = await this.queryEvents({\n kinds: [EVENT_KINDS.NAMETAG_BINDING],\n '#d': [hashedNametag],\n limit: 1,\n });\n }\n\n if (events.length === 0) return null;\n\n // Parse binding event\n const bindingEvent = events[0];\n\n // For Nostr messaging (NIP-04 encryption), we MUST use the event author's pubkey.\n // The 'address' tag contains the Unicity blockchain address (not a hex pubkey),\n // which cannot be used for Nostr encryption.\n // The event.pubkey is always the hex pubkey of the nametag owner.\n if (bindingEvent.pubkey) {\n return bindingEvent.pubkey;\n }\n\n // Fallback: try 'p' tag (our SDK format uses hex pubkey here)\n const pubkeyTag = bindingEvent.tags.find((t: string[]) => t[0] === 'p');\n if (pubkeyTag?.[1]) return pubkeyTag[1];\n\n return null;\n }\n\n async publishNametag(nametag: string, address: string): Promise<void> {\n this.ensureReady();\n\n // Use hashed nametag (privacy-preserving)\n const hashedNametag = hashNametag(nametag);\n const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, address, [\n ['d', hashedNametag],\n ['a', address],\n ]);\n\n await this.publishEvent(event);\n this.log('Published nametag binding:', nametag);\n }\n\n async registerNametag(nametag: string, _publicKey: string): Promise<boolean> {\n this.ensureReady();\n\n // Always use 32-byte Nostr-format pubkey from keyManager (not the 33-byte compressed key)\n const nostrPubkey = this.getNostrPubkey();\n\n // Check if nametag is already taken by someone else\n const existing = await this.resolveNametag(nametag);\n\n this.log('registerNametag:', nametag, 'existing:', existing, 'myPubkey:', nostrPubkey);\n\n if (existing && existing !== nostrPubkey) {\n this.log('Nametag already taken:', nametag, '- owner:', existing);\n return false;\n }\n\n // Always (re)publish to ensure event has correct format with all required tags\n // This is a parameterized replaceable event (kind 30078), so publishing with same 'd' tag\n // will replace any old event. This ensures the event has ['t', hash] tag for nostr-js-sdk.\n\n // Publish nametag binding matching nostr-js-sdk format\n // Use Nostr pubkey (32 bytes) for all fields\n const hashedNametag = hashNametag(nametag);\n const content = JSON.stringify({\n nametag_hash: hashedNametag,\n address: nostrPubkey,\n verified: Date.now(),\n });\n\n const event = await this.createEvent(EVENT_KINDS.NAMETAG_BINDING, content, [\n ['d', hashedNametag],\n ['nametag', hashedNametag],\n ['t', hashedNametag],\n['address', nostrPubkey],\n ]);\n\n await this.publishEvent(event);\n this.log('Registered nametag:', nametag, 'for pubkey:', nostrPubkey.slice(0, 16) + '...');\n return true;\n }\n\n subscribeToBroadcast(tags: string[], handler: BroadcastHandler): () => void {\n const key = tags.sort().join(':');\n\n if (!this.broadcastHandlers.has(key)) {\n this.broadcastHandlers.set(key, new Set());\n\n // Subscribe to relay\n if (this.isConnected()) {\n this.subscribeToTags(tags);\n }\n }\n\n this.broadcastHandlers.get(key)!.add(handler);\n\n return () => {\n this.broadcastHandlers.get(key)?.delete(handler);\n if (this.broadcastHandlers.get(key)?.size === 0) {\n this.broadcastHandlers.delete(key);\n }\n };\n }\n\n async publishBroadcast(content: string, tags?: string[]): Promise<string> {\n this.ensureReady();\n\n const eventTags = tags?.map((t) => ['t', t]) ?? [];\n const event = await this.createEvent(EVENT_KINDS.BROADCAST, content, eventTags);\n\n await this.publishEvent(event);\n return event.id;\n }\n\n // ===========================================================================\n // Event Subscription\n // ===========================================================================\n\n onEvent(callback: TransportEventCallback): () => void {\n this.eventCallbacks.add(callback);\n return () => this.eventCallbacks.delete(callback);\n }\n\n // ===========================================================================\n // Private: Connection Management\n // ===========================================================================\n\n private async connectToRelay(url: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const ws = this.config.createWebSocket(url);\n\n const timeout = setTimeout(() => {\n ws.close();\n reject(new Error(`Connection timeout: ${url}`));\n }, this.config.timeout);\n\n ws.onopen = () => {\n clearTimeout(timeout);\n this.connections.set(url, ws);\n this.reconnectAttempts.set(url, 0);\n this.log('Connected to relay:', url);\n resolve();\n };\n\n ws.onerror = (error) => {\n clearTimeout(timeout);\n this.log('Relay error:', url, error);\n reject(error);\n };\n\n ws.onclose = () => {\n this.connections.delete(url);\n if (this.config.autoReconnect && this.status === 'connected') {\n this.scheduleReconnect(url);\n }\n };\n\n ws.onmessage = (event: IMessageEvent) => {\n this.handleRelayMessage(url, event.data);\n };\n });\n }\n\n private scheduleReconnect(url: string): void {\n const attempts = this.reconnectAttempts.get(url) ?? 0;\n if (attempts >= this.config.maxReconnectAttempts) {\n this.log('Max reconnect attempts reached for:', url);\n return;\n }\n\n this.reconnectAttempts.set(url, attempts + 1);\n const delay = this.config.reconnectDelay * Math.pow(2, attempts);\n\n this.emitEvent({ type: 'transport:reconnecting', timestamp: Date.now() });\n\n setTimeout(() => {\n this.connectToRelay(url).catch(() => {\n // Will retry again if still below max attempts\n });\n }, delay);\n }\n\n // ===========================================================================\n // Private: Message Handling\n // ===========================================================================\n\n private handleRelayMessage(relay: string, data: string): void {\n try {\n const message = JSON.parse(data);\n const [type, ...args] = message;\n\n switch (type) {\n case 'EVENT':\n this.handleEvent(args[1]);\n break;\n case 'EOSE':\n // End of stored events\n break;\n case 'OK':\n // Event accepted\n break;\n case 'NOTICE':\n this.log('Relay notice:', relay, args[0]);\n break;\n }\n } catch (error) {\n this.log('Failed to parse relay message:', error);\n }\n }\n\n private async handleEvent(event: NostrEvent): Promise<void> {\n try {\n switch (event.kind) {\n case EVENT_KINDS.DIRECT_MESSAGE:\n await this.handleDirectMessage(event);\n break;\n case EVENT_KINDS.TOKEN_TRANSFER:\n await this.handleTokenTransfer(event);\n break;\n case EVENT_KINDS.PAYMENT_REQUEST:\n await this.handlePaymentRequest(event);\n break;\n case EVENT_KINDS.PAYMENT_REQUEST_RESPONSE:\n await this.handlePaymentRequestResponse(event);\n break;\n case EVENT_KINDS.BROADCAST:\n this.handleBroadcast(event);\n break;\n }\n } catch (error) {\n this.log('Failed to handle event:', error);\n }\n }\n\n private async handleDirectMessage(event: NostrEvent): Promise<void> {\n if (!this.identity || !this.keyManager) return;\n\n // Skip our own messages (compare with 32-byte Nostr pubkey)\n if (event.pubkey === this.keyManager.getPublicKeyHex()) return;\n\n // Decrypt content\n const content = await this.decryptContent(event.content, event.pubkey);\n\n const message: IncomingMessage = {\n id: event.id,\n senderPubkey: event.pubkey,\n content,\n timestamp: event.created_at * 1000,\n encrypted: true,\n };\n\n this.emitEvent({ type: 'message:received', timestamp: Date.now() });\n\n for (const handler of this.messageHandlers) {\n try {\n handler(message);\n } catch (error) {\n this.log('Message handler error:', error);\n }\n }\n }\n\n private async handleTokenTransfer(event: NostrEvent): Promise<void> {\n if (!this.identity) return;\n\n // Decrypt content\n const content = await this.decryptContent(event.content, event.pubkey);\n const payload = JSON.parse(content) as TokenTransferPayload;\n\n const transfer: IncomingTokenTransfer = {\n id: event.id,\n senderPubkey: event.pubkey,\n payload,\n timestamp: event.created_at * 1000,\n };\n\n this.emitEvent({ type: 'transfer:received', timestamp: Date.now() });\n\n for (const handler of this.transferHandlers) {\n try {\n handler(transfer);\n } catch (error) {\n this.log('Transfer handler error:', error);\n }\n }\n }\n\n private async handlePaymentRequest(event: NostrEvent): Promise<void> {\n if (!this.identity) return;\n\n try {\n // Decrypt content\n const content = await this.decryptContent(event.content, event.pubkey);\n const requestData = JSON.parse(content) as {\n requestId: string;\n amount: string;\n coinId: string;\n message?: string;\n recipientNametag?: string;\n metadata?: Record<string, unknown>;\n };\n\n const request: IncomingPaymentRequest = {\n id: event.id,\n senderPubkey: event.pubkey,\n request: {\n requestId: requestData.requestId,\n amount: requestData.amount,\n coinId: requestData.coinId,\n message: requestData.message,\n recipientNametag: requestData.recipientNametag,\n metadata: requestData.metadata,\n },\n timestamp: event.created_at * 1000,\n };\n\n this.log('Received payment request:', request.id);\n\n for (const handler of this.paymentRequestHandlers) {\n try {\n handler(request);\n } catch (error) {\n this.log('Payment request handler error:', error);\n }\n }\n } catch (error) {\n this.log('Failed to handle payment request:', error);\n }\n }\n\n private async handlePaymentRequestResponse(event: NostrEvent): Promise<void> {\n if (!this.identity) return;\n\n try {\n // Decrypt content\n const content = await this.decryptContent(event.content, event.pubkey);\n const responseData = JSON.parse(content) as {\n requestId: string;\n responseType: 'accepted' | 'rejected' | 'paid';\n message?: string;\n transferId?: string;\n };\n\n const response: IncomingPaymentRequestResponse = {\n id: event.id,\n responderPubkey: event.pubkey,\n response: {\n requestId: responseData.requestId,\n responseType: responseData.responseType,\n message: responseData.message,\n transferId: responseData.transferId,\n },\n timestamp: event.created_at * 1000,\n };\n\n this.log('Received payment request response:', response.id, 'type:', responseData.responseType);\n\n for (const handler of this.paymentRequestResponseHandlers) {\n try {\n handler(response);\n } catch (error) {\n this.log('Payment request response handler error:', error);\n }\n }\n } catch (error) {\n this.log('Failed to handle payment request response:', error);\n }\n }\n\n private handleBroadcast(event: NostrEvent): void {\n const tags = event.tags\n .filter((t: string[]) => t[0] === 't')\n .map((t: string[]) => t[1]);\n\n const broadcast: IncomingBroadcast = {\n id: event.id,\n authorPubkey: event.pubkey,\n content: event.content,\n tags,\n timestamp: event.created_at * 1000,\n };\n\n // Find matching handlers\n for (const [key, handlers] of this.broadcastHandlers) {\n const subscribedTags = key.split(':');\n if (tags.some((t) => subscribedTags.includes(t))) {\n for (const handler of handlers) {\n try {\n handler(broadcast);\n } catch (error) {\n this.log('Broadcast handler error:', error);\n }\n }\n }\n }\n }\n\n // ===========================================================================\n // Private: Event Creation & Publishing\n // ===========================================================================\n\n private async createEvent(\n kind: number,\n content: string,\n tags: string[][]\n ): Promise<NostrEvent> {\n if (!this.identity) throw new Error('Identity not set');\n if (!this.keyManager) throw new Error('KeyManager not initialized');\n\n // Create and sign event using SDK\n const signedEvent = NostrEventClass.create(this.keyManager, {\n kind,\n content,\n tags,\n });\n\n // Convert to our interface\n const event: NostrEvent = {\n id: signedEvent.id,\n kind: signedEvent.kind,\n content: signedEvent.content,\n tags: signedEvent.tags,\n pubkey: signedEvent.pubkey,\n created_at: signedEvent.created_at,\n sig: signedEvent.sig,\n };\n\n return event;\n }\n\n private async createEncryptedEvent(\n kind: number,\n content: string,\n tags: string[][]\n ): Promise<NostrEvent> {\n if (!this.keyManager) throw new Error('KeyManager not initialized');\n\n // Extract recipient pubkey from tags (first 'p' tag)\n const recipientTag = tags.find((t) => t[0] === 'p');\n if (!recipientTag || !recipientTag[1]) {\n throw new Error('No recipient pubkey in tags for encryption');\n }\n const recipientPubkey = recipientTag[1];\n\n // Encrypt content with NIP-04 (using hex variant for string keys)\n const encrypted = await NIP04.encryptHex(\n content,\n this.keyManager.getPrivateKeyHex(),\n recipientPubkey\n );\n\n return this.createEvent(kind, encrypted, tags);\n }\n\n private async publishEvent(event: NostrEvent): Promise<void> {\n const message = JSON.stringify(['EVENT', event]);\n\n const publishPromises = Array.from(this.connections.values()).map((ws) => {\n return new Promise<void>((resolve, reject) => {\n if (ws.readyState !== WebSocketReadyState.OPEN) {\n reject(new Error('WebSocket not open'));\n return;\n }\n\n ws.send(message);\n resolve();\n });\n });\n\n await Promise.any(publishPromises);\n }\n\n private async queryEvents(filter: NostrFilter): Promise<NostrEvent[]> {\n if (this.connections.size === 0) {\n throw new Error('No connected relays');\n }\n\n // Query all relays in parallel and return first non-empty result\n const queryPromises = Array.from(this.connections.values()).map(ws =>\n this.queryEventsFromRelay(ws, filter)\n );\n\n // Wait for first relay that returns events, or all to complete\n const results = await Promise.allSettled(queryPromises);\n\n // Find first successful result with events\n for (const result of results) {\n if (result.status === 'fulfilled' && result.value.length > 0) {\n return result.value;\n }\n }\n\n // No events found on any relay\n return [];\n }\n\n private async queryEventsFromRelay(ws: IWebSocket, filter: NostrFilter): Promise<NostrEvent[]> {\n const subId = this.config.generateUUID().slice(0, 8);\n const events: NostrEvent[] = [];\n\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n this.unsubscribeFromRelay(ws, subId);\n resolve(events);\n }, 5000);\n\n const originalHandler = ws.onmessage;\n ws.onmessage = (event: IMessageEvent) => {\n const message = JSON.parse(event.data);\n const [type, sid, data] = message;\n\n if (sid !== subId) {\n originalHandler?.call(ws, event);\n return;\n }\n\n if (type === 'EVENT') {\n events.push(data);\n } else if (type === 'EOSE') {\n clearTimeout(timeout);\n ws.onmessage = originalHandler;\n this.unsubscribeFromRelay(ws, subId);\n resolve(events);\n }\n };\n\n ws.send(JSON.stringify(['REQ', subId, filter]));\n });\n }\n\n private unsubscribeFromRelay(ws: IWebSocket, subId: string): void {\n if (ws.readyState === WebSocketReadyState.OPEN) {\n ws.send(JSON.stringify(['CLOSE', subId]));\n }\n }\n\n // ===========================================================================\n // Private: Subscriptions\n // ===========================================================================\n\n private subscribeToEvents(): void {\n if (!this.identity || !this.keyManager) return;\n\n const subId = 'main';\n // Use 32-byte Nostr pubkey (x-coordinate only), not 33-byte compressed key\n const nostrPubkey = this.keyManager.getPublicKeyHex();\n const filter: NostrFilter = {\n kinds: [\n EVENT_KINDS.DIRECT_MESSAGE,\n EVENT_KINDS.TOKEN_TRANSFER,\n EVENT_KINDS.PAYMENT_REQUEST,\n EVENT_KINDS.PAYMENT_REQUEST_RESPONSE,\n ],\n '#p': [nostrPubkey],\n since: Math.floor(Date.now() / 1000) - 86400, // Last 24h\n };\n\n const message = JSON.stringify(['REQ', subId, filter]);\n\n for (const ws of this.connections.values()) {\n if (ws.readyState === WebSocketReadyState.OPEN) {\n ws.send(message);\n }\n }\n\n this.subscriptions.set(subId, Array.from(this.connections.keys()));\n this.log('Subscribed to events');\n }\n\n private subscribeToTags(tags: string[]): void {\n const subId = `tags:${tags.join(':')}`;\n const filter: NostrFilter = {\n kinds: [EVENT_KINDS.BROADCAST],\n '#t': tags,\n since: Math.floor(Date.now() / 1000) - 3600, // Last hour\n };\n\n const message = JSON.stringify(['REQ', subId, filter]);\n\n for (const ws of this.connections.values()) {\n if (ws.readyState === WebSocketReadyState.OPEN) {\n ws.send(message);\n }\n }\n\n this.subscriptions.set(subId, Array.from(this.connections.keys()));\n }\n\n // ===========================================================================\n // Private: Encryption\n // ===========================================================================\n\n private async decryptContent(content: string, senderPubkey: string): Promise<string> {\n if (!this.keyManager) throw new Error('KeyManager not initialized');\n\n // Decrypt content using NIP-04 (using hex variant for string keys)\n const decrypted = await NIP04.decryptHex(\n content,\n this.keyManager.getPrivateKeyHex(),\n senderPubkey\n );\n\n // Strip known prefixes for compatibility with nostr-js-sdk\n return this.stripContentPrefix(decrypted);\n }\n\n /**\n * Strip known content prefixes (nostr-js-sdk compatibility)\n * Handles: payment_request:, token_transfer:, etc.\n */\n private stripContentPrefix(content: string): string {\n const prefixes = [\n 'payment_request:',\n 'token_transfer:',\n 'payment_response:',\n ];\n\n for (const prefix of prefixes) {\n if (content.startsWith(prefix)) {\n return content.slice(prefix.length);\n }\n }\n\n return content;\n }\n\n // ===========================================================================\n // Private: Helpers\n // ===========================================================================\n\n private ensureReady(): void {\n if (!this.isConnected()) {\n throw new Error('NostrTransportProvider not connected');\n }\n if (!this.identity) {\n throw new Error('Identity not set');\n }\n }\n\n private emitEvent(event: TransportEvent): void {\n for (const callback of this.eventCallbacks) {\n try {\n callback(event);\n } catch (error) {\n this.log('Event callback error:', error);\n }\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.config.debug) {\n console.log('[NostrTransportProvider]', ...args);\n }\n }\n}\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface NostrEvent {\n id: string;\n kind: number;\n content: string;\n tags: string[][];\n pubkey: string;\n created_at: number;\n sig: string;\n}\n\ninterface NostrFilter {\n ids?: string[];\n authors?: string[];\n kinds?: number[];\n '#p'?: string[];\n '#t'?: string[];\n '#d'?: string[];\n since?: number;\n until?: number;\n limit?: number;\n}\n","/**\n * WebSocket Abstraction\n * Platform-independent WebSocket interface for cross-platform support\n */\n\n// =============================================================================\n// WebSocket Interface\n// =============================================================================\n\n/**\n * Minimal WebSocket interface compatible with browser and Node.js\n */\nexport interface IWebSocket {\n readonly readyState: number;\n\n send(data: string): void;\n close(code?: number, reason?: string): void;\n\n onopen: ((event: unknown) => void) | null;\n onclose: ((event: unknown) => void) | null;\n onerror: ((event: unknown) => void) | null;\n onmessage: ((event: IMessageEvent) => void) | null;\n}\n\nexport interface IMessageEvent {\n data: string;\n}\n\n/**\n * WebSocket ready states (same as native WebSocket)\n */\nexport const WebSocketReadyState = {\n CONNECTING: 0,\n OPEN: 1,\n CLOSING: 2,\n CLOSED: 3,\n} as const;\n\n/**\n * Factory function to create WebSocket instances\n * Different implementations for browser (native) vs Node.js (ws package)\n */\nexport type WebSocketFactory = (url: string) => IWebSocket;\n\n// =============================================================================\n// UUID Generator\n// =============================================================================\n\n/**\n * Generate a unique ID (platform-independent)\n * Browser: crypto.randomUUID()\n * Node: crypto.randomUUID() or uuid package\n */\nexport type UUIDGenerator = () => string;\n\n/**\n * Default UUID generator using crypto.randomUUID\n * Works in modern browsers and Node 19+\n */\nexport function defaultUUIDGenerator(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback for older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","/**\n * SDK2 Constants\n * Default configuration values and storage keys\n */\n\n// =============================================================================\n// Storage Keys\n// =============================================================================\n\n/** Default prefix for all storage keys */\nexport const STORAGE_PREFIX = 'sphere_' as const;\n\n/**\n * Default encryption key for wallet data\n * WARNING: This is a placeholder. In production, use user-provided password.\n * This key is used when no password is provided to encrypt/decrypt mnemonic.\n */\nexport const DEFAULT_ENCRYPTION_KEY = 'sphere-default-key' as const;\n\n/** Storage keys for wallet data */\nexport const STORAGE_KEYS = {\n /** Encrypted BIP39 mnemonic */\n MNEMONIC: `${STORAGE_PREFIX}mnemonic`,\n /** Encrypted master private key */\n MASTER_KEY: `${STORAGE_PREFIX}master_key`,\n /** BIP32 chain code */\n CHAIN_CODE: `${STORAGE_PREFIX}chain_code`,\n /** HD derivation path (full path like m/44'/0'/0'/0/0) */\n DERIVATION_PATH: `${STORAGE_PREFIX}derivation_path`,\n /** Base derivation path (like m/44'/0'/0' without chain/index) */\n BASE_PATH: `${STORAGE_PREFIX}base_path`,\n /** Derivation mode: bip32, wif_hmac, legacy_hmac */\n DERIVATION_MODE: `${STORAGE_PREFIX}derivation_mode`,\n /** Wallet source: mnemonic, file, unknown */\n WALLET_SOURCE: `${STORAGE_PREFIX}wallet_source`,\n /** Wallet existence flag */\n WALLET_EXISTS: `${STORAGE_PREFIX}wallet_exists`,\n /** Registered nametag (legacy - single address) */\n NAMETAG: `${STORAGE_PREFIX}nametag`,\n /** Current active address index */\n CURRENT_ADDRESS_INDEX: `${STORAGE_PREFIX}current_address_index`,\n /** Address nametags map (JSON: { \"0\": \"alice\", \"1\": \"bob\" }) */\n ADDRESS_NAMETAGS: `${STORAGE_PREFIX}address_nametags`,\n /** Token data */\n TOKENS: `${STORAGE_PREFIX}tokens`,\n /** Pending transfers */\n PENDING_TRANSFERS: `${STORAGE_PREFIX}pending_transfers`,\n /** Transfer outbox */\n OUTBOX: `${STORAGE_PREFIX}outbox`,\n /** Conversations */\n CONVERSATIONS: `${STORAGE_PREFIX}conversations`,\n /** Messages */\n MESSAGES: `${STORAGE_PREFIX}messages`,\n /** Transaction history */\n TRANSACTION_HISTORY: `${STORAGE_PREFIX}transaction_history`,\n /** Archived tokens (spent token history) */\n ARCHIVED_TOKENS: `${STORAGE_PREFIX}archived_tokens`,\n /** Tombstones (records of deleted/spent tokens) */\n TOMBSTONES: `${STORAGE_PREFIX}tombstones`,\n /** Forked tokens (alternative histories) */\n FORKED_TOKENS: `${STORAGE_PREFIX}forked_tokens`,\n} as const;\n\n// =============================================================================\n// Nostr Defaults\n// =============================================================================\n\n/** Default Nostr relays */\nexport const DEFAULT_NOSTR_RELAYS = [\n 'wss://relay.unicity.network',\n 'wss://relay.damus.io',\n 'wss://nos.lol',\n 'wss://relay.nostr.band',\n] as const;\n\n/** Nostr event kinds used by SDK - must match @unicitylabs/nostr-js-sdk */\nexport const NOSTR_EVENT_KINDS = {\n /** NIP-04 encrypted direct message */\n DIRECT_MESSAGE: 4,\n /** Token transfer (Unicity custom - 31113) */\n TOKEN_TRANSFER: 31113,\n /** Payment request (Unicity custom - 31115) */\n PAYMENT_REQUEST: 31115,\n /** Payment request response (Unicity custom - 31116) */\n PAYMENT_REQUEST_RESPONSE: 31116,\n /** Nametag binding (NIP-78 app-specific data) */\n NAMETAG_BINDING: 30078,\n /** Public broadcast */\n BROADCAST: 1,\n} as const;\n\n// =============================================================================\n// Aggregator (Oracle) Defaults\n// =============================================================================\n\n/**\n * Default aggregator URL\n * Note: The aggregator is conceptually an oracle - a trusted service that provides\n * verifiable truth about token state through cryptographic inclusion proofs.\n */\nexport const DEFAULT_AGGREGATOR_URL = 'https://aggregator.unicity.network/rpc' as const;\n\n/** Dev aggregator URL */\nexport const DEV_AGGREGATOR_URL = 'https://dev-aggregator.dyndns.org/rpc' as const;\n\n/** Test aggregator URL (Goggregator) */\nexport const TEST_AGGREGATOR_URL = 'https://goggregator-test.unicity.network' as const;\n\n/** Default aggregator request timeout (ms) */\nexport const DEFAULT_AGGREGATOR_TIMEOUT = 30000;\n\n// =============================================================================\n// IPFS Defaults\n// =============================================================================\n\n/** Default IPFS gateways */\nexport const DEFAULT_IPFS_GATEWAYS = [\n 'https://ipfs.unicity.network',\n 'https://dweb.link',\n 'https://ipfs.io',\n] as const;\n\n/** Unicity IPFS bootstrap peers */\nexport const DEFAULT_IPFS_BOOTSTRAP_PEERS = [\n '/dns4/unicity-ipfs2.dyndns.org/tcp/4001/p2p/12D3KooWLNi5NDPPHbrfJakAQqwBqymYTTwMQXQKEWuCrJNDdmfh',\n '/dns4/unicity-ipfs3.dyndns.org/tcp/4001/p2p/12D3KooWQ4aujVE4ShLjdusNZBdffq3TbzrwT2DuWZY9H1Gxhwn6',\n '/dns4/unicity-ipfs4.dyndns.org/tcp/4001/p2p/12D3KooWJ1ByPfUzUrpYvgxKU8NZrR8i6PU1tUgMEbQX9Hh2DEn1',\n '/dns4/unicity-ipfs5.dyndns.org/tcp/4001/p2p/12D3KooWB1MdZZGHN5B8TvWXntbycfe7Cjcz7n6eZ9eykZadvmDv',\n] as const;\n\n// =============================================================================\n// Wallet Defaults\n// =============================================================================\n\n/** Default BIP32 base path (without chain/index) */\nexport const DEFAULT_BASE_PATH = \"m/44'/0'/0'\" as const;\n\n/** Default BIP32 derivation path (full path with chain/index) */\nexport const DEFAULT_DERIVATION_PATH = `${DEFAULT_BASE_PATH}/0/0` as const;\n\n/** Coin types */\nexport const COIN_TYPES = {\n /** ALPHA token (L1 blockchain) */\n ALPHA: 'ALPHA',\n /** Test token */\n TEST: 'TEST',\n} as const;\n\n// =============================================================================\n// L1 (ALPHA Blockchain) Defaults\n// =============================================================================\n\n/** Default Fulcrum electrum server for mainnet */\nexport const DEFAULT_ELECTRUM_URL = 'wss://fulcrum.alpha.unicity.network:50004' as const;\n\n/** Testnet Fulcrum electrum server */\nexport const TEST_ELECTRUM_URL = 'wss://fulcrum.alpha.testnet.unicity.network:50004' as const;\n\n// =============================================================================\n// Network Defaults\n// =============================================================================\n\n/** Testnet Nostr relays */\nexport const TEST_NOSTR_RELAYS = [\n 'wss://nostr-relay.testnet.unicity.network',\n] as const;\n\n/** Network configurations */\nexport const NETWORKS = {\n mainnet: {\n name: 'Mainnet',\n aggregatorUrl: DEFAULT_AGGREGATOR_URL,\n nostrRelays: DEFAULT_NOSTR_RELAYS,\n ipfsGateways: DEFAULT_IPFS_GATEWAYS,\n electrumUrl: DEFAULT_ELECTRUM_URL,\n },\n testnet: {\n name: 'Testnet',\n aggregatorUrl: TEST_AGGREGATOR_URL,\n nostrRelays: TEST_NOSTR_RELAYS,\n ipfsGateways: DEFAULT_IPFS_GATEWAYS,\n electrumUrl: TEST_ELECTRUM_URL,\n },\n dev: {\n name: 'Development',\n aggregatorUrl: DEV_AGGREGATOR_URL,\n nostrRelays: TEST_NOSTR_RELAYS,\n ipfsGateways: DEFAULT_IPFS_GATEWAYS,\n electrumUrl: TEST_ELECTRUM_URL,\n },\n} as const;\n\nexport type NetworkType = keyof typeof NETWORKS;\nexport type NetworkConfig = (typeof NETWORKS)[NetworkType];\n\n// =============================================================================\n// Timeouts & Limits\n// =============================================================================\n\n/** Default timeouts (ms) */\nexport const TIMEOUTS = {\n /** WebSocket connection timeout */\n WEBSOCKET_CONNECT: 10000,\n /** Nostr relay reconnect delay */\n NOSTR_RECONNECT_DELAY: 3000,\n /** Max reconnect attempts */\n MAX_RECONNECT_ATTEMPTS: 5,\n /** Proof polling interval */\n PROOF_POLL_INTERVAL: 1000,\n /** Sync interval */\n SYNC_INTERVAL: 60000,\n} as const;\n\n/** Validation limits */\nexport const LIMITS = {\n /** Min nametag length */\n NAMETAG_MIN_LENGTH: 3,\n /** Max nametag length */\n NAMETAG_MAX_LENGTH: 20,\n /** Max memo length */\n MEMO_MAX_LENGTH: 500,\n /** Max message length */\n MESSAGE_MAX_LENGTH: 10000,\n} as const;\n","/**\n * Node.js Oracle Exports\n * Re-exports shared oracle with Node.js-specific TrustBaseLoader\n */\n\nimport * as fs from 'fs';\nimport {\n UnicityAggregatorProvider,\n type UnicityAggregatorProviderConfig,\n} from '../../../oracle/UnicityAggregatorProvider';\nimport type { TrustBaseLoader } from '../../../oracle/oracle-provider';\n\n// Re-export shared types and classes\nexport {\n UnicityAggregatorProvider,\n type UnicityAggregatorProviderConfig,\n UnicityOracleProvider,\n type UnicityOracleProviderConfig,\n} from '../../../oracle/UnicityAggregatorProvider';\n\nexport type { TrustBaseLoader } from '../../../oracle/oracle-provider';\n\n// =============================================================================\n// Node.js TrustBase Loader\n// =============================================================================\n\n/**\n * Node.js TrustBase loader using fs\n */\nexport class NodeTrustBaseLoader implements TrustBaseLoader {\n private filePath: string;\n\n constructor(filePath: string = './trustbase-testnet.json') {\n this.filePath = filePath;\n }\n\n async load(): Promise<unknown | null> {\n try {\n if (fs.existsSync(this.filePath)) {\n const content = fs.readFileSync(this.filePath, 'utf-8');\n return JSON.parse(content);\n }\n } catch {\n // Ignore file errors\n }\n return null;\n }\n}\n\n/**\n * Create Node.js TrustBase loader\n */\nexport function createNodeTrustBaseLoader(filePath?: string): TrustBaseLoader {\n return new NodeTrustBaseLoader(filePath);\n}\n\n// =============================================================================\n// Node.js Factory\n// =============================================================================\n\n/**\n * Create UnicityAggregatorProvider with Node.js TrustBase loader\n */\nexport function createUnicityAggregatorProvider(\n config: Omit<UnicityAggregatorProviderConfig, 'trustBaseLoader'> & {\n trustBasePath?: string;\n }\n): UnicityAggregatorProvider {\n const { trustBasePath, ...restConfig } = config;\n return new UnicityAggregatorProvider({\n ...restConfig,\n trustBaseLoader: createNodeTrustBaseLoader(trustBasePath),\n });\n}\n\n/** @deprecated Use createUnicityAggregatorProvider instead */\nexport const createUnicityOracleProvider = createUnicityAggregatorProvider;\n","/**\n * Unicity Aggregator Provider\n * Platform-independent implementation using @unicitylabs/state-transition-sdk\n *\n * The oracle is a trusted service that provides verifiable truth\n * about token state through cryptographic inclusion proofs.\n *\n * TrustBaseLoader is injected for platform-specific loading:\n * - Browser: fetch from URL\n * - Node.js: read from file\n */\n\nimport type { ProviderStatus } from '../types';\nimport type {\n OracleProvider,\n TransferCommitment,\n SubmitResult,\n InclusionProof,\n WaitOptions,\n ValidationResult,\n TokenState,\n MintParams,\n MintResult,\n OracleEvent,\n OracleEventCallback,\n TrustBaseLoader,\n} from './oracle-provider';\nimport { DEFAULT_AGGREGATOR_TIMEOUT, TIMEOUTS } from '../constants';\n\n// SDK imports - using direct imports from the SDK\nimport { StateTransitionClient } from '@unicitylabs/state-transition-sdk/lib/StateTransitionClient';\nimport { AggregatorClient } from '@unicitylabs/state-transition-sdk/lib/api/AggregatorClient';\nimport { RootTrustBase } from '@unicitylabs/state-transition-sdk/lib/bft/RootTrustBase';\nimport { Token as SdkToken } from '@unicitylabs/state-transition-sdk/lib/token/Token';\nimport { waitInclusionProof } from '@unicitylabs/state-transition-sdk/lib/util/InclusionProofUtils';\nimport type { TransferCommitment as SdkTransferCommitment } from '@unicitylabs/state-transition-sdk/lib/transaction/TransferCommitment';\n\n// SDK MintCommitment type - using interface to avoid generic complexity\ninterface SdkMintCommitment {\n requestId?: { toString(): string };\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Configuration\n// =============================================================================\n\nexport interface UnicityAggregatorProviderConfig {\n /** Aggregator URL */\n url: string;\n /** API key for authentication */\n apiKey?: string;\n /** Request timeout (ms) */\n timeout?: number;\n /** Skip trust base verification (dev only) */\n skipVerification?: boolean;\n /** Enable debug logging */\n debug?: boolean;\n /** Trust base loader (platform-specific) */\n trustBaseLoader?: TrustBaseLoader;\n}\n\n// =============================================================================\n// RPC Response Types\n// =============================================================================\n\ninterface RpcSubmitResponse {\n requestId?: string;\n}\n\ninterface RpcProofResponse {\n proof?: unknown;\n roundNumber?: number;\n}\n\ninterface RpcValidateResponse {\n valid?: boolean;\n spent?: boolean;\n stateHash?: string;\n error?: string;\n}\n\ninterface RpcSpentResponse {\n spent?: boolean;\n}\n\ninterface RpcTokenStateResponse {\n state?: {\n stateHash?: string;\n spent?: boolean;\n roundNumber?: number;\n };\n}\n\ninterface RpcMintResponse {\n requestId?: string;\n tokenId?: string;\n}\n\n// =============================================================================\n// Implementation\n// =============================================================================\n\n/**\n * Unicity Aggregator Provider\n * Concrete implementation of OracleProvider using Unicity's aggregator service\n */\nexport class UnicityAggregatorProvider implements OracleProvider {\n readonly id = 'unicity-aggregator';\n readonly name = 'Unicity Aggregator';\n readonly type = 'network' as const;\n readonly description = 'Unicity state transition aggregator (oracle implementation)';\n\n private config: Required<Omit<UnicityAggregatorProviderConfig, 'trustBaseLoader'>> & {\n trustBaseLoader?: TrustBaseLoader;\n };\n private status: ProviderStatus = 'disconnected';\n private eventCallbacks: Set<OracleEventCallback> = new Set();\n\n // SDK clients\n private aggregatorClient: AggregatorClient | null = null;\n private stateTransitionClient: StateTransitionClient | null = null;\n private trustBase: RootTrustBase | null = null;\n\n /** Get the current trust base */\n getTrustBase(): RootTrustBase | null {\n return this.trustBase;\n }\n\n /** Get the state transition client */\n getStateTransitionClient(): StateTransitionClient | null {\n return this.stateTransitionClient;\n }\n\n /** Get the aggregator client */\n getAggregatorClient(): AggregatorClient | null {\n return this.aggregatorClient;\n }\n\n // Cache for spent states (immutable)\n private spentCache: Map<string, boolean> = new Map();\n\n constructor(config: UnicityAggregatorProviderConfig) {\n this.config = {\n url: config.url,\n apiKey: config.apiKey ?? '',\n timeout: config.timeout ?? DEFAULT_AGGREGATOR_TIMEOUT,\n skipVerification: config.skipVerification ?? false,\n debug: config.debug ?? false,\n trustBaseLoader: config.trustBaseLoader,\n };\n }\n\n // ===========================================================================\n // BaseProvider Implementation\n // ===========================================================================\n\n async connect(): Promise<void> {\n if (this.status === 'connected') return;\n\n this.status = 'connecting';\n\n // Mark as connected - actual connectivity will be verified on first operation\n // The aggregator requires requestId in params even for status checks,\n // which the SDK client doesn't support directly\n this.status = 'connected';\n this.emitEvent({ type: 'oracle:connected', timestamp: Date.now() });\n this.log('Connected to oracle:', this.config.url);\n }\n\n async disconnect(): Promise<void> {\n this.status = 'disconnected';\n this.emitEvent({ type: 'oracle:disconnected', timestamp: Date.now() });\n this.log('Disconnected from oracle');\n }\n\n isConnected(): boolean {\n return this.status === 'connected';\n }\n\n getStatus(): ProviderStatus {\n return this.status;\n }\n\n // ===========================================================================\n // OracleProvider Implementation\n // ===========================================================================\n\n async initialize(trustBase?: RootTrustBase): Promise<void> {\n // Initialize SDK clients with optional API key\n this.aggregatorClient = new AggregatorClient(\n this.config.url,\n this.config.apiKey || null\n );\n this.stateTransitionClient = new StateTransitionClient(this.aggregatorClient);\n\n if (trustBase) {\n this.trustBase = trustBase;\n } else if (!this.config.skipVerification && this.config.trustBaseLoader) {\n // Load trust base using injected loader\n try {\n const trustBaseJson = await this.config.trustBaseLoader.load();\n if (trustBaseJson) {\n this.trustBase = RootTrustBase.fromJSON(trustBaseJson);\n }\n } catch (error) {\n this.log('Failed to load trust base:', error);\n }\n }\n\n await this.connect();\n this.log('Initialized with trust base:', !!this.trustBase);\n }\n\n /**\n * Submit a transfer commitment to the aggregator.\n * Accepts either an SDK TransferCommitment or a simple commitment object.\n */\n async submitCommitment(commitment: TransferCommitment | SdkTransferCommitment): Promise<SubmitResult> {\n this.ensureConnected();\n\n try {\n let requestId: string;\n\n // Check if it's an SDK commitment (has submitTransferCommitment method signature)\n if (this.isSdkTransferCommitment(commitment)) {\n // Use SDK client directly\n const response = await this.stateTransitionClient!.submitTransferCommitment(commitment);\n requestId = commitment.requestId?.toString() ?? response.status;\n } else {\n // Fallback to RPC for simple commitment objects\n const response = await this.rpcCall<RpcSubmitResponse>('submitCommitment', {\n sourceToken: commitment.sourceToken,\n recipient: commitment.recipient,\n salt: Array.from(commitment.salt),\n data: commitment.data,\n });\n requestId = response.requestId ?? '';\n }\n\n this.emitEvent({\n type: 'commitment:submitted',\n timestamp: Date.now(),\n data: { requestId },\n });\n\n return {\n success: true,\n requestId,\n timestamp: Date.now(),\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMsg,\n timestamp: Date.now(),\n };\n }\n }\n\n /**\n * Submit a mint commitment to the aggregator (SDK only)\n * @param commitment - SDK MintCommitment instance\n */\n async submitMintCommitment(commitment: SdkMintCommitment): Promise<SubmitResult> {\n this.ensureConnected();\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const response = await this.stateTransitionClient!.submitMintCommitment(commitment as any);\n const requestId = commitment.requestId?.toString() ?? response.status;\n\n this.emitEvent({\n type: 'commitment:submitted',\n timestamp: Date.now(),\n data: { requestId },\n });\n\n return {\n success: true,\n requestId,\n timestamp: Date.now(),\n };\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMsg,\n timestamp: Date.now(),\n };\n }\n }\n\n private isSdkTransferCommitment(commitment: unknown): commitment is SdkTransferCommitment {\n return (\n commitment !== null &&\n typeof commitment === 'object' &&\n 'requestId' in commitment &&\n typeof (commitment as SdkTransferCommitment).requestId?.toString === 'function'\n );\n }\n\n async getProof(requestId: string): Promise<InclusionProof | null> {\n this.ensureConnected();\n\n try {\n const response = await this.rpcCall<RpcProofResponse>('getInclusionProof', { requestId });\n\n if (!response.proof) {\n return null;\n }\n\n return {\n requestId,\n roundNumber: response.roundNumber ?? 0,\n proof: response.proof,\n timestamp: Date.now(),\n };\n } catch {\n return null;\n }\n }\n\n async waitForProof(requestId: string, options?: WaitOptions): Promise<InclusionProof> {\n const timeout = options?.timeout ?? this.config.timeout;\n const pollInterval = options?.pollInterval ?? TIMEOUTS.PROOF_POLL_INTERVAL;\n const startTime = Date.now();\n let attempt = 0;\n\n while (Date.now() - startTime < timeout) {\n options?.onPoll?.(++attempt);\n\n const proof = await this.getProof(requestId);\n if (proof) {\n this.emitEvent({\n type: 'proof:received',\n timestamp: Date.now(),\n data: { requestId, roundNumber: proof.roundNumber },\n });\n return proof;\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new Error(`Timeout waiting for proof: ${requestId}`);\n }\n\n async validateToken(tokenData: unknown): Promise<ValidationResult> {\n this.ensureConnected();\n\n try {\n // Try SDK validation first if we have trust base\n if (this.trustBase && !this.config.skipVerification) {\n try {\n const sdkToken = await SdkToken.fromJSON(tokenData);\n const verifyResult = await sdkToken.verify(this.trustBase);\n\n // Calculate state hash\n const stateHash = await sdkToken.state.calculateHash();\n const stateHashStr = stateHash.toJSON();\n\n const valid = verifyResult.isSuccessful;\n\n this.emitEvent({\n type: 'validation:completed',\n timestamp: Date.now(),\n data: { valid },\n });\n\n return {\n valid,\n spent: false, // Spend check is separate\n stateHash: stateHashStr,\n error: valid ? undefined : 'SDK verification failed',\n };\n } catch (sdkError) {\n this.log('SDK validation failed, falling back to RPC:', sdkError);\n }\n }\n\n // Fallback to RPC validation\n const response = await this.rpcCall<RpcValidateResponse>('validateToken', { token: tokenData });\n\n const valid = response.valid ?? false;\n const spent = response.spent ?? false;\n\n this.emitEvent({\n type: 'validation:completed',\n timestamp: Date.now(),\n data: { valid },\n });\n\n // Cache spent state if spent\n if (response.stateHash && spent) {\n this.spentCache.set(response.stateHash, true);\n }\n\n return {\n valid,\n spent,\n stateHash: response.stateHash,\n error: response.error,\n };\n } catch (error) {\n return {\n valid: false,\n spent: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Wait for inclusion proof using SDK (for SDK commitments)\n */\n async waitForProofSdk(\n commitment: SdkTransferCommitment | SdkMintCommitment,\n signal?: AbortSignal\n ): Promise<unknown> {\n this.ensureConnected();\n\n if (!this.trustBase) {\n throw new Error('Trust base not initialized');\n }\n\n return await waitInclusionProof(\n this.trustBase,\n this.stateTransitionClient!,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n commitment as any,\n signal\n );\n }\n\n async isSpent(stateHash: string): Promise<boolean> {\n // Check cache first (spent is immutable)\n if (this.spentCache.has(stateHash)) {\n return this.spentCache.get(stateHash)!;\n }\n\n this.ensureConnected();\n\n try {\n const response = await this.rpcCall<RpcSpentResponse>('isSpent', { stateHash });\n const spent = response.spent ?? false;\n\n // Cache result\n if (spent) {\n this.spentCache.set(stateHash, true);\n }\n\n return spent;\n } catch {\n return false;\n }\n }\n\n async getTokenState(tokenId: string): Promise<TokenState | null> {\n this.ensureConnected();\n\n try {\n const response = await this.rpcCall<RpcTokenStateResponse>('getTokenState', { tokenId });\n\n if (!response.state) {\n return null;\n }\n\n return {\n tokenId,\n stateHash: response.state.stateHash ?? '',\n spent: response.state.spent ?? false,\n roundNumber: response.state.roundNumber,\n lastUpdated: Date.now(),\n };\n } catch {\n return null;\n }\n }\n\n async getCurrentRound(): Promise<number> {\n if (this.aggregatorClient) {\n const blockHeight = await this.aggregatorClient.getBlockHeight();\n return Number(blockHeight);\n }\n return 0;\n }\n\n async mint(params: MintParams): Promise<MintResult> {\n this.ensureConnected();\n\n try {\n const response = await this.rpcCall<RpcMintResponse>('mint', {\n coinId: params.coinId,\n amount: params.amount,\n recipientAddress: params.recipientAddress,\n recipientPubkey: params.recipientPubkey,\n });\n\n return {\n success: true,\n requestId: response.requestId,\n tokenId: response.tokenId,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n // ===========================================================================\n // Event Subscription\n // ===========================================================================\n\n onEvent(callback: OracleEventCallback): () => void {\n this.eventCallbacks.add(callback);\n return () => this.eventCallbacks.delete(callback);\n }\n\n // ===========================================================================\n // Private: RPC\n // ===========================================================================\n\n private async rpcCall<T>(method: string, params: unknown): Promise<T> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(this.config.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: Date.now(),\n method,\n params,\n }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const result = await response.json();\n\n if (result.error) {\n throw new Error(result.error.message ?? 'RPC error');\n }\n\n return (result.result ?? {}) as T;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n // ===========================================================================\n // Private: Helpers\n // ===========================================================================\n\n private ensureConnected(): void {\n if (this.status !== 'connected') {\n throw new Error('UnicityAggregatorProvider not connected');\n }\n }\n\n private emitEvent(event: OracleEvent): void {\n for (const callback of this.eventCallbacks) {\n try {\n callback(event);\n } catch (error) {\n this.log('Event callback error:', error);\n }\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.config.debug) {\n console.log('[UnicityAggregatorProvider]', ...args);\n }\n }\n}\n\n// =============================================================================\n// Backward Compatibility Aliases (Oracle -> Aggregator)\n// =============================================================================\n\n/** @deprecated Use UnicityAggregatorProvider instead */\nexport const UnicityOracleProvider = UnicityAggregatorProvider;\n/** @deprecated Use UnicityAggregatorProviderConfig instead */\nexport type UnicityOracleProviderConfig = UnicityAggregatorProviderConfig;\n","/**\n * Configuration Resolvers\n * Utility functions for resolving provider configurations with extend/override pattern\n */\n\nimport { NETWORKS, type NetworkType, type NetworkConfig } from '../../constants';\nimport type {\n BaseTransportConfig,\n BaseOracleConfig,\n L1Config,\n ResolvedTransportConfig,\n ResolvedOracleConfig,\n} from './config';\n\n// =============================================================================\n// Network Resolution\n// =============================================================================\n\n/**\n * Get network configuration by type\n */\nexport function getNetworkConfig(network: NetworkType = 'mainnet'): NetworkConfig {\n return NETWORKS[network];\n}\n\n// =============================================================================\n// Transport Resolution\n// =============================================================================\n\n/**\n * Resolve transport configuration with extend/override pattern\n *\n * Priority:\n * 1. `relays` - replaces defaults entirely\n * 2. `additionalRelays` - extends network defaults\n * 3. Network defaults\n *\n * @example\n * ```ts\n * // Use network defaults\n * resolveTransportConfig('testnet', undefined);\n *\n * // Replace relays entirely\n * resolveTransportConfig('testnet', { relays: ['wss://custom.relay'] });\n *\n * // Extend defaults\n * resolveTransportConfig('testnet', { additionalRelays: ['wss://extra.relay'] });\n * ```\n */\nexport function resolveTransportConfig(\n network: NetworkType,\n config?: BaseTransportConfig & { reconnectDelay?: number; maxReconnectAttempts?: number }\n): ResolvedTransportConfig {\n const networkConfig = getNetworkConfig(network);\n\n // Resolve relays with extend/override pattern\n let relays: string[];\n if (config?.relays) {\n // Explicit relays - replace entirely\n relays = config.relays;\n } else {\n // Start with network defaults\n relays = [...networkConfig.nostrRelays] as string[];\n // Add additional relays if specified\n if (config?.additionalRelays) {\n relays = [...relays, ...config.additionalRelays];\n }\n }\n\n return {\n relays,\n timeout: config?.timeout,\n autoReconnect: config?.autoReconnect,\n debug: config?.debug,\n // Browser-specific\n reconnectDelay: config?.reconnectDelay,\n maxReconnectAttempts: config?.maxReconnectAttempts,\n };\n}\n\n// =============================================================================\n// Oracle Resolution\n// =============================================================================\n\n/**\n * Resolve oracle configuration with override pattern\n *\n * Uses network default URL if not explicitly provided\n *\n * @example\n * ```ts\n * // Use network default\n * resolveOracleConfig('testnet', undefined);\n *\n * // Override URL\n * resolveOracleConfig('testnet', { url: 'https://custom.aggregator' });\n * ```\n */\nexport function resolveOracleConfig(\n network: NetworkType,\n config?: BaseOracleConfig & { trustBasePath?: string }\n): ResolvedOracleConfig {\n const networkConfig = getNetworkConfig(network);\n\n return {\n url: config?.url ?? networkConfig.aggregatorUrl,\n apiKey: config?.apiKey,\n timeout: config?.timeout,\n skipVerification: config?.skipVerification,\n debug: config?.debug,\n // Node.js-specific\n trustBasePath: config?.trustBasePath,\n };\n}\n\n// =============================================================================\n// L1 Resolution\n// =============================================================================\n\n/**\n * Resolve L1 configuration with override pattern\n *\n * Only returns config if l1 is explicitly provided (L1 is optional)\n *\n * @example\n * ```ts\n * // No L1 config - returns undefined\n * resolveL1Config('testnet', undefined);\n *\n * // Enable L1 with defaults\n * resolveL1Config('testnet', {});\n *\n * // Override electrum URL\n * resolveL1Config('testnet', { electrumUrl: 'wss://custom.fulcrum:50004' });\n * ```\n */\nexport function resolveL1Config(\n network: NetworkType,\n config?: L1Config\n): L1Config | undefined {\n if (config === undefined) {\n return undefined;\n }\n\n const networkConfig = getNetworkConfig(network);\n\n return {\n electrumUrl: config.electrumUrl ?? networkConfig.electrumUrl,\n defaultFeeRate: config.defaultFeeRate,\n enableVesting: config.enableVesting,\n };\n}\n\n// =============================================================================\n// Array Extension Helper\n// =============================================================================\n\n/**\n * Resolve array with extend/override pattern\n *\n * @param defaults - Default values from network config\n * @param replace - Values that replace defaults entirely\n * @param additional - Values to add to defaults\n * @returns Resolved array\n *\n * @example\n * ```ts\n * // Use defaults\n * resolveArrayConfig(['a', 'b'], undefined, undefined); // ['a', 'b']\n *\n * // Replace\n * resolveArrayConfig(['a', 'b'], ['x'], undefined); // ['x']\n *\n * // Extend\n * resolveArrayConfig(['a', 'b'], undefined, ['c']); // ['a', 'b', 'c']\n * ```\n */\nexport function resolveArrayConfig<T>(\n defaults: readonly T[],\n replace?: T[],\n additional?: T[]\n): T[] {\n if (replace) {\n return replace;\n }\n\n const result = [...defaults];\n if (additional) {\n return [...result, ...additional];\n }\n\n return result;\n}\n"],"mappings":"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","names":["fs","path","NostrEventClass","WebSocket","fs","SdkToken","valid"]}
|