diff --git a/neode-ui/mock-backend.js b/neode-ui/mock-backend.js index 75b4ae66..313557b2 100755 --- a/neode-ui/mock-backend.js +++ b/neode-ui/mock-backend.js @@ -223,6 +223,25 @@ function seedMockState() { return { analyticsEnabled: false, nodeVisibility: 'discoverable', + nostrDiscovery: true, + pendingPeerRequests: [ + { + id: 'preq-demo-1', + from_nostr_pubkey: '7e2a9c4b1d8f3a6c5e0b9d2f7a4c1e8b3d6f9a2c5e8b1d4f7a0c3e6b9d2f5a8c', + from_nostr_npub: 'npub1demo0inbound0request0xyzq', + from_did: 'did:key:z6MkwPn5xQc8vT2sLb6eRu9dYf3gHa7mJzK1oDiW4nXvE8tq', + from_name: 'basement-node', + message: 'Hey — saw your node on the relay, mind if we peer?', + received_at: new Date(Date.now() - 45 * 60000).toISOString(), + state: 'pending', + outbound: false, + }, + ], + tollgateEnabled: true, + tollgatePrice: 21, + tollgateStepMs: 60000, + tollgateMinSteps: 5, + tollgateMint: 'https://mint.archy.demo', cashuMints: [ 'https://mint.minibits.cash/Bitcoin', 'https://stablenut.umint.cash', @@ -2447,6 +2466,9 @@ app.post('/rpc/v1', (req, res) => { nodes: [ { did: 'did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2ReMkBe4bR6XBIDNq9', onion: 'disc1abc2def3ghi4jkl5mno6pqr7stu8vwx9yz.onion', pubkey: 'disc1pub', node_address: '192.168.1.50' }, { did: 'did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH', onion: 'disc2xyz9wvu8tsr7qpo6nml5kji4hgf3edc2ba.onion', pubkey: 'disc2pub', node_address: '192.168.1.51' }, + { did: 'did:key:z6MkfV2sQpXm4d8YtR1nWc7uHb3eKj9gLa5xPzD6oTiN8rEw', onion: 'disc3mn04pq15rs26tu37vw48xy59za60bc71de.onion', pubkey: 'disc3pub', node_address: '192.168.1.72' }, + { did: 'did:key:z6MkrJ8pWx2yNc5vT9qLb4eHu7dKf1gMa3sPzE6oXiQ8nRvw', onion: 'disc4fg82hi93jk04lm15no26pq37rs48tu59vw.onion', pubkey: 'disc4pub', node_address: '100.72.19.44' }, + { did: 'did:key:z6MkhT4wQn8xPc2vL6sRb9eYu3dJf7gKa1mNzD5oWiE8tXvq', onion: 'disc5xy60za71bc82de93fg04hi15jk26lm37no.onion', pubkey: 'disc5pub', node_address: '100.101.7.23' }, ], }, }) @@ -3665,6 +3687,134 @@ app.post('/rpc/v1', (req, res) => { return res.json({ result: { node_id: nodeId, history } }) } + // ── OpenWRT / TollGate gateway (demo: a thoroughly-used gateway) ── + case 'openwrt.get-status': { + return res.json({ + result: { + host: '192.168.8.1', + hostname: 'archy-tollgate', + uptime_secs: 19 * 86400 + 7 * 3600 + 42 * 60, + release: { + openwrt_release: 'OpenWrt 24.10.1', + openwrt_version: 'r28597-0425664679', + openwrt_board_name: 'glinet,gl-mt3000', + openwrt_arch: 'aarch64_cortex-a53', + openwrt_target: 'mediatek/filogic', + }, + tollgate: { + installed: true, + enabled: mockState.tollgateEnabled, + metric: 'milliseconds', + step_size_ms: mockState.tollgateStepMs, + price_per_step: mockState.tollgatePrice, + min_steps: mockState.tollgateMinSteps, + currency: 'sat', + mint_url: mockState.tollgateMint, + }, + wifi_interfaces: [ + { section: 'default_radio0', ssid: 'TollGate-⚡-2.4G', device: 'radio0', encryption: 'none', network: 'lan', disabled: false }, + { section: 'default_radio1', ssid: 'TollGate-⚡-5G', device: 'radio1', encryption: 'none', network: 'lan', disabled: false }, + { section: 'wifinet2', ssid: 'Archy-Private', device: 'radio1', encryption: 'sae', network: 'lan', disabled: false }, + ], + wan: { + configured: true, + ssid: 'CasaDelSol-5G', + assoc_ssid: 'CasaDelSol-5G', + encryption: 'psk2', + ip: '192.168.1.187', + internet: true, + radio0_disabled: false, + sta_iface: 'wifinet1', + sta_state: 'COMPLETED', + wifi_log: 'wlan1: associated -> COMPLETED (RSSI -52 dBm)', + lan_ip: '172.16.0.1', + lan_netmask: '255.255.255.0', + dhcp_start: '100', + dhcp_limit: '150', + masq: true, + }, + }, + }) + } + case 'openwrt.scan': { + return res.json({ result: { routers: ['192.168.8.1'] } }) + } + case 'openwrt.scan-wifi': { + return res.json({ + result: { + networks: [ + { ssid: 'CasaDelSol-5G', bssid: 'a4:3e:51:0b:77:21', signal: -52, channel: 44, encryption: 'psk2' }, + { ssid: 'CasaDelSol', bssid: 'a4:3e:51:0b:77:20', signal: -49, channel: 6, encryption: 'psk2' }, + { ssid: 'Vodafone-B221', bssid: '5c:35:3b:9a:12:f0', signal: -71, channel: 1, encryption: 'psk2' }, + { ssid: 'cafe-guest', bssid: '10:27:f5:c4:88:3a', signal: -78, channel: 11, encryption: 'none' }, + ], + }, + }) + } + case 'openwrt.provision-tollgate': { + if (params?.price_per_step != null) mockState.tollgatePrice = params.price_per_step + if (params?.step_size_ms != null) mockState.tollgateStepMs = params.step_size_ms + if (params?.min_steps != null) mockState.tollgateMinSteps = params.min_steps + if (params?.mint_url) mockState.tollgateMint = params.mint_url + if (params?.enabled != null) mockState.tollgateEnabled = !!params.enabled + return res.json({ result: { ok: true } }) + } + case 'openwrt.configure-wan': { + return res.json({ result: { ok: true } }) + } + + // ── Nostr peer discovery (demo) ────────────────────────────────── + case 'nostr.discovery-status': { + return res.json({ result: { enabled: mockState.nostrDiscovery } }) + } + case 'nostr.set-discovery': { + mockState.nostrDiscovery = !!params?.enabled + return res.json({ result: { enabled: mockState.nostrDiscovery } }) + } + case 'handshake.discover': { + return res.json({ + result: { + nodes: [ + { nostr_pubkey: '8f1c9a2b7d4e6f0a3c5b8d1e4f7a0c3b6e9d2f5a8b1c4e7d0a3f6c9b2e5d8a1f', nostr_npub: 'npub13uwf52m04893s79hxc7fmz57jd60jz4kd3nk28h5t2rr3l2xkq0qte0mfz', did: 'did:key:z6MkfV2sQpXm4d8YtR1nWc7uHb3eKj9gLa5xPzD6oTiN8rEw', version: '1.7.99' }, + { nostr_pubkey: '2a4c6e8f0b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3a', nostr_npub: 'npub1z5jvknq0k8f7am7wp0946fmdxu2yjkzr8mfw2n0lqv4tksz3xy8s5c9m2d', did: 'did:key:z6MkrJ8pWx2yNc5vT9qLb4eHu7dKf1gMa3sPzE6oXiQ8nRvw', version: '1.7.99' }, + { nostr_pubkey: '5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d', nostr_npub: 'npub1t9k2vfmq7x8n3a5wj0c4bz6y1d8s2e7r5m9p0l3q6u4i8o2h7g1f5x9c3vk', did: 'did:key:z6MkhT4wQn8xPc2vL6sRb9eYu3dJf7gKa1mNzD5oWiE8tXvq', version: '1.7.98' }, + { nostr_pubkey: '9c1e3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e', nostr_npub: 'npub1w3e8rkmq2x7n9a4vj5c0bz1y6d3s8e2r7m4p9l0q5u8i3o6h2g7f1x4c9vs', did: 'did:key:z6MkgS9wPm3xNc7vK2sQb5eTu8dHf4gJa6mLzD1oXiR8nEvw', version: '1.7.99' }, + ], + }, + }) + } + case 'handshake.connect': { + const reqId = `preq-${Date.now()}` + mockState.pendingPeerRequests.push({ + id: reqId, + from_nostr_pubkey: params?.recipient_nostr_pubkey || 'unknown', + from_nostr_npub: 'npub1outbounddemo', + from_did: 'did:key:zOutboundDemo', + from_name: params?.name || null, + message: params?.message || null, + received_at: new Date().toISOString(), + state: 'pending', + outbound: true, + }) + return res.json({ result: { ok: true, sent_to: params?.recipient_nostr_pubkey || '', id: reqId } }) + } + case 'handshake.poll': { + return res.json({ result: { polled: 4, new_requests: [], applied_invites: [], rejected_outbound: [], skipped: [] } }) + } + case 'federation.list-pending-requests': { + return res.json({ result: { requests: mockState.pendingPeerRequests } }) + } + case 'federation.approve-request': { + const r = mockState.pendingPeerRequests.find((x) => x.id === params?.id) + if (r) r.state = 'approved' + return res.json({ result: { approved: true, id: params?.id || '' } }) + } + case 'federation.reject-request': { + const r = mockState.pendingPeerRequests.find((x) => x.id === params?.id) + if (r) r.state = 'rejected' + return res.json({ result: { rejected: true, id: params?.id || '' } }) + } + default: { console.log(`[RPC] Unknown method: ${method}`) return res.json({