diff options
| author | Adam Soltys <[email protected]> | 2026-02-16 11:51:41 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-02-16 11:51:41 -0800 |
| commit | ee0513838b1d336fa60eb9a8f7ca1ce43e6d9e40 (patch) | |
| tree | 04d097d676c4c0a48287f631a539b4055522dcfe /routes | |
| parent | 20cee249905ee6975e88089b76b2eccb4019e19a (diff) | |
| download | coinos-server-ee0513838b1d336fa60eb9a8f7ca1ce43e6d9e40.tar.gz coinos-server-ee0513838b1d336fa60eb9a8f7ca1ce43e6d9e40.zip | |
passkey auth
Diffstat (limited to 'routes')
| -rw-r--r-- | routes/payments.ts | 31 | ||||
| -rw-r--r-- | routes/users.ts | 58 |
2 files changed, 88 insertions, 1 deletions
diff --git a/routes/payments.ts b/routes/payments.ts index 4bdd0d30..c77da697 100644 --- a/routes/payments.ts +++ b/routes/payments.ts @@ -933,8 +933,9 @@ export default { async arkSync(req, res) { try { const { user } = req; - const { transactions, aid } = req.body; + const { transactions = [], aid } = req.body; const { id: uid } = user; + l("arkSync", user.username, aid, "txs:", transactions.length, "bal:", req.body.balance); // Per-account lock prevents concurrent syncs from racing const lockKey = `arksynclock:${aid}`; @@ -1003,6 +1004,34 @@ export default { } } + // Reconcile expired VTXOs + const { balance } = req.body; + if (typeof balance === "number" && balance >= 0) { + const paymentIds = await db.lRange(`${aid}:payments`, 0, -1); + let expectedBalance = 0; + for (const pid of paymentIds) { + const pay = await g(`payment:${pid}`); + if (pay) expectedBalance += pay.amount; + } + + if (expectedBalance > balance) { + const p = await createArkPayment({ + aid, + uid, + amount: balance - expectedBalance, + hash: `expired-${Date.now()}`, + rate, + currency, + created: Date.now(), + extraHashMappings: [], + }); + p.memo = "expired"; + await s(`payment:${p.id}`, p); + payments.push(p); + synced++; + } + } + // Check for pending custodial ark invoice to forward let forward; if (received > 0) { diff --git a/routes/users.ts b/routes/users.ts index 904a5bb0..8d67444d 100644 --- a/routes/users.ts +++ b/routes/users.ts @@ -6,6 +6,12 @@ import { db, g, ga, gf, s, scan } from "$lib/db"; import { err, l, warn } from "$lib/logging"; import { mail, templates } from "$lib/mail"; import { getNostrUser, getProfile, serverPubkey2 } from "$lib/nostr"; +import { + generatePasskeyRegistration, + verifyPasskeyRegistration, + generatePasskeyLogin, + verifyPasskeyLogin, +} from "$lib/passkey"; import register from "$lib/register"; import { emit } from "$lib/sockets"; import upload from "$lib/upload"; @@ -1164,6 +1170,58 @@ export default { res.send({}); }, + async passkeyRegisterOptions(req, res) { + try { + const { user } = req; + const origin = req.body.origin || `https://${config.hostname}`; + const options = await generatePasskeyRegistration(user, origin); + res.send(options); + } catch (e) { + console.log(e); + bail(res, e.message); + } + }, + + async passkeyRegisterVerify(req, res) { + try { + const { user } = req; + const origin = req.body.origin || `https://${config.hostname}`; + const credential = await verifyPasskeyRegistration(user, req.body, origin); + if (!user.passkeys) user.passkeys = []; + user.passkeys.push(credential); + await s(`user:${user.id}`, user); + res.send({ ok: true }); + } catch (e) { + console.log(e); + bail(res, e.message); + } + }, + + async passkeyLoginOptions(req, res) { + try { + const origin = req.body.origin || `https://${config.hostname}`; + const options = await generatePasskeyLogin(origin); + res.send(options); + } catch (e) { + console.log(e); + bail(res, e.message); + } + }, + + async passkeyLoginVerify(req, res) { + try { + const { credential, challengeId, origin: reqOrigin } = req.body; + const origin = reqOrigin || `https://${config.hostname}`; + const user = await verifyPasskeyLogin(credential, challengeId, origin); + const payload = { id: user.id }; + const token = jwt.sign(payload, config.jwt); + res.send({ user: pick(user, whitelist), token }); + } catch (e) { + console.log(e); + bail(res, e.message); + } + }, + async credits(req, res) { const { id } = req.user; const bitcoin = await getCredit(id, "bitcoin"); |
