From ad7b09b43323d0ffc0a8ddabb43e4838a184c697 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 24 Feb 2026 13:18:42 -0800 Subject: formatting --- lib/app.ts | 4 +- lib/ark.ts | 29 ++------- lib/auth.ts | 3 +- lib/ecash.ts | 1 - lib/esplora.ts | 9 +-- lib/health.ts | 29 ++++----- lib/lightning.ts | 16 ++--- lib/ln.ts | 4 +- lib/locales/index.ts | 8 ++- lib/locations.ts | 5 +- lib/migrate.ts | 5 +- lib/nostr.ts | 27 +++----- lib/notes.ts | 47 ++++---------- lib/notifications.ts | 16 ++--- lib/nwc.ts | 138 +++++++++++++++++------------------------ lib/passkey.ts | 8 +-- lib/payments.ts | 171 ++++++++++++--------------------------------------- lib/rates.ts | 4 +- lib/register.ts | 7 ++- lib/sockets.ts | 13 ++-- lib/tb.ts | 40 +++--------- lib/upload.ts | 9 +-- lib/utils.ts | 17 ++--- lib/zmq.ts | 39 +++--------- 24 files changed, 190 insertions(+), 459 deletions(-) (limited to 'lib') diff --git a/lib/app.ts b/lib/app.ts index b8bcb610..da29d9fe 100644 --- a/lib/app.ts +++ b/lib/app.ts @@ -149,8 +149,6 @@ app.setErrorHandler((error, _, reply) => { } }); -app.setNotFoundHandler((_, reply) => - reply.code(404).type("text/html").send("Not Found"), -); +app.setNotFoundHandler((_, reply) => reply.code(404).type("text/html").send("Not Found")); export default app; diff --git a/lib/ark.ts b/lib/ark.ts index ad708b7f..6558a74a 100644 --- a/lib/ark.ts +++ b/lib/ark.ts @@ -2,13 +2,7 @@ import { EventSource } from "eventsource"; if (!globalThis.EventSource) globalThis.EventSource = EventSource; import config from "$config"; -import { - SingleKey, - Wallet, - Ramps, - RestArkProvider, - VtxoManager, -} from "@arkade-os/sdk"; +import { SingleKey, Wallet, Ramps, RestArkProvider, VtxoManager } from "@arkade-os/sdk"; import { l, warn } from "$lib/logging"; let wallet: any; @@ -31,9 +25,7 @@ const failedBoardingOutpoints = new Set(); const withTimeout = (promise: Promise, ms: number, label: string) => Promise.race([ promise, - new Promise((_, reject) => - setTimeout(() => reject(new Error(`${label} timed out`)), ms), - ), + new Promise((_, reject) => setTimeout(() => reject(new Error(`${label} timed out`)), ms)), ]); export const refreshArkWallet = async (force = false) => { @@ -58,11 +50,7 @@ export const refreshArkWallet = async (force = false) => { // Recover swept/expired VTXOs if (balance.recoverable > 0) { try { - const txid = await withTimeout( - manager.recoverVtxos(), - 60_000, - "ark recovery", - ); + const txid = await withTimeout(manager.recoverVtxos(), 60_000, "ark recovery"); l("ark recovered swept vtxos, txid:", txid); } catch (e: any) { warn("ark vtxo recovery failed:", e.message); @@ -74,11 +62,7 @@ export const refreshArkWallet = async (force = false) => { const expiring = await manager.getExpiringVtxos(); if (expiring.length > 0) { l("ark renewing", expiring.length, "expiring vtxos"); - const txid = await withTimeout( - manager.renewVtxos(), - 60_000, - "ark renewal", - ); + const txid = await withTimeout(manager.renewVtxos(), 60_000, "ark renewal"); l("ark renewed vtxos, txid:", txid); } } catch (e: any) { @@ -98,10 +82,7 @@ export const refreshArkWallet = async (force = false) => { const outpointKey = (u: any) => `${u.txid}:${u.vout}`; const sorted = [...confirmed] .filter((u: any) => !failedBoardingOutpoints.has(outpointKey(u))) - .sort( - (a: any, b: any) => - (b.status?.block_height || 0) - (a.status?.block_height || 0), - ); + .sort((a: any, b: any) => (b.status?.block_height || 0) - (a.status?.block_height || 0)); for (const utxo of sorted) { try { diff --git a/lib/auth.ts b/lib/auth.ts index 79c04e9d..c2eca6d4 100644 --- a/lib/auth.ts +++ b/lib/auth.ts @@ -50,8 +50,7 @@ export const jwtStrategy = new jwt.Strategy( let { id } = payload; const wl = { GET: ["/invoice", "/payments"], POST: ["/invoice"] }; - if (id.endsWith("-ro") && wl[m].some((p) => u.startsWith(p))) - id = id.slice(0, -3); + if (id.endsWith("-ro") && wl[m].some((p) => u.startsWith(p))) id = id.slice(0, -3); const user = await getUser(id); next(null, user); diff --git a/lib/ecash.ts b/lib/ecash.ts index bcd2b7f4..5a5776b5 100644 --- a/lib/ecash.ts +++ b/lib/ecash.ts @@ -13,7 +13,6 @@ import { getEncodedTokenV4, } from "@cashu/cashu-ts"; - const { URL } = process.env; const m = new CashuMint(config.mintUrl); const w = new CashuWallet(m); diff --git a/lib/esplora.ts b/lib/esplora.ts index 4fd81b32..d92fad0c 100644 --- a/lib/esplora.ts +++ b/lib/esplora.ts @@ -91,8 +91,7 @@ export const getTxHex = async (txid: string) => { // Address derivation const hdVersionsForKey = (pubkey: string) => { - if (pubkey.startsWith("tpub") || pubkey.startsWith("tprv")) - return REGTEST_VERSIONS; + if (pubkey.startsWith("tpub") || pubkey.startsWith("tprv")) return REGTEST_VERSIONS; // xpub/xprv use default BITCOIN_VERSIONS (mainnet) — pass undefined return undefined; }; @@ -136,11 +135,7 @@ export const parseDescriptor = (desc: string) => { return { fingerprint: match[1], pubkey: match[2] }; }; -export const findLastUsedIndex = async ( - pubkey: string, - fingerprint: string, - maxScan = 100, -) => { +export const findLastUsedIndex = async (pubkey: string, fingerprint: string, maxScan = 100) => { let lastUsed = -1; for (let i = 0; i < maxScan; i++) { const { address } = deriveAddress(pubkey, fingerprint, i, false); diff --git a/lib/health.ts b/lib/health.ts index c2e268c6..fbefa8fa 100644 --- a/lib/health.ts +++ b/lib/health.ts @@ -22,13 +22,16 @@ export function getHealthStatus() { function withTimeout(promise: Promise, ms: number, label: string): Promise { return new Promise((resolve, reject) => { - const timer = setTimeout( - () => reject(new Error(`${label} timed out after ${ms}ms`)), - ms, - ); + const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms); promise.then( - (v) => { clearTimeout(timer); resolve(v); }, - (e) => { clearTimeout(timer); reject(e); }, + (v) => { + clearTimeout(timer); + resolve(v); + }, + (e) => { + clearTimeout(timer); + reject(e); + }, ); }); } @@ -79,11 +82,7 @@ async function checkLightningHealth(): Promise { const errorCode = e?.code ?? e?.errno ?? "unknown"; const errorMsg = e?.message ?? String(e); - err( - `health check: FAILED after ${duration}ms`, - `code=${errorCode}`, - `error=${errorMsg}`, - ); + err(`health check: FAILED after ${duration}ms`, `code=${errorCode}`, `error=${errorMsg}`); if (e instanceof LightningUnavailableError) { err("health check: lightning RPC socket unavailable"); @@ -102,18 +101,14 @@ export async function runHealthCheck() { if (healthy) { if (consecutiveFailures > 0) { - l( - `health check: recovered after ${consecutiveFailures} consecutive failures`, - ); + l(`health check: recovered after ${consecutiveFailures} consecutive failures`); } consecutiveFailures = 0; lastSuccessTime = Date.now(); lastFailureReason = ""; } else { consecutiveFailures++; - warn( - `health check: failure ${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}`, - ); + warn(`health check: failure ${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}`); if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) { err( diff --git a/lib/lightning.ts b/lib/lightning.ts index 4824d9ab..a259b601 100644 --- a/lib/lightning.ts +++ b/lib/lightning.ts @@ -66,8 +66,7 @@ export async function listenForLightning() { handleZap(inv, pubkey); } } catch (e) { - if (!e.message.includes("Unexpected")) - warn("failed to handle zap", e.message); + if (!e.message.includes("Unexpected")) warn("failed to handle zap", e.message); } } @@ -88,11 +87,7 @@ export async function listenForLightning() { const errorCode = e?.code ?? e?.errno ?? "unknown"; const errorMsg = e?.message ?? String(e); - err( - `lightning listener: error waiting for invoice`, - `code=${errorCode}`, - `error=${errorMsg}` - ); + err(`lightning listener: error waiting for invoice`, `code=${errorCode}`, `error=${errorMsg}`); if (e instanceof LightningUnavailableError) { err("lightning listener: RPC socket unavailable"); @@ -103,7 +98,7 @@ export async function listenForLightning() { if (listenerRetries >= MAX_LISTENER_RETRIES) { err( `lightning listener: ${MAX_LISTENER_RETRIES} consecutive failures, ` + - `last error: ${errorMsg}` + `last error: ${errorMsg}`, ); err("lightning listener: exiting process to trigger container restart"); @@ -115,7 +110,7 @@ export async function listenForLightning() { warn( `lightning listener: retry ${listenerRetries}/${MAX_LISTENER_RETRIES} ` + - `in ${LISTENER_RETRY_DELAY / 1000}s` + `in ${LISTENER_RETRY_DELAY / 1000}s`, ); setTimeout(listenForLightning, LISTENER_RETRY_DELAY); } @@ -150,8 +145,7 @@ export async function replay(index) { handleZap(inv, pubkey); } } catch (e) { - if (!e.message.includes("Unexpected")) - warn("failed to handle zap", e.message); + if (!e.message.includes("Unexpected")) warn("failed to handle zap", e.message); } } diff --git a/lib/ln.ts b/lib/ln.ts index 0ef99fc5..b4bd148d 100644 --- a/lib/ln.ts +++ b/lib/ln.ts @@ -47,7 +47,7 @@ function lightningProxy(rpcPath: string) { if (isUnavailable(e)) { throw new LightningUnavailableError( - `Lightning RPC unavailable at ${rpcPath} (${e?.code ?? e?.errno ?? "error"})` + `Lightning RPC unavailable at ${rpcPath} (${e?.code ?? e?.errno ?? "error"})`, ); } throw e; @@ -75,7 +75,7 @@ function lightningProxy(rpcPath: string) { } }; }, - } + }, ); } diff --git a/lib/locales/index.ts b/lib/locales/index.ts index c3aaa7c8..c902a8d2 100644 --- a/lib/locales/index.ts +++ b/lib/locales/index.ts @@ -1,5 +1,7 @@ import fs from "fs"; -export default "ar,bn,de,el,en,es,fa,fr,hi,it,ja,ko,nl,pl,pt,ru,th,tr,zh".split(",").reduce((a, l) => { - a[l] = JSON.parse(fs.readFileSync(`lib/locales/${l}.json`)); +export default "ar,bn,de,el,en,es,fa,fr,hi,it,ja,ko,nl,pl,pt,ru,th,tr,zh" + .split(",") + .reduce((a, l) => { + a[l] = JSON.parse(fs.readFileSync(`lib/locales/${l}.json`)); return a; -}, {}); + }, {}); diff --git a/lib/locations.ts b/lib/locations.ts index 660645a8..91bc4599 100644 --- a/lib/locations.ts +++ b/lib/locations.ts @@ -6,10 +6,7 @@ import got from "got"; const dedup = (array) => Object.values( array.reduce((acc, obj) => { - if ( - !acc[obj.id] || - new Date(obj.updated_at) > new Date(acc[obj.id].updated_at) - ) { + if (!acc[obj.id] || new Date(obj.updated_at) > new Date(acc[obj.id].updated_at)) { acc[obj.id] = obj; } return acc; diff --git a/lib/migrate.ts b/lib/migrate.ts index d4bfd61a..e3cfa9bc 100644 --- a/lib/migrate.ts +++ b/lib/migrate.ts @@ -40,10 +40,7 @@ export const migrateAccounts = async () => { account.pubkey = parsed.pubkey; account.fingerprint = parsed.fingerprint; try { - account.nextIndex = await findLastUsedIndex( - parsed.pubkey, - parsed.fingerprint, - ); + account.nextIndex = await findLastUsedIndex(parsed.pubkey, parsed.fingerprint); } catch (e) { warn("account migration index scan skipped", key, e.message); account.nextIndex = account.nextIndex || 0; diff --git a/lib/nostr.ts b/lib/nostr.ts index 354f928b..bcb20ea1 100644 --- a/lib/nostr.ts +++ b/lib/nostr.ts @@ -12,13 +12,9 @@ import { Relay } from "nostr-tools/relay"; export const EX = 60 * 60 * 24; const coinos = await Relay.connect(config.nostr); -export const serverSecret = bytesToHex( - nip19.decode(config.nostrKey).data as Uint8Array, -); +export const serverSecret = bytesToHex(nip19.decode(config.nostrKey).data as Uint8Array); -export const serverSecret2 = bytesToHex( - nip19.decode(config.nostrKey2).data as Uint8Array, -); +export const serverSecret2 = bytesToHex(nip19.decode(config.nostrKey2).data as Uint8Array); export const serverPubkey = getPublicKey(hexToBytes(serverSecret)); export const serverPubkey2 = getPublicKey(hexToBytes(serverSecret2)); @@ -54,29 +50,21 @@ export async function handleZap(invoice, sender = undefined) { fail("No tags found"); } - const ptags = zapreq.tags.filter( - (t) => t?.length && t.length >= 2 && t[0] === "p", - ); + const ptags = zapreq.tags.filter((t) => t?.length && t.length >= 2 && t[0] === "p"); if (ptags.length !== 1) { fail("None or multiple p tags found"); } - const etags = zapreq.tags.filter( - (t) => t?.length && t.length >= 2 && t[0] === "e", - ); + const etags = zapreq.tags.filter((t) => t?.length && t.length >= 2 && t[0] === "e"); if (!(etags.length === 0 || etags.length === 1)) { fail("Expected none or 1 e tags"); } - const atags = zapreq.tags.filter( - (t) => t?.length && t.length >= 2 && t[0] === "a", - ); + const atags = zapreq.tags.filter((t) => t?.length && t.length >= 2 && t[0] === "a"); - const relays_tag = zapreq.tags.find( - (t) => t?.length && t.length >= 2 && t[0] === "relays", - ); + const relays_tag = zapreq.tags.find((t) => t?.length && t.length >= 2 && t[0] === "relays"); if (!relays_tag) { fail("No relays tag found"); @@ -168,8 +156,7 @@ export const getCount = async (pubkey) => { if (follows === null) { const result = await get({ authors: [pubkey], kinds: [3] }); follows = result ? result.tags.filter((t) => t[0] === "p").length : 0; - if (follows?.length) - await db.set(`${pubkey}:follows:n`, JSON.stringify(follows), { EX }); + if (follows?.length) await db.set(`${pubkey}:follows:n`, JSON.stringify(follows), { EX }); } const k = `${pubkey}:followers:n`; diff --git a/lib/notes.ts b/lib/notes.ts index 84d157ee..6e8e6afc 100644 --- a/lib/notes.ts +++ b/lib/notes.ts @@ -20,8 +20,7 @@ const first = (list: any) => (list ? list[0] : undefined); export const fromNostrURI = (s: string) => s.replace(/^[\w+]+:\/?\/?/, ""); export const urlIsMedia = (url: string) => - !url.match(/\.(apk|docx|xlsx|csv|dmg)/) && - last(url.split("://"))?.includes("/"); + !url.match(/\.(apk|docx|xlsx|csv|dmg)/) && last(url.split("://"))?.includes("/"); type ContentArgs = { content: string; @@ -35,13 +34,10 @@ export type ParsedPart = { value: any; }; -export const isEmbeddableMedia = (url: string) => - isImage(url) || isVideo(url) || isAudio(url); +export const isEmbeddableMedia = (url: string) => isImage(url) || isVideo(url) || isAudio(url); -export const isImage = (url: string) => - url?.match(/^.*\.(jpg|jpeg|png|webp|gif|avif|svg)/gi); -export const isVideo = (url: string) => - url?.match(/^.*\.(mov|mkv|mp4|avi|m4v|webm)/gi); +export const isImage = (url: string) => url?.match(/^.*\.(jpg|jpeg|png|webp|gif|avif|svg)/gi); +export const isVideo = (url: string) => url?.match(/^.*\.(mov|mkv|mp4|avi|m4v|webm)/gi); export const isAudio = (url: string) => url?.match(/^.*\.(ogg|mp3|wav)/gi); /** @@ -70,9 +66,7 @@ export function groupContent(parts: ParsedPart[]): ParsedPart[] { parts.forEach((part, index) => { if ( part.type === LINK && - (isImage(part.value.url) || - isVideo(part.value.url) || - isAudio(part.value.url)) + (isImage(part.value.url) || isVideo(part.value.url) || isAudio(part.value.url)) ) { if (!buffer) { buffer = { @@ -87,8 +81,7 @@ export function groupContent(parts: ParsedPart[]): ParsedPart[] { for (const nextPart of parts.slice(index + 1)) { const isNewline = nextPart.type === NEWLINE; - const isBlankText = - nextPart.type === TEXT && nextPart.value.trim() === ""; + const isBlankText = nextPart.type === TEXT && nextPart.value.trim() === ""; const isLink = nextPart.type === LINK; // This is a noop, keep checking the next part @@ -114,11 +107,7 @@ export function groupContent(parts: ParsedPart[]): ParsedPart[] { return result; } -export const parseContent = ({ - content, - tags = [], - html = false, -}: ContentArgs): ParsedPart[] => { +export const parseContent = ({ content, tags = [], html = false }: ContentArgs): ParsedPart[] => { const result: ParsedPart[] = []; let text = content.trim(); let buffer = ""; @@ -174,9 +163,7 @@ export const parseContent = ({ const parseBech32 = () => { const bech32 = first( - text.match( - /^(web\+)?(nostr:)?\/?\/?n(event|ote|profile|pub|addr)1[\d\w]+/i, - ), + text.match(/^(web\+)?(nostr:)?\/?\/?n(event|ote|profile|pub|addr)1[\d\w]+/i), ); if (bech32) { @@ -211,9 +198,7 @@ export const parseContent = ({ }; const parseUrl = () => { - const raw = first( - text.match(/^([a-z+:]{2,30}:\/\/)?[^\s]+\.[a-z]{2,6}[^\s]*[^.!?,:\s]/gi), - ); + const raw = first(text.match(/^([a-z+:]{2,30}:\/\/)?[^\s]+\.[a-z]{2,6}[^\s]*[^.!?,:\s]/gi)); // Skip url if it's just the end of a filepath if (raw) { @@ -290,10 +275,7 @@ export const parseContent = ({ return result; }; -export const truncateContent = ( - content, - { showEntire, maxLength, showMedia = false }, -) => { +export const truncateContent = (content, { showEntire, maxLength, showMedia = false }) => { if (showEntire) { return content; } @@ -303,13 +285,8 @@ export const truncateContent = ( const truncateAt = maxLength * 0.6; content.every((part, i) => { - const isText = - [TOPIC, TEXT].includes(part.type) || - (part.type === LINK && !part.value.isMedia); - const isMedia = - part.type === INVOICE || - part.type.startsWith("nostr:") || - part.value.isMedia; + const isText = [TOPIC, TEXT].includes(part.type) || (part.type === LINK && !part.value.isMedia); + const isMedia = part.type === INVOICE || part.type.startsWith("nostr:") || part.value.isMedia; if (isText) { length += part.value.length; diff --git a/lib/notifications.ts b/lib/notifications.ts index d1e43392..261ad4bb 100644 --- a/lib/notifications.ts +++ b/lib/notifications.ts @@ -12,11 +12,7 @@ import { finalizeEvent, nip04 } from "nostr-tools"; import webpush from "web-push"; if (config.vapid) { - webpush.setVapidDetails( - `mailto:${config.support}`, - config.vapid.pk, - config.vapid.sk, - ); + webpush.setVapidDetails(`mailto:${config.support}`, config.vapid.pk, config.vapid.sk); } export const notify = async (p, user, withdrawal) => { @@ -62,12 +58,10 @@ export const notify = async (p, user, withdrawal) => { }; for (const s of subscriptions) { - webpush - .sendNotification(JSON.parse(s), JSON.stringify(payload)) - .catch((e) => { - warn("sub failed", e.message); - db.sRem(`${user.id}:subscriptions`, s); - }); + webpush.sendNotification(JSON.parse(s), JSON.stringify(payload)).catch((e) => { + warn("sub failed", e.message); + db.sRem(`${user.id}:subscriptions`, s); + }); } if (config.mqtt) { diff --git a/lib/nwc.ts b/lib/nwc.ts index 47b632f7..b635f665 100644 --- a/lib/nwc.ts +++ b/lib/nwc.ts @@ -3,13 +3,7 @@ import { archive, db, g, gf } from "$lib/db"; import { generate } from "$lib/invoices"; import ln from "$lib/ln"; import { err, l, warn } from "$lib/logging"; -import { - handleZap, - serverPubkey, - serverPubkey2, - serverSecret, - serverSecret2, -} from "$lib/nostr"; +import { handleZap, serverPubkey, serverPubkey2, serverSecret, serverSecret2 } from "$lib/nostr"; import { sendInternal, sendKeysend, sendLightning } from "$lib/payments"; import { getBalance } from "$lib/tb"; import { fail, getInvoice, sleep } from "$lib/utils"; @@ -89,64 +83,62 @@ export default () => { r.on("error", () => {}); r.on("event", async (sub, ev) => { - try { - if (sub !== "nwc") return; - const now = Math.floor(Date.now() / 1000); - if (ev.created_at && now - ev.created_at > nwcEventMaxAgeSeconds) return; - if (await db.zScore(handledKey, ev.id)) return; - - db.zAdd(handledKey, { score: now, value: ev.id }); - db.zRemRangeByScore(handledKey, 0, now - nwcEventMaxAgeSeconds); - const size = await db.zCard(handledKey); - if (size > handledMaxSize) { - await db.zRemRangeByRank(handledKey, 0, size - handledMaxSize - 1); - } - let { content, pubkey } = ev; - const pk = ev.tags.find((t) => t[0] === "p")[1]; - const sk = serverKeys[pk]; - const { params, method } = JSON.parse( - await nip04.decrypt(sk, pubkey, content), - ); - - // console.log("nwc", method, params, pubkey); - - if (!methods.includes(method)) return; - try { - const app = await g(`app:${pubkey}`); - if (!app) fail("pubkey not found"); - const user = await g(`user:${app.uid}`); - - const result = await handle(method, params, ev, app, user); - const payload = JSON.stringify({ result_type: method, ...result }); - content = await nip04.encrypt(sk, pubkey, payload); - - let response: UnsignedEvent = { - created_at: Math.floor(Date.now() / 1000), - kind: 23195, - pubkey: serverPubkey, - tags: [ - ["p", pubkey], - ["e", ev.id], - ], - content, - }; - - response = await finalizeEvent(response, hexToBytes(sk)); - r.send(["EVENT", response]); + if (sub !== "nwc") return; + const now = Math.floor(Date.now() / 1000); + if (ev.created_at && now - ev.created_at > nwcEventMaxAgeSeconds) return; + if (await db.zScore(handledKey, ev.id)) return; + + db.zAdd(handledKey, { score: now, value: ev.id }); + db.zRemRangeByScore(handledKey, 0, now - nwcEventMaxAgeSeconds); + const size = await db.zCard(handledKey); + if (size > handledMaxSize) { + await db.zRemRangeByRank(handledKey, 0, size - handledMaxSize - 1); + } + let { content, pubkey } = ev; + const pk = ev.tags.find((t) => t[0] === "p")[1]; + const sk = serverKeys[pk]; + const { params, method } = JSON.parse(await nip04.decrypt(sk, pubkey, content)); + + // console.log("nwc", method, params, pubkey); + + if (!methods.includes(method)) return; + + try { + const app = await g(`app:${pubkey}`); + if (!app) fail("pubkey not found"); + const user = await g(`user:${app.uid}`); + + const result = await handle(method, params, ev, app, user); + const payload = JSON.stringify({ result_type: method, ...result }); + content = await nip04.encrypt(sk, pubkey, payload); + + let response: UnsignedEvent = { + created_at: Math.floor(Date.now() / 1000), + kind: 23195, + pubkey: serverPubkey, + tags: [ + ["p", pubkey], + ["e", ev.id], + ], + content, + }; + + response = await finalizeEvent(response, hexToBytes(sk)); + r.send(["EVENT", response]); + } catch (e) { + // err( + // "problem with nwc", + // pubkey, + // method, + // JSON.stringify(params), + // e.message, + // ); + } } catch (e) { - // err( - // "problem with nwc", - // pubkey, - // method, - // JSON.stringify(params), - // e.message, - // ); + // err("problem with nwc", e.message); } - } catch (e) { - // err("problem with nwc", e.message); - } - }); + }); } connect(); @@ -171,9 +163,7 @@ const handle = (method, params, ev, app, user) => const pids = await db.lRange(`${pubkey}:payments`, 0, -1); let payments = await Promise.all(pids.map((pid) => g(`payment:${pid}`))); - payments = payments.filter( - (p) => p?.created > Date.now() - periods[budget_renewal], - ); + payments = payments.filter((p) => p?.created > Date.now() - periods[budget_renewal]); const spent = payments.reduce( (a, b) => @@ -186,14 +176,7 @@ const handle = (method, params, ev, app, user) => ); if (!created) { - warn( - "old nwc token", - pubkey, - user?.username, - spent, - amount, - max_amount, - ); + warn("old nwc token", pubkey, user?.username, spent, amount, max_amount); return error({ code: "UNAUTHORIZED", message: `This NWC connection is no longer valid please create a new one at https://coinos.io/settings/nostr`, @@ -344,11 +327,7 @@ const handle = (method, params, ev, app, user) => expiry, }; - const { - hash, - created: created_at, - paymentHash, - } = await generate({ invoice, user }); + const { hash, created: created_at, paymentHash } = await generate({ invoice, user }); return result({ type: "incoming", @@ -401,8 +380,7 @@ const handle = (method, params, ev, app, user) => const { pays } = await ln.listpays({ bolt11: invoice, payment_hash }); - if (!pays.length) - return error({ code: "NOT_FOUND", message: "Invoice not found" }); + if (!pays.length) return error({ code: "NOT_FOUND", message: "Invoice not found" }); const { amount_msat: amount, diff --git a/lib/passkey.ts b/lib/passkey.ts index b2cb96b4..29b9b095 100644 --- a/lib/passkey.ts +++ b/lib/passkey.ts @@ -4,9 +4,7 @@ import { generateAuthenticationOptions, verifyAuthenticationResponse, } from "@simplewebauthn/server"; -import type { - AuthenticatorTransportFuture, -} from "@simplewebauthn/types"; +import type { AuthenticatorTransportFuture } from "@simplewebauthn/types"; import { db, g, s } from "$lib/db"; import { fail, getUser } from "$lib/utils"; import { v4 } from "uuid"; @@ -102,9 +100,7 @@ export async function verifyPasskeyLogin(response: any, challengeId: string, ori if (!user) fail("User not found"); const passkeys = user.passkeys || []; - const passkey = passkeys.find( - (p: any) => p.credentialID === response.id, - ); + const passkey = passkeys.find((p: any) => p.credentialID === response.id); if (!passkey) fail("Passkey not found"); const expectedChallenge = await db.get(`challenge:passkey:${challengeId}`); diff --git a/lib/payments.ts b/lib/payments.ts index 8fee1a26..841beac5 100644 --- a/lib/payments.ts +++ b/lib/payments.ts @@ -134,34 +134,16 @@ export const debit = async ({ }) => { amount = Number.parseInt(amount); - const whitelisted = await db.sIsMember( - "whitelist", - user?.username?.toLowerCase().trim(), - ); + const whitelisted = await db.sIsMember("whitelist", user?.username?.toLowerCase().trim()); - const blacklisted = await db.sIsMember( - "blacklist", - user?.username?.toLowerCase().trim(), - ); + const blacklisted = await db.sIsMember("blacklist", user?.username?.toLowerCase().trim()); const serverLimit = await g(`${type}:limit`); const userLimit = await g("limit"); - const frozen = - (await g("hardfreeze")) || - ((await g("freeze")) && type !== PaymentType.internal); + const frozen = (await g("hardfreeze")) || ((await g("freeze")) && type !== PaymentType.internal); if (frozen || (amount > userLimit && !whitelisted) || amount > serverLimit) { - warn( - "Blocking", - user.username, - amount, - hash, - user.id, - type, - frozen, - userLimit, - serverLimit, - ); + warn("Blocking", user.username, amount, hash, user.id, type, frozen, userLimit, serverLimit); fail("Problem sending payment"); } @@ -184,8 +166,7 @@ export const debit = async ({ ref = invoice.uid; - const equivalentRate = - invoice.rate * (rates[currency] / rates[invoice.currency]); + const equivalentRate = invoice.rate * (rates[currency] / rates[invoice.currency]); if (Math.abs(invoice.rate / rates[invoice.currency] - 1) < 0.01) { rate = equivalentRate; @@ -201,17 +182,12 @@ export const debit = async ({ let creditType = type; if (creditType === PaymentType.bolt12) creditType = PaymentType.lightning; - let ourfee: any = [ - PaymentType.bitcoin, - PaymentType.liquid, - PaymentType.lightning, - ].includes(type) + let ourfee: any = [PaymentType.bitcoin, PaymentType.liquid, PaymentType.lightning].includes(type) ? Math.round((amount + fee + tip) * config.fee[creditType]) : 0; if (aid !== uid) ourfee = 0; - const frozenBalance = - !blacklisted || whitelisted ? 0 : await getBalance(uid); + const frozenBalance = !blacklisted || whitelisted ? 0 : await getBalance(uid); ourfee = await tbDebit( aid, @@ -334,8 +310,7 @@ export const credit = async ({ items: undefined, }; - if ([PaymentType.bitcoin, PaymentType.liquid].includes(type)) - inv.pending += amount; + if ([PaymentType.bitcoin, PaymentType.liquid].includes(type)) inv.pending += amount; else { inv.received += amount; inv.preimage = ref; @@ -506,9 +481,7 @@ const pay = async ({ aid = undefined, amount, to, user }) => { if (URL.includes(domain)) to = name; lnurl = `https://${domain}/.well-known/lnurlp/${name}`; } else if (to.startsWith("lnurl")) { - lnurl = Buffer.from( - bech32.fromWords(bech32.decode(to, 20000).words), - ).toString(); + lnurl = Buffer.from(bech32.fromWords(bech32.decode(to, 20000).words)).toString(); } const recipient = await getUser(to); @@ -552,8 +525,7 @@ const pay = async ({ aid = undefined, amount, to, user }) => { const localInv = await getInvoice(to).catch(() => null); if (localInv) { const recipient = await getUser(localInv.uid); - if (recipient) - return sendInternal({ amount, invoice: localInv, recipient, sender: user }); + if (recipient) return sendInternal({ amount, invoice: localInv, recipient, sender: user }); } } @@ -568,9 +540,12 @@ const pay = async ({ aid = undefined, amount, to, user }) => { const { id: source } = await ln.getinfo(); const { offer_issuer_id } = await ln.decode(to); const { routes } = await ln.getroutes( - source, offer_issuer_id, amount * 1000, + source, + offer_issuer_id, + amount * 1000, ["auto.localchans", "auto.sourcefree"], - Math.round(amount * 0.02) * 1000, 6, + Math.round(amount * 0.02) * 1000, + 6, ); fee = routes.length ? Math.max(5, Math.round((routes[0].path[0].amount_msat - routes[0].amount_msat) / 1000)) @@ -627,12 +602,8 @@ const sendNonCustodial = async (params) => { // Build set of own addresses for change detection const ownAddresses = new Set(); for (let i = 0; i <= nextIndex; i++) { - ownAddresses.add( - deriveAddress(account.pubkey, account.fingerprint, i, false).address, - ); - ownAddresses.add( - deriveAddress(account.pubkey, account.fingerprint, i, true).address, - ); + ownAddresses.add(deriveAddress(account.pubkey, account.fingerprint, i, false).address); + ownAddresses.add(deriveAddress(account.pubkey, account.fingerprint, i, true).address); } let totalIn = 0; @@ -704,8 +675,7 @@ export const sendOnchain = async (params) => { inflight[txid] = true; if (!signed) { - if (config[type].walletpass) - await node.walletPassphrase(config[type].walletpass, 300); + if (config[type].walletpass) await node.walletPassphrase(config[type].walletpass, 300); ({ hex } = await node.signRawTransactionWithWallet( type === PaymentType.liquid ? await node.blindRawTransaction(hex) : hex, @@ -825,13 +795,7 @@ export const sendKeysend = async ({ } }; -export const sendLightning = async ({ - user, - pr, - amount, - fee = undefined, - memo = undefined, -}) => { +export const sendLightning = async ({ user, pr, amount, fee = undefined, memo = undefined }) => { let p; if (typeof amount !== "undefined") { @@ -842,8 +806,7 @@ export const sendLightning = async ({ } } - let { type, invoice_amount_msat, amount_msat, invoice_node_id, payee } = - await ln.decode(pr); + let { type, invoice_amount_msat, amount_msat, invoice_node_id, payee } = await ln.decode(pr); if (type.includes("bolt12")) { amount_msat = invoice_amount_msat; payee = invoice_node_id; @@ -857,11 +820,9 @@ export const sendLightning = async ({ if (fee < 0) fail("Fee cannot be negative"); const { pays } = await ln.listpays(pr); - if (pays.find((p) => p.status === "complete")) - fail("Invoice has already been paid"); + if (pays.find((p) => p.status === "complete")) fail("Invoice has already been paid"); - if (pays.find((p) => p.status === "pending")) - fail("Payment is already underway"); + if (pays.find((p) => p.status === "pending")) fail("Payment is already underway"); p = await debit({ hash: pr, @@ -941,23 +902,16 @@ const getAddressType = async (a) => { } }; -const buildNonCustodial = async ({ - aid, - amount, - address, - feeRate, - subtract, - user, -}) => { +const buildNonCustodial = async ({ aid, amount, address, feeRate, subtract, user }) => { const account = await g(`account:${aid}`); if (!account?.pubkey) fail("account missing pubkey"); amount = Number.parseInt(amount); if (amount < 0) fail("invalid amount"); - const fees: any = await fetch( - `${api[PaymentType.bitcoin]}/fees/recommended`, - ).then((r) => r.json()); + const fees: any = await fetch(`${api[PaymentType.bitcoin]}/fees/recommended`).then((r) => + r.json(), + ); fees.hourFee = fees.halfHourFee; fees.halfHourFee = fees.fastestFee; @@ -969,18 +923,8 @@ const buildNonCustodial = async ({ const nextIndex = account.nextIndex || 0; // Derive all used external + internal addresses and fetch UTXOs - const externalAddrs = deriveAddresses( - account.pubkey, - account.fingerprint, - nextIndex + 1, - false, - ); - const internalAddrs = deriveAddresses( - account.pubkey, - account.fingerprint, - nextIndex + 1, - true, - ); + const externalAddrs = deriveAddresses(account.pubkey, account.fingerprint, nextIndex + 1, false); + const internalAddrs = deriveAddresses(account.pubkey, account.fingerprint, nextIndex + 1, true); const allAddrs = [...externalAddrs, ...internalAddrs]; const rawUtxos = await getAddressUtxos(allAddrs); @@ -989,26 +933,14 @@ const buildNonCustodial = async ({ // Build address-to-path lookup const addrToPath = {}; for (let i = 0; i <= nextIndex; i++) { - const { address: extAddr } = deriveAddress( - account.pubkey, - account.fingerprint, - i, - false, - ); + const { address: extAddr } = deriveAddress(account.pubkey, account.fingerprint, i, false); addrToPath[extAddr] = `m/0/${i}`; - const { address: intAddr } = deriveAddress( - account.pubkey, - account.fingerprint, - i, - true, - ); + const { address: intAddr } = deriveAddress(account.pubkey, account.fingerprint, i, true); addrToPath[intAddr] = `m/1/${i}`; } // Convert esplora UTXOs to selectUTXO input format - const keyVersions = account.pubkey.startsWith("tpub") - ? hdVersions - : undefined; + const keyVersions = account.pubkey.startsWith("tpub") ? hdVersions : undefined; const accountKey = HDKey.fromExtendedKey(account.pubkey, keyVersions); const utxoInputs = rawUtxos.map((u) => { @@ -1072,12 +1004,8 @@ const buildNonCustodial = async ({ // Build input metadata for client signing const inputs = selected.inputs.map((input) => { const inputTxid = - typeof input.txid === "string" - ? input.txid - : Buffer.from(input.txid).toString("hex"); - const utxo = rawUtxos.find( - (u) => u.txid === inputTxid && u.vout === input.index, - ); + typeof input.txid === "string" ? input.txid : Buffer.from(input.txid).toString("hex"); + const utxo = rawUtxos.find((u) => u.txid === inputTxid && u.vout === input.index); const path = utxo ? addrToPath[utxo.address] : undefined; return { witnessUtxo: { @@ -1093,14 +1021,7 @@ const buildNonCustodial = async ({ return { feeRate, ourfee, fee, fees, hex, inputs, subtract }; }; -export const build = async ({ - aid, - amount, - address, - feeRate, - subtract, - user, -}) => { +export const build = async ({ aid, amount, address, feeRate, subtract, user }) => { const type = await getAddressType(address); if (!aid) aid = user.id; @@ -1138,8 +1059,7 @@ export const build = async ({ let outs = [{ [address]: btc(amount) }]; - if (type === PaymentType.liquid) - outs = outs.map((o) => ({ ...o, asset: config.liquid.btc })); + if (type === PaymentType.liquid) outs = outs.map((o) => ({ ...o, asset: config.liquid.btc })); let raw = await node.createRawTransaction([], outs, 0, replaceable); @@ -1168,9 +1088,7 @@ export const build = async ({ if (subtract || amount + fee + ourfee > balance) { subtract = true; if (amount <= fee + ourfee + dust) { - fail( - `insufficient funds ⚡️${balance} of ⚡️${amount + fee + ourfee + dust}`, - ); + fail(`insufficient funds ⚡️${balance} of ⚡️${amount + fee + ourfee + dust}`); } outs = [{ [address]: btc(amount - ourfee) }]; @@ -1269,9 +1187,7 @@ export const importAccountHistory = async (account) => { const addressSet = new Set(allAddrs); const utxos = await getAddressUtxos(allAddrs); - const confirmedUtxos = utxos.filter( - (u) => u.status.confirmed && u.value >= 300, - ); + const confirmedUtxos = utxos.filter((u) => u.status.confirmed && u.value >= 300); const total = confirmedUtxos.reduce((sum, u) => sum + u.value, 0); const rates = await g("rates"); @@ -1294,9 +1210,7 @@ export const importAccountHistory = async (account) => { continue; } - const created = u.status?.block_time - ? u.status.block_time * 1000 - : Date.now(); + const created = u.status?.block_time ? u.status.block_time * 1000 : Date.now(); const p = { id: v4(), aid: id, @@ -1371,9 +1285,7 @@ export const importAccountHistory = async (account) => { if (amount <= 0) continue; const fee = Math.max(0, totalIn - totalOut); - const created = tx.status?.block_time - ? tx.status.block_time * 1000 - : Date.now(); + const created = tx.status?.block_time ? tx.status.block_time * 1000 : Date.now(); const p = { id: v4(), @@ -1409,7 +1321,6 @@ export const importAccountHistory = async (account) => { } }; - export const check = async () => { if (process.env.URL.includes("dev")) return; try { @@ -1495,9 +1406,7 @@ const reverse = async (p) => { const freezeCheck = async () => { const funds = await ln.listfunds(); - const lnbalance = Math.round( - funds.channels.reduce((a, b) => a + b.our_amount_msat, 0) / 1000, - ); + const lnbalance = Math.round(funds.channels.reduce((a, b) => a + b.our_amount_msat, 0) / 1000); const bcbalance = Math.round((await bc.getBalance()) * SATS); const { bitcoin } = await lq.getBalance(); diff --git a/lib/rates.ts b/lib/rates.ts index dcb44464..74dfa50d 100644 --- a/lib/rates.ts +++ b/lib/rates.ts @@ -27,9 +27,7 @@ const connect = async () => { try { rates.IRT = ( - (await got( - "https://api.nobitex.ir/v2/orderbook/BTCIRT", - ).json()) as any + (await got("https://api.nobitex.ir/v2/orderbook/BTCIRT").json()) as any ).lastTradePrice; } catch (e) {} diff --git a/lib/register.ts b/lib/register.ts index e99238b1..ac1997db 100644 --- a/lib/register.ts +++ b/lib/register.ts @@ -19,8 +19,7 @@ export default async (user, ip) => { const reserved = ["ecash"]; if (!username) fail("Username required"); username = username.toLowerCase().replace(/\s/g, ""); - if (!valid.test(username)) - fail("Usernames can only have letters and numbers"); + if (!valid.test(username)) fail("Usernames can only have letters and numbers"); if (reserved.includes(username)) fail("Invalid username"); if (username.includes("undefined")) fail("Invalid username"); @@ -41,7 +40,9 @@ export default async (user, ip) => { if (config.ipregistry) { try { const { - location: { country: { code } }, + location: { + country: { code }, + }, }: any = await got( `https://api.ipregistry.co/${ip}?key=${config.ipregistry}&fields=location.country.code`, ).json(); diff --git a/lib/sockets.ts b/lib/sockets.ts index 2e1c98e9..88817728 100644 --- a/lib/sockets.ts +++ b/lib/sockets.ts @@ -120,12 +120,8 @@ Bun.serve({ await track(ws, data); } catch (e) { - if (e.message.includes("not found")) - ws.send(JSON.stringify({ type: "logout" })); - setTimeout( - () => ws?.close(code, `closing due to error ${e.message}`), - 1000, - ); + if (e.message.includes("not found")) ws.send(JSON.stringify({ type: "logout" })); + setTimeout(() => ws?.close(code, `closing due to error ${e.message}`), 1000); } break; case "token": @@ -139,7 +135,7 @@ Bun.serve({ subscriptions.push({ invoice: data, ws }); break; default: - // warn("received socket message of unknown type", type, data); + // warn("received socket message of unknown type", type, data); } }, open(ws: any) { @@ -158,8 +154,7 @@ Bun.serve({ } let i; - ~(i = subscriptions.findIndex((s) => s.ws.id === id)) && - subscriptions.splice(i, 1); + ~(i = subscriptions.findIndex((s) => s.ws.id === id)) && subscriptions.splice(i, 1); if (all[id]) delete all[id]; } catch (e) { diff --git a/lib/tb.ts b/lib/tb.ts index ae1ac576..29411fef 100644 --- a/lib/tb.ts +++ b/lib/tb.ts @@ -1,11 +1,6 @@ import config from "$config"; import { warn } from "$lib/logging"; -import { - createClient, - CreateAccountError, - AccountFlags, - TransferFlags, -} from "tigerbeetle-node"; +import { createClient, CreateAccountError, AccountFlags, TransferFlags } from "tigerbeetle-node"; import { createHash } from "crypto"; let client: any; @@ -231,10 +226,7 @@ export async function tbDebit( let coveredMicro = 0n; if (ourfee > 0 && creditType && creditLedger[creditType]) { const creditAcct = await getAccount( - creditId( - uid === aid ? uid : "00000000-0000-0000-0000-000000000000", - creditType, - ), + creditId(uid === aid ? uid : "00000000-0000-0000-0000-000000000000", creditType), ); const creditBalMicro = accountBalanceMicro(creditAcct); const ourfeeMicro = BigInt(ourfee) * MSATS; @@ -349,9 +341,7 @@ export async function tbCredit( // Add fee credit if applicable - MICROSATS for sub-satoshi precision! // e.g., 2% of 10 sats = 0.2 sats = 200,000 microsats (accumulates over time) if (creditType && creditLedger[creditType] && config.fee[creditType]) { - const creditAmountMicro = BigInt( - Math.round(amount * MSATS_NUM * config.fee[creditType]), - ); + const creditAmountMicro = BigInt(Math.round(amount * MSATS_NUM * config.fee[creditType])); if (creditAmountMicro > 0n) { transfers.push({ id: nextTransferId(), @@ -421,11 +411,7 @@ export async function tbConfirm(aid: string, amount: number) { } } -export async function tbReverse( - uid: string, - total: number, - creditAmount: number, -) { +export async function tbReverse(uid: string, total: number, creditAmount: number) { const transfers: any[] = []; const linked = TransferFlags.linked; @@ -650,11 +636,7 @@ export async function tbFundCredit(name: string, amount: number) { } } -export async function tbFundDebit( - name: string, - amount: number, - errMsg: string, -): Promise { +export async function tbFundDebit(name: string, amount: number, errMsg: string): Promise { const transfers = [ { id: nextTransferId(), @@ -700,11 +682,7 @@ export async function tbMultiplyForMicrosats(uid: string): Promise { const MULTIPLIER = 999999n; // Adding this turns X into X*1000000 let count = 0; - const multiplyAccount = async ( - accountId: bigint, - ledger: number, - houseId: bigint, - ) => { + const multiplyAccount = async (accountId: bigint, ledger: number, houseId: bigint) => { const acct = await client.lookupAccounts([u128(accountId)]); if (!acct.length) return; const current = acct[0].credits_posted - acct[0].debits_posted; @@ -736,11 +714,7 @@ export async function tbMultiplyForMicrosats(uid: string): Promise { await multiplyAccount(balId, LEDGER_SATS, HOUSE_SATS); await multiplyAccount(pendId, LEDGER_SATS, HOUSE_SATS); await multiplyAccount(creditId(uid, "bitcoin"), LEDGER_CREDIT_BTC, HOUSE_BTC); - await multiplyAccount( - creditId(uid, "lightning"), - LEDGER_CREDIT_LN, - HOUSE_LN, - ); + await multiplyAccount(creditId(uid, "lightning"), LEDGER_CREDIT_LN, HOUSE_LN); await multiplyAccount(creditId(uid, "liquid"), LEDGER_CREDIT_LQ, HOUSE_LQ); return count; diff --git a/lib/upload.ts b/lib/upload.ts index 7b5ad86d..2ed5d905 100644 --- a/lib/upload.ts +++ b/lib/upload.ts @@ -16,15 +16,10 @@ export default async (req, res) => { const [format, ext] = (await fileTypeFromBuffer(buf)).mime.split("/"); - if (format !== "image" && !["jpg", "jpeg", "png"].includes(ext)) - fail("unsupported file type"); + if (format !== "image" && !["jpg", "jpeg", "png"].includes(ext)) fail("unsupported file type"); const w = type === "banner" ? 1920 : 240; - buf = await sharp(buf, { failOnError: false }) - .rotate() - .resize(w) - .webp() - .toBuffer(); + buf = await sharp(buf, { failOnError: false }).rotate().resize(w).webp().toBuffer(); const hash = createHash("sha256").update(buf).digest("hex"); diff --git a/lib/utils.ts b/lib/utils.ts index 878ef037..7a3d4c13 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -49,7 +49,7 @@ export const bip21 = (address, { amount, memo, tip, type }) => { export const getAccount = async (id) => { return g(`account:${id}`); -} +}; export const getUser = async (username, fields = undefined) => { if (username === "undefined") fail("invalid user"); @@ -121,22 +121,17 @@ export function formatReceipt(items, currency) { }; } const maxLineWidth = 32; - const { quantityColumnWidth, priceColumnWidth } = - calculateColumnWidths(items); + const { quantityColumnWidth, priceColumnWidth } = calculateColumnWidths(items); const nameColumnWidth = maxLineWidth - quantityColumnWidth - priceColumnWidth; return items .map((item) => { const quantityStr = String(item.quantity).padEnd(quantityColumnWidth); - const priceStr = f(item.price * item.quantity, currency).padStart( - priceColumnWidth, - ); + const priceStr = f(item.price * item.quantity, currency).padStart(priceColumnWidth); const nameLines = wrapText(item.name, nameColumnWidth); // Construct the full line(s) with the first line including the price - const fullLines = [ - `${quantityStr}${nameLines[0].padEnd(nameColumnWidth)}${priceStr}`, - ]; + const fullLines = [`${quantityStr}${nameLines[0].padEnd(nameColumnWidth)}${priceStr}`]; // Add any additional name lines, properly indented for (let i = 1; i < nameLines.length; i++) { fullLines.push(" ".repeat(quantityColumnWidth) + nameLines[i]); @@ -162,9 +157,7 @@ export const time = (() => { })(); export const fmt = (sats) => - `⚡️${new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format( - sats, - )}`; + `⚡️${new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format(sats)}`; export const link = (id) => `${URL}/payment/${id}`; diff --git a/lib/zmq.ts b/lib/zmq.ts index 09f5a4ba..bce898d4 100644 --- a/lib/zmq.ts +++ b/lib/zmq.ts @@ -23,17 +23,14 @@ const TX_OPTS = { const enc = new TextEncoder(); const dec = new TextDecoder(); -const reverseHex = (buf: Uint8Array) => - bytesToHex(Uint8Array.from(buf).reverse()); +const reverseHex = (buf: Uint8Array) => bytesToHex(Uint8Array.from(buf).reverse()); const readVarInt = (data: Uint8Array, offset: number) => { const first = data[offset]; if (first < 0xfd) return { value: first, size: 1 }; const view = new DataView(data.buffer, data.byteOffset, data.byteLength); - if (first === 0xfd) - return { value: view.getUint16(offset + 1, true), size: 3 }; - if (first === 0xfe) - return { value: view.getUint32(offset + 1, true), size: 5 }; + if (first === 0xfd) return { value: view.getUint16(offset + 1, true), size: 3 }; + if (first === 0xfe) return { value: view.getUint32(offset + 1, true), size: 5 }; return { value: Number(view.getBigUint64(offset + 1, true)), size: 9 }; }; @@ -150,10 +147,7 @@ const frame = (flags: number, body: Uint8Array) => { }; const command = (name: string, props: Record = {}) => { - const parts: Uint8Array[] = [ - Uint8Array.of(name.length), - enc.encode(name), - ]; + const parts: Uint8Array[] = [Uint8Array.of(name.length), enc.encode(name)]; for (const [k, v] of Object.entries(props)) { const kb = enc.encode(k); const vb = enc.encode(v); @@ -169,23 +163,14 @@ const subscribeCommand = (topic: string) => { const t = enc.encode(topic); return frame( 0x04, - concatBytes( - Uint8Array.of(9), - enc.encode("SUBSCRIBE"), - Uint8Array.of(t.length), - t, - ), + concatBytes(Uint8Array.of(9), enc.encode("SUBSCRIBE"), Uint8Array.of(t.length), t), ); }; const legacySubscribe = (topic: string) => frame(0x00, concatBytes(Uint8Array.of(1), enc.encode(topic))); -const startSub = ( - url: string, - topic: string, - onMessage: (b: Uint8Array) => void, -) => +const startSub = (url: string, topic: string, onMessage: (b: Uint8Array) => void) => new Promise((resolve) => { const [host, port] = url.replace("tcp://", "").split(":"); const socket = net.connect({ host, port: Number(port) }); @@ -212,11 +197,7 @@ const startSub = ( let header: number; if (flags & 0x02) { if (buffer.length < 9) return; - const view = new DataView( - buffer.buffer, - buffer.byteOffset, - buffer.byteLength, - ); + const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); size = Number(view.getBigUint64(1)); header = 9; } else { @@ -262,11 +243,7 @@ export const startZmq = async () => { if (process.env.DISABLE_ZMQ === "1") return; l("zmq connecting", RAWTX_URL, RAWBLOCK_URL); - const retry = async ( - url: string, - topic: string, - handler: (b: Uint8Array) => Promise, - ) => { + const retry = async (url: string, topic: string, handler: (b: Uint8Array) => Promise) => { let delay = 1000; const maxDelay = 30000; while (true) { -- cgit v1.2.3