Skip to content

Commit a3c3c1e

Browse files
feat: add GET /pay/.address for pod deposit address
Generates a keypair on first use, returns a taproot deposit address. Phase 1 of JavaScriptSolidServer#267.
1 parent 79b4c03 commit a3c3c1e

1 file changed

Lines changed: 29 additions & 1 deletion

File tree

src/handlers/pay.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,30 @@
2828
import crypto from 'crypto';
2929
import { getNostrPubkey, pubkeyToDidNostr } from '../auth/nostr.js';
3030
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';
3232
import { loadTrail, transferToken } from '../token.js';
33+
import { secp256k1 } from '@noble/curves/secp256k1';
34+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
3335
import fs from 'fs-extra';
3436
import path from 'path';
3537

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+
3655
const DEFAULT_COST = 1; // satoshis per request
3756

3857
// --- Chain registry for multi-chain deposits ---
@@ -244,6 +263,15 @@ export function createPayHandler(options = {}) {
244263
return reply.send(info);
245264
}
246265

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+
247275
// --- GET /pay/.balance ---
248276
if (url === '/pay/.balance' && request.method === 'GET') {
249277
const pubkey = await getNostrPubkey(request);

0 commit comments

Comments
 (0)