|
28 | 28 | import crypto from 'crypto'; |
29 | 29 | import { getNostrPubkey, pubkeyToDidNostr } from '../auth/nostr.js'; |
30 | 30 | import { readLedger, writeLedger, getBalance, credit, debit } from '../webledger.js'; |
31 | | -import { verifyMrc20Deposit, verifyMrc20Anchor, jcs, sha256Hex } from '../mrc20.js'; |
| 31 | +import { verifyMrc20Deposit, verifyMrc20Anchor, jcs, sha256Hex, btAddress } from '../mrc20.js'; |
32 | 32 | import { loadTrail, transferToken } from '../token.js'; |
| 33 | +import { secp256k1 } from '@noble/curves/secp256k1'; |
| 34 | +import { bytesToHex, hexToBytes } from '@noble/hashes/utils'; |
33 | 35 | import fs from 'fs-extra'; |
34 | 36 | import path from 'path'; |
35 | 37 |
|
| 38 | +// --- Pod keypair for deposit addresses --- |
| 39 | +const keypairFile = () => path.join(process.env.DATA_ROOT || './data', '.well-known/webledgers/keypair.json'); |
| 40 | + |
| 41 | +async function loadOrCreateKeypair() { |
| 42 | + try { |
| 43 | + const data = await fs.readFile(keypairFile(), 'utf8'); |
| 44 | + return JSON.parse(data); |
| 45 | + } catch { |
| 46 | + const privkey = secp256k1.utils.randomPrivateKey(); |
| 47 | + const pubkey = secp256k1.getPublicKey(privkey, true); |
| 48 | + const kp = { privkey: bytesToHex(privkey), pubkey: bytesToHex(pubkey) }; |
| 49 | + await fs.ensureDir(path.dirname(keypairFile())); |
| 50 | + await fs.writeFile(keypairFile(), JSON.stringify(kp, null, 2)); |
| 51 | + return kp; |
| 52 | + } |
| 53 | +} |
| 54 | + |
36 | 55 | const DEFAULT_COST = 1; // satoshis per request |
37 | 56 |
|
38 | 57 | // --- Chain registry for multi-chain deposits --- |
@@ -244,6 +263,15 @@ export function createPayHandler(options = {}) { |
244 | 263 | return reply.send(info); |
245 | 264 | } |
246 | 265 |
|
| 266 | + // --- GET /pay/.address — public deposit address --- |
| 267 | + if (url === '/pay/.address' && request.method === 'GET') { |
| 268 | + const kp = await loadOrCreateKeypair(); |
| 269 | + const chain = request.query?.chain || (payChains ? payChains[0] : 'tbtc4'); |
| 270 | + const network = chain === 'btc' ? 'mainnet' : (chain === 'tbtc3' ? 'testnet' : 'testnet4'); |
| 271 | + const address = btAddress(kp.pubkey, [], network); |
| 272 | + return reply.send({ address, chain, pubkey: kp.pubkey }); |
| 273 | + } |
| 274 | + |
247 | 275 | // --- GET /pay/.balance --- |
248 | 276 | if (url === '/pay/.balance' && request.method === 'GET') { |
249 | 277 | const pubkey = await getNostrPubkey(request); |
|
0 commit comments