// npub.cash-Abholung, Stufe 1: Quotes von npubx.cash listen (JWT via NIP-98). // Nutzung: node npc.js quotes | node npc.js user // Protokoll aus cashubtc/cdk crates/cdk-npubcash (selbst verifiziert, Wake 7). const { finalizeEvent } = require('nostr-tools'); const fs = require('fs'); const key = JSON.parse(fs.readFileSync(__dirname + '/nostr-key.json', 'utf8')); const sk = Uint8Array.from(Buffer.from(key.sk_hex, 'hex')); const BASE = 'https://npubx.cash'; function nip98(url, method) { const ev = finalizeEvent({ kind: 27235, created_at: Math.floor(Date.now() / 1000), tags: [['u', url], ['method', method]], content: '', }, sk); return Buffer.from(JSON.stringify(ev)).toString('base64'); } async function jwt() { const url = `${BASE}/api/v2/auth/nip98`; const r = await fetch(url, { headers: { Authorization: `Nostr ${nip98(url, 'GET')}`, Accept: 'application/json', }}); if (!r.ok) throw new Error(`auth ${r.status}: ${await r.text()}`); return (await r.json()).data.token; } async function apiGet(path, token) { const r = await fetch(`${BASE}${path}`, { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json', }}); const text = await r.text(); if (!r.ok) throw new Error(`${path} ${r.status}: ${text.slice(0, 300)}`); return JSON.parse(text); } (async () => { const cmd = process.argv[2] || 'quotes'; const token = await jwt(); if (cmd === 'user') { const url = `${BASE}/api/v2/user`; const r = await fetch(url, { headers: { Authorization: `Nostr ${nip98(url, 'GET')}`, Accept: 'application/json' } }); console.log(r.status, (await r.text()).slice(0, 500)); return; } const res = await apiGet('/api/v2/wallet/quotes?offset=0&limit=50', token); const qs = res.data.quotes; console.log(`Quotes: ${qs.length} (total ${res.metadata.total})`); for (const q of qs) { console.log(`- id=${q.id} amount=${q.amount} ${q.unit} state=${q.state} locked=${q.locked} paid_at=${q.paid_at} mint=${q.mint_url}`); } })().catch(e => { console.error('FEHLER:', e.message); process.exit(1); });