@elisym/merchant-node 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/publish.ts","../src/relays.ts","../src/checks.ts","../src/config.ts","../src/home.ts","../src/ledger.ts","../src/signature.ts","../src/intake.ts","../src/listener.ts","../src/reply.ts","../src/terms.ts","../src/solana.ts","../src/runtime.ts","../src/setup-ledger.ts","../src/store-events.ts","../src/cli.ts"],"names":["log","storeAuth","errorText","LIMITS","parseCaip19","priceInSubunits","readFileSync","generateSecretKey","writeFileSync","renameSync","MAX_FUTURE_SKEW_SECS","KIND_GIFT_WRAP","resolve","buildOrderMessage","wrapOrderMessage","check","deliver","getPublicKey","finalizeEvent","KIND_INBOX_RELAYS","splitNip05","newest","KIND_PRODUCT","KIND_PAYTO"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * A payment may pay any price or payout the store offered within this long\n * before the payment's block time: a relay lag or a rotation between the\n * widget's read and the payment must not refuse a correct payment.\n */\nexport const TERMS_WINDOW_SECS = 45 * 60;\n\n/**\n * How far before an order's `created_at` a scan for its payment starts: the\n * rumor may be dated up to 15 minutes ahead (commerce `MAX_FUTURE_SKEW_SECS`).\n */\nexport const ORDER_SCAN_MARGIN_SECS = 30 * 60;\n\n/** How long an unpaid order is caught up (per payout address, not per order). */\nexport const CATCH_UP_SECS = 3 * 24 * 60 * 60;\n\n/** NIP-59 back-dates a gift wrap up to two days: a subscription reaches back that far. */\nexport const WRAP_BACKDATE_SECS = 2 * 24 * 60 * 60;\n\n/** How often a running merchant catches up on its payout addresses. */\nexport const CATCH_UP_INTERVAL_MS = 60_000;\n\n/** The receipt `medium` of each Solana network. */\nexport const SOLANA_MEDIUMS = { mainnet: 'solana', devnet: 'solana-devnet' } as const;\n\n/**\n * Where the store publishes its offer: the relays the checkout always reads\n * (its `DEFAULT_RELAYS`). The store's own inbox relays are added to these.\n */\nexport const OFFER_RELAYS: readonly string[] = [\n 'wss://relay.elisym.network',\n 'wss://relay.damus.io',\n 'wss://nos.lol',\n 'wss://relay.nostr.band',\n];\n\n/** How long one relay may take to connect and answer a publish. */\nexport const PUBLISH_DEADLINE_MS = 20_000;\n\n/** No order is dated before this (2020-09): a payment request refuses such a date. */\nexport const EARLIEST_ORDER_SECS = 1_600_000_000;\n\n/** Receipts kept per order: more are dropped (anyone can send them for free). */\nexport const MAX_RECEIPTS_PER_ORDER = 5;\n\n/**\n * Reported transactions checked again per catch-up, across ALL orders: a landed\n * payment is found by the payout-account scan anyway, so this only speeds up a\n * receipt that came before its transaction, and it must not grow with orders.\n */\nexport const MAX_RECHECKS_PER_SWEEP = 20;\n\n/** Pauses before a closed inbox subscription is opened again, growing to the last. */\nexport const RESUBSCRIBE_BACKOFF_MS: readonly number[] = [1_000, 5_000, 15_000, 60_000];\n\n/**\n * Receipts checked on arrival per minute, across all orders: a fresh order and\n * its receipts are free to send, so the rest wait for the sweep's bounded recheck.\n */\nexport const MAX_LIVE_CHECKS_PER_MINUTE = 20;\n\n/**\n * When a reported transaction is not visible to the node's RPC yet (`ask_again`),\n * it is checked again after these pauses (each within the live budget), not only\n * at the next minute's sweep: the buyer waits on the other side.\n */\nexport const ASK_AGAIN_DELAYS_MS: readonly number[] = [3_000, 10_000, 30_000];\n\n/**\n * A delivered order's status is sent again when its order or a receipt is read\n * again (a relay may have dropped the first one), at most this often per order.\n */\nexport const RESEND_EVERY_SECS = 10 * 60;\n\n/**\n * Statuses sent again at once, off the queue: a restart reads two days of\n * orders back, and a slow relay must not hold new orders behind them.\n */\nexport const MAX_REPEATS_IN_FLIGHT = 4;\n\n/**\n * A delivery counts as done once this many of the store's inbox relays took it\n * (or all of them, when fewer are configured) - one relay may drop it later.\n */\nexport const DELIVERY_RELAYS_WANTED = 2;\n\n/** After this long past the payment, one relay taking the delivery is enough. */\nexport const DELIVERY_SETTLE_SECS = 60 * 60;\n\n/** New terms are dated this much before the local clock, which may run ahead of chain time. */\nexport const TERMS_CLOCK_MARGIN_SECS = 60;\n","import type { NostrEvent } from 'nostr-tools';\nimport type { EventTemplate, VerifiedEvent } from 'nostr-tools/pure';\nimport { PUBLISH_DEADLINE_MS } from './constants';\n\nexport type AuthSigner = (template: EventTemplate) => Promise<VerifiedEvent>;\n\n/** The part of a connected nostr-tools relay a publish uses. */\nexport interface PublishRelay {\n /** Resolves only on the relay's OK true; rejects on a refusal or a timeout. */\n publish(event: NostrEvent): Promise<string>;\n auth(signer: AuthSigner): Promise<string>;\n}\n\nexport interface PublishPool {\n ensureRelay(url: string): Promise<PublishRelay>;\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nasync function publishOne(\n pool: PublishPool,\n url: string,\n event: NostrEvent,\n auth: AuthSigner,\n): Promise<void> {\n const relay = await pool.ensureRelay(url);\n try {\n await relay.publish(event);\n } catch (error) {\n // A relay that takes writes only from an authenticated key asks once; the\n // store key signs and the event goes again. Any other refusal stands.\n if (!errorText(error).startsWith('auth-required')) {\n throw error;\n }\n await relay.auth(auth);\n await relay.publish(event);\n }\n}\n\n/**\n * Publish to each relay on its own and return the ones that answered OK (the\n * pool's own publish counts a connection failure as an answer). Each relay has\n * one overall deadline.\n */\nexport async function publishToRelays(\n pool: PublishPool,\n relays: readonly string[],\n event: NostrEvent,\n auth: AuthSigner,\n log: (message: string) => void,\n deadlineMs = PUBLISH_DEADLINE_MS,\n): Promise<string[]> {\n const accepted: string[] = [];\n await Promise.all(\n relays.map(async (url) => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => reject(new Error('timed out')), deadlineMs);\n });\n try {\n await Promise.race([publishOne(pool, url, event, auth), deadline]);\n accepted.push(url);\n } catch (error) {\n log(`publish to ${url} failed: ${errorText(error)}`);\n } finally {\n clearTimeout(timer);\n }\n }),\n );\n return accepted;\n}\n","import { isPublicHostname } from '@elisym/commerce';\n\n/** The longest relay URL the checkout accepts (its `MAX_RELAY_URL_LENGTH`). */\nconst MAX_RELAY_URL_LENGTH = 256;\n\n/**\n * A relay URL in the one spelling the checkout uses, or `undefined` for one it\n * never contacts: only `wss:` on a public DNS name, no credentials, query or\n * fragment, repeated slashes collapsed and a trailing one dropped (the\n * checkout's `normalizeRelayUrl`).\n */\nexport function checkoutRelaySpelling(value: string | undefined): string | undefined {\n if (value === undefined || value.length > MAX_RELAY_URL_LENGTH || !URL.canParse(value)) {\n return undefined;\n }\n const url = new URL(value);\n if (\n url.protocol !== 'wss:' ||\n url.username !== '' ||\n url.password !== '' ||\n url.search !== '' ||\n url.hash !== '' ||\n !isPublicHostname(url.hostname)\n ) {\n return undefined;\n }\n return `wss://${url.host}${url.pathname.replace(/\\/+/g, '/').replace(/\\/$/, '')}`;\n}\n","import {\n KIND_GIFT_WRAP,\n KIND_INBOX_RELAYS,\n KIND_PAYTO,\n KIND_PRODUCT,\n LIMITS,\n buildOrderMessage,\n parseCaip19,\n parsePayto,\n parseProduct,\n priceInSubunits,\n wrapOrderMessage,\n} from '@elisym/commerce';\nimport type { Network } from '@elisym/pay-core';\nimport type { Filter, NostrEvent } from 'nostr-tools';\nimport {\n type EventTemplate,\n type VerifiedEvent,\n finalizeEvent,\n generateSecretKey,\n getPublicKey,\n} from 'nostr-tools/pure';\nimport { type AuthSigner, type PublishPool, publishToRelays } from './publish';\nimport { checkoutRelaySpelling } from './relays';\nimport type { OfferTerms } from './terms';\n\n/** How long a check waits for a relay to answer a read. */\nconst READ_WAIT_MS = 10_000;\n\n/** The part of nostr-tools' `SimplePool` the checks read with. */\nexport interface QueryPool {\n querySync(\n relays: string[],\n filter: Filter,\n params: { maxWait?: number; onauth?: (template: EventTemplate) => Promise<VerifiedEvent> },\n ): Promise<NostrEvent[]>;\n}\n\nexport interface RelayVerdict {\n relay: string;\n /** Took a gift wrap for a key it never saw. */\n accepts: boolean;\n /** Served it back to that key. */\n serves: boolean;\n}\n\n/**\n * Whether each inbox relay does what the store needs from it: take a gift\n * wrap addressed to any key (the store replies to one-time buyer keys, which\n * have no inbox of their own) and serve it back to that key. A probe wrap to a\n * fresh key is written with the store's auth and read back with the key's, on\n * its own connections (`reader`): a connection authenticates once, and one\n * that did as the store would be served what the store may read.\n */\nexport async function checkInboxRelays(\n writer: PublishPool,\n reader: QueryPool,\n relays: readonly string[],\n storeSecretKey: Uint8Array,\n storeAuth: AuthSigner,\n log: (message: string) => void,\n now: number,\n): Promise<RelayVerdict[]> {\n const recipientSecretKey = generateSecretKey();\n const recipient = getPublicKey(recipientSecretKey);\n const probe = wrapOrderMessage(\n buildOrderMessage(\n {\n type: 'status',\n buyerPubkey: recipient,\n orderId: `probe-${now.toString(36)}`,\n status: 'pending',\n },\n now,\n ),\n storeSecretKey,\n recipient,\n ).recipientWrap;\n const recipientAuth = async (template: EventTemplate) =>\n finalizeEvent(template, recipientSecretKey);\n return await Promise.all(\n relays.map(async (relay) => {\n const accepted = await publishToRelays(writer, [relay], probe, storeAuth, log);\n if (accepted.length === 0) {\n return { relay, accepts: false, serves: false };\n }\n const found = await reader\n .querySync(\n [relay],\n { kinds: [KIND_GIFT_WRAP], '#p': [recipient], ids: [probe.id] },\n { maxWait: READ_WAIT_MS, onauth: recipientAuth },\n )\n .catch(() => []);\n return { relay, accepts: true, serves: found.some((event) => event.id === probe.id) };\n }),\n );\n}\n\nexport interface DomainVerdict {\n url: string;\n ok: boolean;\n problem?: string;\n}\n\n/**\n * Whether `domain` serves `expected` (the store's nostr.json) where commerce\n * reads it, with the CORS header a browser needs to read it from another site.\n */\nexport async function checkDomain(\n domain: string,\n expected: { names: Record<string, string> },\n fetcher: typeof fetch = fetch,\n): Promise<DomainVerdict> {\n const url = `https://${domain}/.well-known/nostr.json?name=_`;\n let response: Response;\n try {\n response = await fetcher(url, { redirect: 'error', signal: AbortSignal.timeout(READ_WAIT_MS) });\n } catch (error) {\n return { url, ok: false, problem: `not reachable (${errorText(error)})` };\n }\n if (!response.ok) {\n return { url, ok: false, problem: `answered ${response.status}` };\n }\n if (response.headers.get('access-control-allow-origin') !== '*') {\n return { url, ok: false, problem: 'no \"Access-Control-Allow-Origin: *\" header' };\n }\n let served: unknown;\n try {\n const text = await response.text();\n if (text.length > LIMITS.MAX_NIP05_DOCUMENT_BYTES) {\n return { url, ok: false, problem: 'the document is too large' };\n }\n served = JSON.parse(text);\n } catch {\n return { url, ok: false, problem: 'not JSON' };\n }\n const names =\n typeof served === 'object' && served !== null && 'names' in served\n ? (served.names as Record<string, unknown>)\n : undefined;\n for (const [name, pubkey] of Object.entries(expected.names)) {\n if (names?.[name] !== pubkey) {\n return { url, ok: false, problem: `\"${name}\" is not ${pubkey}` };\n }\n }\n return { url, ok: true };\n}\n\n/**\n * What buyers are offered that this node does not honour, read from the relays'\n * newest listing (kind 30402) and owner payout list (kind 10133): a payout on\n * another rail or network, an address its ledger does not stand behind, or a\n * coin the listing prices at an amount the ledger does not record (a listing\n * published by a setup that stopped before writing the ledger). A buyer could\n * pay one and never get a delivery. `undefined` when no relay served either.\n */\nexport function offersNotHonoured(\n listing: NostrEvent | undefined,\n payoutList: NostrEvent | undefined,\n network: Network,\n standing: readonly OfferTerms[],\n): string[] | undefined {\n if (listing === undefined && payoutList === undefined) {\n return undefined;\n }\n const targets = payoutList === undefined ? [] : parsePayto(payoutList).targets;\n const found = targets\n .filter(\n (target) =>\n target.caip19.chain.family !== 'solana' ||\n target.caip19.chain.network !== network ||\n !standing.some(\n (terms) => terms.caip19 === target.caip19.id && terms.payout === target.address,\n ),\n )\n .map((target) => `${target.caip19.id} ${target.address}`);\n const product = listing === undefined ? undefined : parseProduct(listing);\n for (const id of product?.accept ?? []) {\n const caip19 = parseCaip19(id);\n const target = targets.find((candidate) => candidate.caip19.id === caip19?.id);\n // A coin with no payout, or one the widget cannot price, is not payable at all.\n if (caip19 === undefined || target === undefined || product === undefined) {\n continue;\n }\n let amount: string;\n try {\n amount = priceInSubunits(product.price, caip19.asset).toString();\n } catch {\n continue;\n }\n const honoured = standing.some(\n (terms) =>\n terms.caip19 === caip19.id && terms.payout === target.address && terms.amount === amount,\n );\n if (!honoured) {\n found.push(`${caip19.id} at ${amount}`);\n }\n }\n return [...new Set(found)];\n}\n\n/** How many relays of an inbox list the checkout uses (its `STORE_RELAY_CAP`). */\nconst CHECKOUT_INBOX_CAP = 8;\n\n/**\n * The relays the store's published inbox list (kind 10050) sends buyers' orders\n * to that this node does not read (`read`: its configured inbox relays) - an\n * order sent there is never taken. `undefined` when no relay served a list.\n */\nexport function inboxRelaysNotRead(\n inboxList: NostrEvent | undefined,\n read: readonly string[],\n): string[] | undefined {\n if (inboxList === undefined) {\n return undefined;\n }\n const reading = read.map(checkoutRelaySpelling);\n const listed: string[] = [];\n for (const tag of inboxList.tags) {\n const relay = tag[0] === 'relay' ? checkoutRelaySpelling(tag[1]) : undefined;\n if (relay !== undefined && !listed.includes(relay)) {\n listed.push(relay);\n }\n }\n return listed.slice(0, CHECKOUT_INBOX_CAP).filter((relay) => !reading.includes(relay));\n}\n\n/** What one set of relays serves: the newest listing, payout list and inbox list. */\nexport interface RelayView {\n listing: NostrEvent | undefined;\n payoutList: NostrEvent | undefined;\n inboxList: NostrEvent | undefined;\n}\n\n/**\n * Everything the relays offer buyers that this node does not honour, across\n * views (each set of relays a page may read: the defaults every page reads, and\n * with the store's own relays): terms it does not honour, and inbox relays it does not\n * read. `served` is false when no view served a listing or payout list at all.\n */\nexport function offerProblems(\n views: readonly RelayView[],\n inboxRelays: readonly string[],\n network: Network,\n standing: readonly OfferTerms[],\n): { problems: string[]; served: boolean } {\n const problems = new Set<string>();\n let served = false;\n for (const view of views) {\n for (const relay of inboxRelaysNotRead(view.inboxList, inboxRelays) ?? []) {\n problems.add(`orders sent to ${relay}, which this node does not read`);\n }\n const notHonoured = offersNotHonoured(view.listing, view.payoutList, network, standing);\n served ||= notHonoured !== undefined;\n for (const offer of notHonoured ?? []) {\n problems.add(offer);\n }\n }\n return { problems: [...problems], served };\n}\n\n/** The store's newest inbox list (kind 10050) the relays serve. */\nexport async function newestInboxList(\n pool: QueryPool,\n relays: readonly string[],\n storePubkey: string,\n): Promise<NostrEvent | undefined> {\n const events = await pool\n .querySync(\n [...relays],\n { kinds: [KIND_INBOX_RELAYS], authors: [storePubkey] },\n { maxWait: READ_WAIT_MS },\n )\n .catch(() => []);\n return newest(\n events.filter((event) => event.pubkey === storePubkey && event.kind === KIND_INBOX_RELAYS),\n );\n}\n\n/** The store's newest listing of product `d` the relays serve (the newest wins, then the lowest id). */\nexport async function newestListing(\n pool: QueryPool,\n relays: readonly string[],\n storePubkey: string,\n d: string,\n): Promise<NostrEvent | undefined> {\n const events = await pool\n .querySync(\n [...relays],\n { kinds: [KIND_PRODUCT], authors: [storePubkey], '#d': [d] },\n { maxWait: READ_WAIT_MS },\n )\n .catch(() => []);\n return newest(\n events.filter(\n (event) =>\n event.pubkey === storePubkey &&\n event.kind === KIND_PRODUCT &&\n event.tags.some((tag) => tag[0] === 'd' && tag[1] === d),\n ),\n );\n}\n\n/** The newest event, and of two in the same second the lowest id (NIP-01), as the checkout picks. */\nexport function newest(events: readonly NostrEvent[]): NostrEvent | undefined {\n return events.reduce<NostrEvent | undefined>(\n (best, event) =>\n best === undefined ||\n event.created_at > best.created_at ||\n (event.created_at === best.created_at && event.id < best.id)\n ? event\n : best,\n undefined,\n );\n}\n\n/** The owner's newest payout list (kind 10133) the relays serve, as the widget picks it. */\nexport async function newestPayoutList(\n pool: QueryPool,\n relays: readonly string[],\n ownerPubkey: string,\n): Promise<NostrEvent | undefined> {\n const events = await pool\n .querySync(\n [...relays],\n { kinds: [KIND_PAYTO], authors: [ownerPubkey] },\n { maxWait: READ_WAIT_MS },\n )\n .catch(() => []);\n return newest(\n events.filter((event) => event.pubkey === ownerPubkey && event.kind === KIND_PAYTO),\n );\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { readFileSync } from 'node:fs';\nimport {\n DELIVERY_METHODS,\n LIMITS,\n canonicalPayoutAddress,\n parseCaip19,\n priceInSubunits,\n splitNip05,\n} from '@elisym/commerce';\nimport type { Network } from '@elisym/pay-core';\nimport Decimal from 'decimal.js-light';\nimport { z } from 'zod';\nimport { checkoutRelaySpelling } from './relays';\nimport type { Delivery } from './reply';\nimport type { StoreConfig } from './store-events';\n\nexport interface MerchantConfig extends StoreConfig {\n network: Network;\n /** A Solana RPC for the network, server-side (a browser-restricted key will not do). */\n rpcUrl: string;\n product: StoreConfig['product'] & {\n /** What the buyer gets once paid: a link (a Blossom URL is one) or text. */\n delivery: Delivery;\n };\n}\n\n/** At most this many inbox relays: each is read and written for every order. */\nconst MAX_INBOX_RELAYS = 5;\n\nfunction isLocalHost(host: string): boolean {\n return host === 'localhost' || host === '127.0.0.1';\n}\n\n/** A URL with one of `secure` as its scheme, or `insecure` on this machine only. */\nfunction urlWith(secure: string, insecure: string) {\n return z.string().refine(\n (value) => {\n if (!URL.canParse(value)) {\n return false;\n }\n const url = new URL(value);\n return url.protocol === secure || (url.protocol === insecure && isLocalHost(url.hostname));\n },\n { message: `must be a ${secure}// URL` },\n );\n}\n\nconst PRICE_RE = /^\\d{1,9}(\\.\\d{1,6})?$/;\n\nconst configSchema = z\n .object({\n name: z.string().trim().min(1).max(100),\n nip05: z\n .string()\n .refine((value) => splitNip05(value) !== undefined, { message: 'is not a nip05 address' })\n // nostr.json names the owner key \"owner\": the store cannot take that name.\n .refine((value) => splitNip05(value)?.local !== 'owner', {\n message: 'cannot use the name \"owner\" (it names the owner key)',\n })\n .optional(),\n network: z.enum(['mainnet', 'devnet']),\n rpcUrl: urlWith('https:', 'http:'),\n inboxRelays: z\n .array(\n urlWith('wss:', 'ws:').refine(\n (value) => value.startsWith('ws:') || checkoutRelaySpelling(value) !== undefined,\n { message: 'must be a relay the checkout contacts: wss: on a public DNS name' },\n ),\n )\n .min(1)\n .max(MAX_INBOX_RELAYS),\n product: z.object({\n d: z\n .string()\n .regex(/^[A-Za-z0-9._-]{1,64}$/, 'use 1-64 letters, digits, dots, dashes or underscores'),\n title: z.string().trim().min(1).max(200),\n description: z.string().max(LIMITS.MAX_CONTENT_LENGTH),\n summary: z.string().max(LIMITS.MAX_TAG_VALUE_LENGTH).optional(),\n priceUsd: z.string().refine((value) => PRICE_RE.test(value) && new Decimal(value).gt(0), {\n message: 'must be a USD amount above 0, such as \"49\" or \"0.50\"',\n }),\n delivery: z.object({\n method: z.enum(DELIVERY_METHODS),\n value: z.string().min(1).max(LIMITS.MAX_TAG_VALUE_LENGTH),\n }),\n }),\n payouts: z\n .array(\n z.object({\n caip19: z.string(),\n address: z.string(),\n signature: z.string().optional(),\n }),\n )\n .min(1),\n })\n .strict()\n .superRefine((config, context) => {\n // One relay under two spellings would count twice toward a delivery.\n const spellings = config.inboxRelays.map(\n (relay) => checkoutRelaySpelling(relay) ?? relay.replace(/\\/+$/, ''),\n );\n spellings.forEach((spelling, index) => {\n if (spellings.indexOf(spelling) !== index) {\n context.addIssue({\n code: 'custom',\n path: ['inboxRelays', index],\n message: 'is listed twice',\n });\n }\n });\n const seen = new Set<string>();\n config.payouts.forEach((payout, index) => {\n const path = ['payouts', index];\n const caip19 = parseCaip19(payout.caip19);\n // The node verifies Solana payments on its own network only: a buyer who\n // paid on another rail or network would never get a delivery.\n if (caip19 === undefined || caip19.chain.family !== 'solana') {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: 'must be a Solana coin this node can verify',\n });\n return;\n }\n if (caip19.chain.network !== config.network) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: `is on ${caip19.chain.network}, the node runs on ${config.network}`,\n });\n }\n if (canonicalPayoutAddress(caip19.chain, payout.address) !== payout.address) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'address'],\n message: 'is not a Solana address',\n });\n }\n const price = config.product.priceUsd;\n if (PRICE_RE.test(price) && new Decimal(price).gt(0)) {\n try {\n priceInSubunits({ amount: price, currency: 'USD' }, caip19.asset);\n } catch {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: `${caip19.asset.symbol} cannot be paid a USD price`,\n });\n }\n }\n if (seen.has(caip19.id)) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: 'is listed twice: one payout per coin',\n });\n }\n seen.add(caip19.id);\n });\n });\n\ntype ParsedConfig = { ok: true; config: MerchantConfig } | { ok: false; problems: string[] };\n\nfunction parseConfig(value: unknown): ParsedConfig {\n const parsed = configSchema.safeParse(value);\n if (parsed.success) {\n const config = parsed.data as MerchantConfig;\n // One spelling everywhere (published, listened on, compared with the default\n // relays): the checkout's. A local ws: test relay stays as written.\n config.inboxRelays = config.inboxRelays.map((relay) => checkoutRelaySpelling(relay) ?? relay);\n return { ok: true, config };\n }\n return {\n ok: false,\n problems: parsed.error.issues.map(\n (issue) => `${issue.path.length === 0 ? 'config' : issue.path.join('.')}: ${issue.message}`,\n ),\n };\n}\n\n/** Every problem with a config, one per line; empty when it is usable. */\nexport function configProblems(value: unknown): string[] {\n const parsed = parseConfig(value);\n return parsed.ok ? [] : parsed.problems;\n}\n\n/** Read and validate the config; throws with every problem found. */\nexport function loadConfig(path: string): MerchantConfig {\n let value: unknown;\n try {\n value = JSON.parse(readFileSync(path, 'utf8'));\n } catch (error) {\n throw new Error(\n `cannot read ${path}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n const parsed = parseConfig(value);\n if (!parsed.ok) {\n throw new Error(`${path} is not usable:\\n- ${parsed.problems.join('\\n- ')}`);\n }\n return parsed.config;\n}\n\n/** The config `init` writes for the operator to fill in. */\nexport function configTemplate(network: Network): MerchantConfig {\n const usdc =\n network === 'mainnet'\n ? 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'\n : 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1/token:4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU';\n return {\n name: 'My store',\n network,\n rpcUrl:\n network === 'mainnet'\n ? 'https://mainnet.helius-rpc.com/?api-key=<a server-side key>'\n : 'https://api.devnet.solana.com',\n inboxRelays: ['wss://relay.elisym.network', 'wss://nos.lol'],\n product: {\n d: 'my-product',\n title: 'My product',\n description: 'What the buyer gets.',\n priceUsd: '10',\n delivery: { method: 'access', value: 'https://example.com/<the link the buyer gets>' },\n },\n payouts: [{ caip19: usdc, address: '<your Solana wallet address>' }],\n };\n}\n","import { randomBytes } from 'node:crypto';\nimport {\n chmodSync,\n linkSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n utimesSync,\n writeFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { generateSecretKey } from 'nostr-tools/pure';\nimport { bytesToHex, hexToBytes } from 'nostr-tools/utils';\nimport type { StoreKeys } from './store-events';\n\n/**\n * Where a merchant keeps its state: `config.json` (the operator's), `keys.json`\n * (the store and owner secret keys), `ledger.json`, `run.lock` and the\n * `nostr.json` a level A domain serves.\n */\nexport interface MerchantHome {\n dir: string;\n config: string;\n keys: string;\n ledger: string;\n lock: string;\n nostrJson: string;\n}\n\nexport const HOME_ENV = 'ELISYM_MERCHANT_HOME';\nconst DEFAULT_HOME_NAME = '.elisym-merchant';\n\n/** `--home <dir>`, else `$ELISYM_MERCHANT_HOME`, else `~/.elisym-merchant`. */\nexport function merchantHome(\n flag: string | undefined,\n env: Readonly<Record<string, string | undefined>> = process.env,\n): MerchantHome {\n const chosen = flag ?? env[HOME_ENV];\n const dir = resolve(\n chosen === undefined || chosen === '' ? join(homedir(), DEFAULT_HOME_NAME) : chosen,\n );\n return {\n dir,\n config: join(dir, 'config.json'),\n keys: join(dir, 'keys.json'),\n ledger: join(dir, 'ledger.json'),\n lock: join(dir, 'run.lock'),\n nostrJson: join(dir, 'nostr.json'),\n };\n}\n\n/** Create the home, readable by its owner only (it holds secret keys). */\nexport function ensureHome(home: MerchantHome): void {\n mkdirSync(home.dir, { recursive: true, mode: 0o700 });\n try {\n // One that already existed (a Docker volume, say) is narrowed too.\n chmodSync(home.dir, 0o700);\n } catch {\n // Not ours to change: the files in it are still written 0600.\n }\n}\n\nfunction isMissing(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\n/**\n * The store's keys. Only a missing file mints new ones (and only with\n * `create`): an unreadable one must never replace the store's identity.\n */\nexport function loadOrCreateKeys(home: MerchantHome, create: boolean): StoreKeys {\n let text: string | undefined;\n try {\n text = readFileSync(home.keys, 'utf8');\n } catch (error) {\n if (!isMissing(error)) {\n throw error;\n }\n }\n if (text !== undefined) {\n const stored = JSON.parse(text) as { store: string; owner: string };\n return { storeSecretKey: hexToBytes(stored.store), ownerSecretKey: hexToBytes(stored.owner) };\n }\n if (!create) {\n throw new Error(`no store keys in ${home.dir}: run init first`);\n }\n const keys = { storeSecretKey: generateSecretKey(), ownerSecretKey: generateSecretKey() };\n ensureHome(home);\n writeFileSync(\n home.keys,\n `${JSON.stringify({ store: bytesToHex(keys.storeSecretKey), owner: bytesToHex(keys.ownerSecretKey) })}\\n`,\n { mode: 0o600, flag: 'wx' },\n );\n return keys;\n}\n\n/** A lock nobody refreshed for this long was left by a process that is gone. */\nexport const LOCK_STALE_MS = 90_000;\n\n/** How often the holder refreshes its lock. */\nconst LOCK_HEARTBEAT_MS = 20_000;\n\n/**\n * Whether a running merchant holds the home: its lock was refreshed lately.\n * Freshness, not a PID: a PID says nothing across containers or hosts sharing\n * a mounted home (and in a container the node always has the same one).\n */\nexport function heldByRunningMerchant(home: MerchantHome, now: number = Date.now()): boolean {\n try {\n return now - statSync(home.lock).mtimeMs < LOCK_STALE_MS;\n } catch {\n return false;\n }\n}\n\nfunction createLock(home: MerchantHome, token: string): boolean {\n try {\n writeFileSync(home.lock, token, { flag: 'wx', mode: 0o600 });\n return true;\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'EEXIST') {\n return false;\n }\n throw error;\n }\n}\n\nfunction heldError(home: MerchantHome): Error {\n return new Error(\n `another merchant holds ${home.lock}; a node that stopped without releasing it frees it ${LOCK_STALE_MS / 1000} s after its last refresh`,\n );\n}\n\n/**\n * Take the home for this process: refreshed while it runs, released on exit.\n * A stale lock is moved aside under a name of this process's own first, so of\n * two processes breaking it at once only one goes on; one that turns out fresh\n * (taken meanwhile) is put back.\n */\nexport function takeLock(\n home: MerchantHome,\n options: {\n /**\n * Called when the lock turned out not to be this process's any more (it was\n * stopped past `LOCK_STALE_MS` and another took the home): by default it\n * exits, since its ledger in memory would overwrite the other's.\n */\n onLost?: () => void;\n /** When the existing lock is judged; tests move it. */\n judgedAt?: number;\n } = {},\n): () => void {\n ensureHome(home);\n const token = `${process.pid}-${randomBytes(8).toString('hex')}`;\n if (!createLock(home, token)) {\n if (heldByRunningMerchant(home, options.judgedAt)) {\n throw heldError(home);\n }\n const aside = `${home.lock}.${token}`;\n try {\n renameSync(home.lock, aside);\n } catch {\n throw heldError(home);\n }\n if (Date.now() - statSync(aside).mtimeMs < LOCK_STALE_MS) {\n try {\n linkSync(aside, home.lock);\n } catch {\n // Someone holds the name again: that lock stands.\n }\n rmSync(aside, { force: true });\n throw heldError(home);\n }\n rmSync(aside, { force: true });\n if (!createLock(home, token)) {\n throw heldError(home);\n }\n }\n const ours = () => {\n try {\n return readFileSync(home.lock, 'utf8') === token;\n } catch {\n return false;\n }\n };\n const onLost =\n options.onLost ??\n (() => {\n console.error(`error: ${home.lock} was taken by another process; stopping`);\n process.exit(1);\n });\n const heartbeat = setInterval(() => {\n try {\n if (!ours()) {\n clearInterval(heartbeat);\n onLost();\n return;\n }\n const now = new Date();\n utimesSync(home.lock, now, now);\n } catch {\n // Gone between the read and the touch: the next beat finds it lost.\n }\n }, LOCK_HEARTBEAT_MS);\n heartbeat.unref();\n const release = () => {\n clearInterval(heartbeat);\n process.removeListener('exit', release);\n if (ours()) {\n rmSync(home.lock, { force: true });\n }\n };\n process.once('exit', release);\n return release;\n}\n","import { readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { MAX_FUTURE_SKEW_SECS } from '@elisym/commerce';\nimport { CATCH_UP_SECS } from './constants';\nimport type { TermsPeriod } from './terms';\n\n/** A direct-mode order as the merchant holds it. */\nexport interface MerchantOrder {\n /** `<buyer>:<orderId>`: an order id is the buyer's, so it is unique per buyer. */\n key: string;\n buyerPubkey: string;\n orderId: string;\n /** The order rumor: the same rumor again is a no-op, a different one is dropped. */\n rumorId: string;\n /** The rumor's `created_at`: it positions the payment scan, never the price. */\n createdAt: number;\n /** The Solana reference derived from (store, buyer, orderId). */\n reference: string;\n email?: string;\n /** Transactions the buyer reported (kind 17), at most `MAX_RECEIPTS_PER_ORDER`. */\n reportedTxs: string[];\n /** Reported transactions judged finally NOT a payment for this order: never checked again. */\n refusedTxs?: string[];\n /** Queue position of each reported transaction: when it arrived, then when the sweep last checked it. */\n recheckedAt?: Record<string, number>;\n paid?: {\n signature: string;\n /** Decimal string of subunits the bound transfer paid. */\n amount: string;\n blockTime: number;\n caip19: string;\n medium: string;\n };\n /** Inbox relays that took the delivery so far: a retry goes to the others only. */\n deliveredTo?: string[];\n /** Set once the delivery counts as done (see `deliveryDone`). */\n deliveredAt?: number;\n}\n\nexport interface LedgerState {\n version: 1;\n orders: Record<string, MerchantOrder>;\n /** Every rumor id already read (orders and receipts alike). */\n seenRumors: Record<string, true>;\n /** Keys of unpaid orders pruned after the catch-up window: the id stays used. */\n closedOrders?: Record<string, true>;\n /** Payment signature -> the order it paid: each payment credits one order, once. */\n claims: Record<string, string>;\n /** The store's own terms over time, as it published them. */\n terms: TermsPeriod[];\n /**\n * Seconds: the last moment every inbox relay was read through (stored wraps\n * paged to EOSE, live since). A restart reaches back from here, less the\n * two-day wrap back-dating. Never a wrap's own date: the sender sets that.\n */\n resumeAt?: number;\n /**\n * `<account>:<signature>` -> what a landed transaction on a payout account\n * binds: each is fetched and read once, however many orders are open.\n */\n scans: Record<string, ScannedTransaction>;\n /** The product id (`d`) the store published: another one would strand the old listing. */\n productD?: string;\n /** The payouts the owner's 10133 lists, and when it was signed: republished unchanged, it keeps its date. */\n payto?: { createdAt: number; payouts: string };\n}\n\nexport interface ScannedTransaction {\n blockTime: number;\n /** References with a transfer bound to them into the payout (pay-core's binding). */\n references: string[];\n}\n\nexport function emptyLedger(): LedgerState {\n return { version: 1, orders: {}, seenRumors: {}, claims: {}, terms: [], scans: {} };\n}\n\nexport function orderKey(buyerPubkey: string, orderId: string): string {\n return `${buyerPubkey}:${orderId}`;\n}\n\n/**\n * Claim `signature` for the order `key`: true when it is now (or already was)\n * that order's, false when another order holds it. The claim must be saved\n * before the delivery goes out.\n */\nexport function claimPayment(state: LedgerState, signature: string, key: string): boolean {\n const holder = state.claims[signature];\n if (holder !== undefined && holder !== key) {\n return false;\n }\n state.claims[signature] = key;\n return true;\n}\n\n/** Orders still waiting for a payment, within the catch-up window at `now`. */\nexport function openOrders(state: LedgerState, now: number, catchUpSecs: number): MerchantOrder[] {\n return Object.values(state.orders).filter(\n (order) => order.paid === undefined && now - order.createdAt <= catchUpSecs,\n );\n}\n\n/** Orders paid but not yet delivered: a crash between the two resumes here. */\nexport function undeliveredOrders(state: LedgerState): MerchantOrder[] {\n return Object.values(state.orders).filter(\n (order) => order.paid !== undefined && order.deliveredAt === undefined,\n );\n}\n\n/**\n * Drop unpaid orders past the catch-up window (and a skew allowance): nothing\n * scans for them any more, and anyone can post them for free. Their rumor ids\n * stay, so the same order rumor is still a no-op; paid orders always stay, so a\n * claim can never be re-credited to a recreated order.\n */\nexport function pruneExpiredOrders(state: LedgerState, now: number): void {\n for (const [key, order] of Object.entries(state.orders)) {\n if (order.paid === undefined && now - order.createdAt > CATCH_UP_SECS + MAX_FUTURE_SKEW_SECS) {\n delete state.orders[key];\n (state.closedOrders ??= {})[key] = true;\n }\n }\n}\n\n/**\n * Record a transaction the buyer reported for `order`, with its place in the\n * recheck queue: the time it arrived. The queue then runs first in, first out,\n * so reports arriving later - free to send - never go ahead of it.\n */\nexport function recordReport(order: MerchantOrder, tx: string, arrivedAt: number): void {\n order.reportedTxs.push(tx);\n order.recheckedAt = { ...order.recheckedAt, [tx]: arrivedAt };\n}\n\nexport function loadLedger(path: string): LedgerState {\n let text: string;\n try {\n text = readFileSync(path, 'utf8');\n } catch {\n return emptyLedger();\n }\n const state = JSON.parse(text) as LedgerState;\n if (state.version !== 1) {\n throw new Error(`Unknown ledger version in ${path}`);\n }\n state.scans ??= {};\n return state;\n}\n\n/** Write the whole ledger, atomically: a crash leaves the old file or the new one, never half. */\nexport function saveLedger(path: string, state: LedgerState): void {\n const temporary = `${path}.tmp`;\n writeFileSync(temporary, `${JSON.stringify(state, null, 2)}\\n`, { mode: 0o600 });\n renameSync(temporary, path);\n}\n","import { type Signature, isSignature } from '@solana/kit';\n\n/** Whether `value` is a Solana signature: kit's own check throws on text outside base58. */\nexport function isSolanaSignature(value: string): value is Signature {\n try {\n return isSignature(value);\n } catch {\n return false;\n }\n}\n","import {\n type UnwrappedOrderMessage,\n deriveOrderPaymentReference,\n productAddress,\n} from '@elisym/commerce';\nimport { EARLIEST_ORDER_SECS, MAX_RECEIPTS_PER_ORDER } from './constants';\nimport { type LedgerState, type MerchantOrder, orderKey, recordReport } from './ledger';\nimport { isSolanaSignature } from './signature';\n\nexport interface StoreIdentity {\n storePubkey: string;\n /** The one product this store sells in direct mode: `30402:<store>:<d>`. */\n productAddress: string;\n /** Receipt mediums the store takes, e.g. `solana-devnet`. */\n mediums: readonly string[];\n}\n\nexport type IntakeResult =\n | { kind: 'ignored'; reason: IgnoreReason }\n | { kind: 'order'; order: MerchantOrder }\n /** `isNew`: the order had not reported this transaction before. */\n | { kind: 'receipt'; order: MerchantOrder; tx: string; isNew: boolean };\n\nexport type IgnoreReason =\n /** The same rumor again (a resumed widget republishes it byte for byte). */\n | 'seen'\n /** Addressed to another key, or naming another store. */\n | 'not_for_this_store'\n /** Not one item of this store's own product at quantity 1, or dated before any payment could be. */\n | 'not_a_direct_order'\n /** A different order rumor under an order id this buyer already used here: dropped silently. */\n | 'order_id_reused'\n /** A receipt for an order this store does not hold. */\n | 'unknown_order'\n /** A receipt under another reference, on a rail the store does not take, or naming no transaction. */\n | 'foreign_payment'\n /** More receipts for one order than the store keeps. */\n | 'too_many_receipts'\n /** A message type the merchant does not act on (status, payment request). */\n | 'not_handled';\n\nexport function storeIdentity(\n storePubkey: string,\n d: string,\n mediums: readonly string[],\n): StoreIdentity {\n return { storePubkey, productAddress: productAddress({ storePubkey, d }), mediums };\n}\n\n/**\n * Take one unwrapped order message into the ledger. The buyer is the SEAL\n * signer (`senderPubkey`), never the one-time wrap key; the reference is\n * derived here, never taken from the buyer.\n */\nexport function intake(\n state: LedgerState,\n unwrapped: UnwrappedOrderMessage,\n store: StoreIdentity,\n now: number = Math.floor(Date.now() / 1000),\n): IntakeResult {\n if (state.seenRumors[unwrapped.rumorId] === true) {\n return { kind: 'ignored', reason: 'seen' };\n }\n const { message } = unwrapped;\n if (unwrapped.recipientPubkey !== store.storePubkey) {\n return { kind: 'ignored', reason: 'not_for_this_store' };\n }\n if (message.type === 'order') {\n if (message.storePubkey !== store.storePubkey) {\n return { kind: 'ignored', reason: 'not_for_this_store' };\n }\n const [item, ...rest] = message.items;\n if (\n unwrapped.createdAt < EARLIEST_ORDER_SECS ||\n item === undefined ||\n rest.length > 0 ||\n item.product !== store.productAddress ||\n item.quantity !== 1\n ) {\n return { kind: 'ignored', reason: 'not_a_direct_order' };\n }\n const key = orderKey(unwrapped.senderPubkey, message.orderId);\n state.seenRumors[unwrapped.rumorId] = true;\n if (state.orders[key] !== undefined || state.closedOrders?.[key] === true) {\n return { kind: 'ignored', reason: 'order_id_reused' };\n }\n const reference = deriveOrderPaymentReference({\n storePubkey: store.storePubkey,\n buyerPubkey: unwrapped.senderPubkey,\n orderId: message.orderId,\n });\n const order: MerchantOrder = {\n key,\n buyerPubkey: unwrapped.senderPubkey,\n orderId: message.orderId,\n rumorId: unwrapped.rumorId,\n createdAt: unwrapped.createdAt,\n reference: reference.solana,\n reportedTxs: [],\n ...(message.email === undefined ? {} : { email: message.email }),\n };\n state.orders[key] = order;\n return { kind: 'order', order };\n }\n if (message.type === 'receipt') {\n if (message.storePubkey !== store.storePubkey) {\n return { kind: 'ignored', reason: 'not_for_this_store' };\n }\n const order = state.orders[orderKey(unwrapped.senderPubkey, message.orderId)];\n if (order === undefined) {\n return { kind: 'ignored', reason: 'unknown_order' };\n }\n const { medium, reference, tx } = message.payment;\n if (\n reference !== order.reference ||\n !store.mediums.includes(medium) ||\n !isSolanaSignature(tx)\n ) {\n return { kind: 'ignored', reason: 'foreign_payment' };\n }\n if (!order.reportedTxs.includes(tx) && order.reportedTxs.length >= MAX_RECEIPTS_PER_ORDER) {\n return { kind: 'ignored', reason: 'too_many_receipts' };\n }\n state.seenRumors[unwrapped.rumorId] = true;\n const isNew = !order.reportedTxs.includes(tx);\n if (isNew) {\n recordReport(order, tx, now);\n }\n return { kind: 'receipt', order, tx, isNew };\n }\n return { kind: 'ignored', reason: 'not_handled' };\n}\n","import { KIND_GIFT_WRAP, MAX_FUTURE_SKEW_SECS } from '@elisym/commerce';\nimport type { Filter, NostrEvent } from 'nostr-tools';\nimport type { EventTemplate, VerifiedEvent } from 'nostr-tools/pure';\nimport { RESUBSCRIBE_BACKOFF_MS, WRAP_BACKDATE_SECS } from './constants';\n\n/** The close reason nostr-tools gives a `subscribeEose` that reached EOSE (or its own timeout). */\nconst EOSE_CLOSE_REASON = 'closed automatically on eose';\n\n/** How long one backfill page may take before it counts as not read. */\nexport const PAGE_WAIT_MS = 30_000;\n\n/**\n * Passed as `maxWait`: longer than `PAGE_WAIT_MS`, so the library's own EOSE\n * timeout - which it reports exactly like a real EOSE - never ends a page first.\n */\nconst LIBRARY_WAIT_MS = PAGE_WAIT_MS + 15_000;\n\n/** A failed backfill is tried again after this long, while its subscription is open. */\nconst BACKFILL_RETRY_MS = 30_000;\n\ninterface SubscribeParams {\n maxWait?: number;\n onauth?: (template: EventTemplate) => Promise<VerifiedEvent>;\n onevent: (event: NostrEvent) => void;\n oneose?: () => void;\n onclose?: (reasons: string[]) => void;\n}\n\n/** The part of nostr-tools' `SimplePool` the listener uses. */\nexport interface ListenerPool {\n subscribe(relays: string[], filter: Filter, params: SubscribeParams): { close(): void };\n subscribeEose(relays: string[], filter: Filter, params: SubscribeParams): { close(): void };\n}\n\nexport interface ListenerOptions {\n pool: ListenerPool;\n storePubkey: string;\n auth: (template: EventTemplate) => Promise<VerifiedEvent>;\n onWrap: (wrap: NostrEvent) => void;\n log: (message: string) => void;\n now: () => number;\n /** Timers, so tests can run them; returns a cancel function. */\n setTimer?: (task: () => void, ms: number) => () => void;\n}\n\n/**\n * The resume point after a sweep: the moment it was queued, if every inbox\n * relay was read through and live then (every wrap received earlier is ahead of\n * the sweep on the queue); otherwise the old one stays.\n */\nexport function resumePointAfterSweep(\n allLive: boolean,\n queuedAt: number,\n current: number | undefined,\n): number | undefined {\n return allLive ? queuedAt : current;\n}\n\n/**\n * Wrap ids already handed on, dropped once older than any read could reach:\n * a wrap read again (the live burst overlapping the backfill, a reconnect\n * re-reading its window) is not unwrapped a second time.\n */\nexport class SeenWraps {\n private readonly seen = new Map<string, number>();\n\n /** True the first time a wrap id is offered, false after. */\n admit(wrap: Pick<NostrEvent, 'id' | 'created_at'>): boolean {\n if (this.seen.has(wrap.id)) {\n return false;\n }\n this.seen.set(wrap.id, wrap.created_at);\n return true;\n }\n\n /** Let a wrap be offered again (one that could not be acted on yet). */\n forget(id: string): void {\n this.seen.delete(id);\n }\n\n /** Forget wraps dated before `oldestReadable`: no read reaches them any more. */\n prune(oldestReadable: number): void {\n for (const [id, createdAt] of this.seen) {\n if (createdAt < oldestReadable) {\n this.seen.delete(id);\n }\n }\n }\n\n get size(): number {\n return this.seen.size;\n }\n}\n\n/**\n * Where a read that must reach every wrap sent since `from` starts: NIP-59\n * dates each wrap at a random moment up to two days back, and the rumor inside\n * may be dated up to the skew allowance ahead.\n */\nexport function readSince(from: number): number {\n return from - WRAP_BACKDATE_SECS - MAX_FUTURE_SKEW_SECS;\n}\n\nexport function wrapFilter(storePubkey: string, since: number, until?: number): Filter {\n return {\n kinds: [KIND_GIFT_WRAP],\n '#p': [storePubkey],\n since,\n ...(until === undefined ? {} : { until }),\n };\n}\n\n/**\n * The next backfill page after one that returned `received` wraps, the oldest\n * dated `oldest`, or `undefined` when the history down to `since` is read.\n * `until` is inclusive: a page that did not move below `until` (a flood of\n * wraps sharing one second) steps one second down rather than stopping.\n */\nexport function nextPageUntil(\n since: number,\n until: number,\n received: number,\n oldest: number,\n): number | undefined {\n if (received === 0 || oldest <= since) {\n return undefined;\n }\n const next = oldest < until ? oldest : until - 1;\n return next > since ? next : undefined;\n}\n\n/**\n * One subscription per store inbox relay, kept alive, plus a paged backfill of\n * what the relay stored before it opened. A relay counts as read through only\n * once a backfill reached a genuine end on a subscription that is still open.\n */\nexport class InboxListener {\n private readonly live = new Set<string>();\n private readonly attempts = new Map<string, number>();\n private readonly setTimer: (task: () => void, ms: number) => () => void;\n\n constructor(private readonly options: ListenerOptions) {\n this.setTimer =\n options.setTimer ??\n ((task, ms) => {\n const handle = setTimeout(task, ms);\n return () => clearTimeout(handle);\n });\n }\n\n /** Whether every one of `relays` is currently read through and listening. */\n allLive(relays: readonly string[]): boolean {\n return relays.every((relay) => this.live.has(relay));\n }\n\n isLive(relay: string): boolean {\n return this.live.has(relay);\n }\n\n /** Listen on `relay` for every wrap sent since `from`. */\n listen(relay: string, from: number): void {\n const { pool, storePubkey, auth, onWrap, log, now } = this.options;\n const since = readSince(from);\n const openedAt = now();\n let closed = false;\n let readThrough = false;\n const runBackfill = () => {\n if (closed) {\n return;\n }\n void this.backfill(relay, since, openedAt).then((done) => {\n if (closed) {\n return;\n }\n if (done) {\n readThrough = true;\n this.attempts.set(relay, 0);\n this.live.add(relay);\n return;\n }\n log(`could not read the stored wraps of ${relay}; trying again`);\n this.setTimer(runBackfill, BACKFILL_RETRY_MS);\n });\n };\n pool.subscribe([relay], wrapFilter(storePubkey, since), {\n onauth: auth,\n onevent: onWrap,\n // nostr-tools also calls this right before `onclose` when a subscription\n // fails: the backfill starts on the next turn, and only if still open.\n oneose: () => this.setTimer(runBackfill, 0),\n onclose: (reasons) => {\n closed = true;\n this.live.delete(relay);\n const attempt = this.attempts.get(relay) ?? 0;\n this.attempts.set(relay, attempt + 1);\n const pause =\n RESUBSCRIBE_BACKOFF_MS[Math.min(attempt, RESUBSCRIBE_BACKOFF_MS.length - 1)] ?? 60_000;\n // Reach back from the close only if this subscription read the stored history.\n const resumeFrom = readThrough ? now() : from;\n log(`subscription on ${relay} closed (${reasons.join(', ')}); again in ${pause} ms`);\n this.setTimer(() => this.listen(relay, resumeFrom), pause);\n },\n });\n }\n\n /** Page backwards through `relay`'s stored wraps in `[since, until]`; true only when read to the end. */\n backfill(relay: string, since: number, until: number): Promise<boolean> {\n const { pool, storePubkey, auth, onWrap } = this.options;\n return new Promise((resolve) => {\n let received = 0;\n let oldest = until;\n let timedOut = false;\n let cancelTimer: (() => void) | undefined;\n const subscription = pool.subscribeEose([relay], wrapFilter(storePubkey, since, until), {\n maxWait: LIBRARY_WAIT_MS,\n onauth: auth,\n onevent: (wrap) => {\n received += 1;\n oldest = Math.min(oldest, wrap.created_at);\n onWrap(wrap);\n },\n onclose: (reasons) => {\n cancelTimer?.();\n if (timedOut || !reasons.every((reason) => reason === EOSE_CLOSE_REASON)) {\n resolve(false);\n return;\n }\n const next = nextPageUntil(since, until, received, oldest);\n if (next === undefined) {\n resolve(true);\n } else {\n void this.backfill(relay, since, next).then(resolve);\n }\n },\n });\n cancelTimer = this.setTimer(() => {\n timedOut = true;\n subscription.close();\n }, PAGE_WAIT_MS);\n });\n }\n}\n","import { type WrappedOrderMessage, buildOrderMessage, wrapOrderMessage } from '@elisym/commerce';\nimport { DELIVERY_RELAYS_WANTED, DELIVERY_SETTLE_SECS } from './constants';\nimport type { MerchantOrder } from './ledger';\n\nexport interface Delivery {\n method: 'download' | 'license' | 'access' | 'webhook' | 'api';\n /** Shown to the buyer as text, or opened as a link only when it is `https:`. */\n value: string;\n}\n\n/**\n * The store's `completed` status for a paid order, sealed by the store key and\n * gift-wrapped to the buyer (the seal signer of the order). It carries the\n * payment the store credited, so the buyer's widget can show what was counted.\n */\nexport function buildDeliveryReply(\n order: MerchantOrder,\n delivery: Delivery,\n storeSecretKey: Uint8Array,\n createdAt: number,\n): WrappedOrderMessage {\n if (order.paid === undefined) {\n throw new Error('Only a paid order is delivered');\n }\n const rumor = buildOrderMessage(\n {\n type: 'status',\n buyerPubkey: order.buyerPubkey,\n orderId: order.orderId,\n status: 'completed',\n delivery,\n receipt: {\n medium: order.paid.medium,\n tx: order.paid.signature,\n amount: order.paid.amount,\n fee: '0',\n },\n },\n createdAt,\n );\n return wrapOrderMessage(rumor, storeSecretKey, order.buyerPubkey);\n}\n\n/**\n * Whether a delivery that `accepted` of the store's `relays` inbox relays took\n * counts as done: two of them (all, when fewer are configured), since one may\n * drop it later; once the payment is `paidAgeSecs` past `DELIVERY_SETTLE_SECS`,\n * any one - a relay down for good must not keep it pending forever.\n */\nexport function deliveryDone(accepted: number, relays: number, paidAgeSecs: number): boolean {\n if (accepted === 0) {\n return false;\n }\n return (\n accepted >= Math.min(DELIVERY_RELAYS_WANTED, relays) || paidAgeSecs >= DELIVERY_SETTLE_SECS\n );\n}\n","import { TERMS_WINDOW_SECS } from './constants';\n\n/** What the store asked for one product in one coin: pay `amount` to `payout`. */\nexport interface OfferTerms {\n /** CAIP-19 id of the coin. */\n caip19: string;\n /** The owner's payout address for it (the wallet, not a token account). */\n payout: string;\n /** Decimal string of the coin's subunits (quantity 1). */\n amount: string;\n}\n\n/** Terms as published, and when they were replaced (absent while they stand). */\nexport interface TermsPeriod {\n terms: OfferTerms;\n /** Seconds: when the store published these terms. */\n from: number;\n /** Seconds: when newer terms replaced them. */\n until?: number;\n}\n\nfunction sameTerms(left: OfferTerms, right: OfferTerms): boolean {\n return (\n left.caip19 === right.caip19 && left.payout === right.payout && left.amount === right.amount\n );\n}\n\n/**\n * Record newly published terms for their coin: the standing terms of that coin\n * end now. Publishing the same terms again changes nothing.\n */\nexport function publishTerms(\n periods: readonly TermsPeriod[],\n terms: OfferTerms,\n at: number,\n): TermsPeriod[] {\n const standing = periods.find(\n (period) => period.until === undefined && period.terms.caip19 === terms.caip19,\n );\n if (standing !== undefined && sameTerms(standing.terms, terms)) {\n return [...periods];\n }\n return [\n ...periods.map((period) =>\n period === standing ? { ...period, until: Math.max(at, period.from) } : period,\n ),\n { terms, from: at },\n ];\n}\n\n/**\n * End the standing terms of every coin not in `offered`: a coin dropped from the\n * offer stops being payable once the window after `at` has passed.\n */\nexport function retireTerms(\n periods: readonly TermsPeriod[],\n offered: readonly string[],\n at: number,\n): TermsPeriod[] {\n return periods.map((period) =>\n period.until === undefined && !offered.includes(period.terms.caip19)\n ? { ...period, until: Math.max(at, period.from) }\n : period,\n );\n}\n\n/**\n * Every set of terms a payment made at `blockTime` may pay: offered at some\n * moment between `blockTime - TERMS_WINDOW_SECS` and `blockTime`. The window\n * hangs on the block time, which the chain sets - never on the order's\n * `created_at`, which the buyer signs: a back-dated order must not reach an\n * older, cheaper price.\n */\nexport function termsAt(periods: readonly TermsPeriod[], blockTime: number): OfferTerms[] {\n const earliest = blockTime - TERMS_WINDOW_SECS;\n const found: OfferTerms[] = [];\n for (const period of periods) {\n const offered =\n period.from <= blockTime && (period.until === undefined || period.until > earliest);\n if (offered && !found.some((terms) => sameTerms(terms, period.terms))) {\n found.push(period.terms);\n }\n }\n return found;\n}\n\n/** Every distinct set of terms still in reach of a payment made at or after `since`. */\nexport function termsSince(periods: readonly TermsPeriod[], since: number): OfferTerms[] {\n const earliest = since - TERMS_WINDOW_SECS;\n const found: OfferTerms[] = [];\n for (const period of periods) {\n if (\n (period.until === undefined || period.until > earliest) &&\n !found.some((terms) => sameTerms(terms, period.terms))\n ) {\n found.push(period.terms);\n }\n }\n return found;\n}\n\n/** The terms standing now: the newest of each coin, not yet replaced. */\nexport function standingTerms(periods: readonly TermsPeriod[]): OfferTerms[] {\n return periods.filter((period) => period.until === undefined).map((period) => period.terms);\n}\n\n/**\n * The terms buyers can read once a publish went out in part: the coins and\n * price of the listing (`listingOut`: the new ones, else the standing ones),\n * paid to the addresses of the payout list (`payoutsOut`: the new ones, else\n * the standing ones). A coin with no payout on either side cannot be paid.\n */\nexport function visibleTerms(\n standing: readonly OfferTerms[],\n next: readonly OfferTerms[],\n listingOut: boolean,\n payoutsOut: boolean,\n): OfferTerms[] {\n const listed = listingOut ? next : standing;\n const payouts = payoutsOut ? next : standing;\n const visible: OfferTerms[] = [];\n for (const { caip19, amount } of listed) {\n const payout = payouts.find((terms) => terms.caip19 === caip19)?.payout;\n if (payout !== undefined) {\n visible.push({ caip19, payout, amount });\n }\n }\n return visible;\n}\n","import { parseCaip19 } from '@elisym/commerce';\nimport {\n type Asset,\n type DirectInstruction,\n type Network,\n ELISYM_PROTOCOL_TAG,\n boundTransferAmount,\n composeSolanaPaymentRequest,\n directInstructionsFromRpcTransaction,\n listReferenceSignatures,\n verifyDirectSolanaPayment,\n} from '@elisym/pay-core';\nimport { TOKEN_PROGRAM_ADDRESS, findAssociatedTokenPda } from '@solana-program/token';\nimport { type Rpc, type Signature, type SolanaRpcApi, address } from '@solana/kit';\nimport {\n CATCH_UP_SECS,\n MAX_RECHECKS_PER_SWEEP,\n ORDER_SCAN_MARGIN_SECS,\n SOLANA_MEDIUMS,\n TERMS_WINDOW_SECS,\n} from './constants';\nimport {\n type LedgerState,\n type MerchantOrder,\n type ScannedTransaction,\n claimPayment,\n openOrders,\n} from './ledger';\nimport { isSolanaSignature } from './signature';\nimport { type OfferTerms, termsAt, termsSince } from './terms';\n\nexport interface SolanaContext {\n rpc: Rpc<SolanaRpcApi>;\n network: Network;\n}\n\nexport type PaymentCheck =\n | { kind: 'paid'; order: MerchantOrder }\n /** Nothing final was learned (a node error, a page not readable, not landed yet). */\n | { kind: 'ask_again' }\n | {\n kind: 'refused';\n reason: 'claimed_by_another_order' | 'not_a_payment_for_this_order' | 'order_already_paid';\n };\n\n/** The Solana coin of `terms` on this network, or `undefined` for another chain or network. */\nfunction solanaAsset(terms: OfferTerms, network: Network): Asset | undefined {\n const caip19 = parseCaip19(terms.caip19);\n if (\n caip19 === undefined ||\n caip19.chain.family !== 'solana' ||\n caip19.chain.network !== network\n ) {\n return undefined;\n }\n return caip19.asset;\n}\n\nconst ASK_AGAIN_REASONS: readonly string[] = ['rpc_error', 'unreadable', 'not_found'];\n\n/**\n * Check one transaction against one order, per the direct-mode contract: the\n * payment is bound to the order's derived reference at the instruction level,\n * pays terms the store offered within the window before the payment's block\n * time, and is claimed once. On `paid` the ledger holds the claim and the\n * payment; the caller saves it before delivering.\n */\nexport async function checkPayment(\n state: LedgerState,\n order: MerchantOrder,\n signature: string,\n context: SolanaContext,\n): Promise<PaymentCheck> {\n const holder = state.claims[signature];\n if (holder !== undefined && holder !== order.key) {\n return { kind: 'refused', reason: 'claimed_by_another_order' };\n }\n // An order is paid once: a second payment is kept for a refund by hand, never credited.\n if (order.paid !== undefined) {\n return order.paid.signature === signature\n ? { kind: 'paid', order }\n : { kind: 'refused', reason: 'order_already_paid' };\n }\n const candidates = termsSince(state.terms, order.createdAt - ORDER_SCAN_MARGIN_SECS);\n let askAgain = false;\n for (const terms of candidates) {\n const asset = solanaAsset(terms, context.network);\n if (asset === undefined) {\n continue;\n }\n const request = composeSolanaPaymentRequest({\n recipient: terms.payout,\n amount: BigInt(terms.amount),\n asset,\n network: context.network,\n reference: order.reference,\n createdAt: order.createdAt,\n });\n const verdict = await verifyDirectSolanaPayment(context.rpc, request, signature);\n if (!verdict.verified) {\n askAgain ||= ASK_AGAIN_REASONS.includes(verdict.reason);\n continue;\n }\n // A null block time is judged again later, never guessed.\n if (verdict.blockTime === null) {\n askAgain = true;\n continue;\n }\n const offered = termsAt(state.terms, verdict.blockTime).some(\n (standing) =>\n standing.caip19 === terms.caip19 &&\n standing.payout === terms.payout &&\n standing.amount === terms.amount,\n );\n if (!offered) {\n continue;\n }\n if (!claimPayment(state, signature, order.key)) {\n return { kind: 'refused', reason: 'claimed_by_another_order' };\n }\n order.paid = {\n signature,\n amount: verdict.amount.toString(),\n blockTime: verdict.blockTime,\n caip19: terms.caip19,\n medium: SOLANA_MEDIUMS[context.network],\n };\n return { kind: 'paid', order };\n }\n return askAgain\n ? { kind: 'ask_again' }\n : { kind: 'refused', reason: 'not_a_payment_for_this_order' };\n}\n\n/** The account a payout's payments land in: the wallet for SOL, its associated token account otherwise. */\nexport async function receivingAccount(terms: OfferTerms, asset: Asset): Promise<string> {\n if (asset.mint === undefined) {\n return terms.payout;\n }\n const [account] = await findAssociatedTokenPda({\n owner: address(terms.payout),\n mint: address(asset.mint),\n tokenProgram:\n asset.tokenProgram === undefined ? TOKEN_PROGRAM_ADDRESS : address(asset.tokenProgram),\n });\n return account;\n}\n\n/**\n * The references a transaction binds a transfer to, into `terms.payout`: every\n * account placed just before the protocol tag is a candidate, and pay-core's\n * binding decides. Read without knowing any order, so one read serves them all.\n */\nasync function boundReferences(\n instructions: readonly DirectInstruction[],\n terms: OfferTerms,\n asset: Asset,\n): Promise<string[]> {\n const candidates = new Set<string>();\n for (const instruction of instructions) {\n const { accounts } = instruction;\n const tag = accounts[accounts.length - 1];\n const reference = accounts[accounts.length - 2];\n if (tag?.address === ELISYM_PROTOCOL_TAG && reference !== undefined) {\n candidates.add(reference.address);\n }\n }\n const bound: string[] = [];\n for (const reference of candidates) {\n const amount = await boundTransferAmount(instructions, {\n reference,\n recipient: terms.payout,\n asset,\n });\n if (amount > 0n) {\n bound.push(reference);\n }\n }\n return bound;\n}\n\n/** Read one landed transaction of a payout account, or `undefined` when it cannot be judged yet. */\nasync function scanTransaction(\n signature: Signature,\n terms: OfferTerms,\n asset: Asset,\n context: SolanaContext,\n): Promise<ScannedTransaction | undefined> {\n let transaction: unknown;\n try {\n transaction = await context.rpc\n .getTransaction(signature, {\n commitment: 'confirmed',\n encoding: 'json',\n maxSupportedTransactionVersion: 0,\n })\n .send();\n } catch {\n return undefined;\n }\n if (transaction === null || typeof transaction !== 'object') {\n return undefined;\n }\n const blockTime: unknown = Reflect.get(transaction, 'blockTime');\n // A null block time is judged again later: never cached, never guessed.\n if (typeof blockTime !== 'number' && typeof blockTime !== 'bigint') {\n return undefined;\n }\n let instructions: DirectInstruction[];\n try {\n instructions = directInstructionsFromRpcTransaction(transaction);\n } catch {\n return undefined;\n }\n return {\n blockTime: Number(blockTime),\n references: await boundReferences(instructions, terms, asset),\n };\n}\n\nexport interface CatchUpResult {\n paid: MerchantOrder[];\n /** Receiving accounts whose history was cut short by the page cap: older payments may be missed. */\n incomplete: string[];\n}\n\n/**\n * Catch up on every open order at once, per payout ADDRESS (anyone can post\n * orders for free, so never one scan per order): list the payout's receiving\n * account back to the oldest open order, read each landed transaction ONCE\n * (the ledger keeps what it binds), and match its references to the open\n * orders locally. Transactions the buyers reported are checked again too.\n */\nexport async function catchUp(\n state: LedgerState,\n context: SolanaContext,\n now: number,\n): Promise<CatchUpResult> {\n const result: CatchUpResult = { paid: [], incomplete: [] };\n const open = openOrders(state, now, CATCH_UP_SECS);\n forgetOldScans(state, now);\n if (open.length === 0) {\n return result;\n }\n const byReference = new Map(open.map((order) => [order.reference, order]));\n // A transaction finally refused for an order is remembered and never checked\n // for it again, whether it came from a receipt or from the account scan.\n const credit = async (order: MerchantOrder, signature: string) => {\n if (\n order.paid !== undefined ||\n order.refusedTxs?.includes(signature) === true ||\n state.claims[signature] !== undefined\n ) {\n return;\n }\n const check = await checkPayment(state, order, signature, context);\n if (check.kind === 'paid') {\n result.paid.push(order);\n } else if (check.kind === 'refused') {\n order.refusedTxs = [...(order.refusedTxs ?? []), signature];\n }\n };\n // Reported transactions not yet judged, first in first out (queue position:\n // arrival, then last check), under one budget for the whole sweep: every one\n // is reached within a few sweeps, and fresh reports cannot jump ahead of it.\n const pending: { order: MerchantOrder; signature: string; checkedAt: number }[] = [];\n for (const order of open) {\n for (const signature of order.reportedTxs) {\n if (\n order.paid === undefined &&\n order.refusedTxs?.includes(signature) !== true &&\n state.claims[signature] === undefined\n ) {\n // Its place in the queue: when it arrived, then when it was last checked.\n pending.push({ order, signature, checkedAt: order.recheckedAt?.[signature] ?? 0 });\n }\n }\n }\n pending.sort((left, right) => left.checkedAt - right.checkedAt);\n for (const { order, signature } of pending.slice(0, MAX_RECHECKS_PER_SWEEP)) {\n order.recheckedAt = { ...order.recheckedAt, [signature]: now };\n await credit(order, signature);\n }\n let oldest = Number.POSITIVE_INFINITY;\n for (const order of open) {\n oldest = Math.min(oldest, order.createdAt);\n }\n oldest -= ORDER_SCAN_MARGIN_SECS;\n const scannedAccounts = new Set<string>();\n for (const terms of termsSince(state.terms, oldest)) {\n const asset = solanaAsset(terms, context.network);\n if (asset === undefined) {\n continue;\n }\n const account = await receivingAccount(terms, asset);\n if (scannedAccounts.has(account)) {\n continue;\n }\n scannedAccounts.add(account);\n const listing = await listReferenceSignatures(context.rpc, account, {\n notBefore: oldest,\n commitment: 'confirmed',\n });\n if (!listing.complete) {\n result.incomplete.push(account);\n }\n for (const entry of listing.signatures) {\n // A listing page may reach below the floor; no open order needs those rows,\n // and reading them would repeat every sweep (they fall out of the memo).\n if (\n entry.failed ||\n !isSolanaSignature(entry.signature) ||\n (entry.blockTime !== null && entry.blockTime < oldest)\n ) {\n continue;\n }\n const memo = `${account}:${entry.signature}`;\n let scan: ScannedTransaction | undefined = state.scans[memo];\n if (scan === undefined) {\n scan = await scanTransaction(entry.signature, terms, asset, context);\n if (scan === undefined) {\n continue;\n }\n state.scans[memo] = scan;\n }\n for (const reference of scan.references) {\n const order = byReference.get(reference);\n if (order !== undefined) {\n await credit(order, entry.signature);\n }\n }\n }\n }\n return result;\n}\n\n/** Drop what the ledger remembers of transactions no open order can reach any more. */\nfunction forgetOldScans(state: LedgerState, now: number): void {\n const horizon = now - CATCH_UP_SECS - ORDER_SCAN_MARGIN_SECS - TERMS_WINDOW_SECS;\n for (const [memo, scan] of Object.entries(state.scans)) {\n if (scan.blockTime < horizon) {\n delete state.scans[memo];\n }\n }\n}\n","import { MAX_FUTURE_SKEW_SECS, unwrapOrderMessage } from '@elisym/commerce';\nimport type { NostrEvent } from 'nostr-tools';\nimport {\n ASK_AGAIN_DELAYS_MS,\n MAX_LIVE_CHECKS_PER_MINUTE,\n MAX_REPEATS_IN_FLIGHT,\n RESEND_EVERY_SECS,\n} from './constants';\nimport { type StoreIdentity, intake } from './intake';\nimport {\n type LedgerState,\n type MerchantOrder,\n orderKey,\n pruneExpiredOrders,\n undeliveredOrders,\n} from './ledger';\nimport { SeenWraps, readSince, resumePointAfterSweep } from './listener';\nimport { deliveryDone } from './reply';\nimport {\n type CatchUpResult,\n type PaymentCheck,\n type SolanaContext,\n catchUp,\n checkPayment,\n} from './solana';\n\nexport interface RuntimeDeps {\n state: LedgerState;\n store: StoreIdentity;\n storeSecretKey: Uint8Array;\n context: SolanaContext;\n /** Write the ledger to disk. */\n save: () => void;\n /**\n * Publish the delivery of one paid order to the store's inbox relays, except\n * `skip` (they took it already); resolves to the relays that took it now.\n */\n deliver: (order: MerchantOrder, skip: readonly string[]) => Promise<string[]>;\n /** How many inbox relays the store has: a delivery wants two of them (see `deliveryDone`). */\n inboxRelayCount: number;\n log: (message: string) => void;\n now: () => number;\n /**\n * Run `task` on the merchant's queue after `ms`: a reported transaction the\n * RPC does not see yet is checked again soon. Without it, only sweeps do.\n */\n later?: (ms: number, task: () => Promise<void>) => void;\n /** Replaceable in tests. */\n checkPayment?: typeof checkPayment;\n catchUp?: (state: LedgerState, context: SolanaContext, now: number) => Promise<CatchUpResult>;\n}\n\n/**\n * What the running merchant does with each wrap and on each sweep. The caller\n * runs every task on ONE queue, so ledger changes happen in order; every change\n * is saved before anything is sent.\n */\nexport class MerchantRuntime {\n readonly seenWraps = new SeenWraps();\n private readonly check: typeof checkPayment;\n /** Live checks in the current minute: `[minute, count]`. */\n private liveChecks: [number, number] = [0, 0];\n private readonly sweepCatchUp: NonNullable<RuntimeDeps['catchUp']>;\n /** When each delivered order's status was last sent again (this run only). */\n private readonly resentAt = new Map<string, number>();\n private repeatsInFlight = 0;\n\n constructor(private readonly deps: RuntimeDeps) {\n this.check = deps.checkPayment ?? checkPayment;\n this.sweepCatchUp = deps.catchUp ?? catchUp;\n }\n\n /**\n * Whether a wrap goes on the queue: not one dated further ahead than any\n * genuine wrap can be (NIP-59 only back-dates; nothing would ever prune it),\n * and not one already handed on (the live burst overlapping the backfill, a\n * reconnect re-reading its window).\n */\n admit(wrap: NostrEvent): boolean {\n if (wrap.created_at > this.deps.now() + MAX_FUTURE_SKEW_SECS) {\n return false;\n }\n return this.seenWraps.admit(wrap);\n }\n\n /** Take one wrap in: an order is recorded; a receipt's transaction is checked. */\n async handleWrap(wrap: NostrEvent): Promise<void> {\n const { state, store, storeSecretKey, save, log } = this.deps;\n const unwrapped = unwrapOrderMessage(wrap, storeSecretKey);\n if (unwrapped === undefined) {\n return;\n }\n const result = intake(state, unwrapped, store, this.deps.now());\n // Read again for an order already delivered: the buyer may never have got it.\n const { message } = unwrapped;\n const again =\n (result.kind === 'ignored' && result.reason === 'seen') || result.kind === 'receipt';\n if (again && (message.type === 'order' || message.type === 'receipt')) {\n const known = state.orders[orderKey(unwrapped.senderPubkey, message.orderId)];\n if (known?.deliveredAt !== undefined && message.storePubkey === store.storePubkey) {\n if (result.kind === 'receipt') {\n save();\n }\n this.resend(known);\n return;\n }\n }\n if (result.kind === 'ignored') {\n // A receipt that came before its order is read again when it is re-sent\n // or re-read, once the order is in.\n if (result.reason === 'unknown_order') {\n this.seenWraps.forget(wrap.id);\n }\n return;\n }\n save();\n if (result.kind === 'order') {\n log(`order ${result.order.key}`);\n return;\n }\n // Only a transaction the order reports for the first time is checked at once,\n // and only within a per-minute budget: orders and receipts are free to send,\n // so the rest wait for the sweep's bounded recheck.\n if (\n !result.isNew ||\n result.order.refusedTxs?.includes(result.tx) === true ||\n !this.takeLiveCheck()\n ) {\n return;\n }\n await this.checkReported(result.order, result.tx, 0);\n }\n\n /** Check one reported transaction now; one the RPC does not see yet is tried again soon. */\n private async checkReported(order: MerchantOrder, tx: string, attempt: number): Promise<void> {\n const { state, context, save, log } = this.deps;\n const check: PaymentCheck = await this.check(state, order, tx, context);\n log(`receipt ${order.key} ${tx}: ${check.kind}`);\n if (check.kind === 'refused') {\n order.refusedTxs = [...(order.refusedTxs ?? []), tx];\n }\n save();\n if (check.kind === 'paid') {\n await this.deliverPending();\n } else if (check.kind === 'ask_again') {\n this.askAgain(order.key, tx, attempt);\n }\n }\n\n private askAgain(key: string, tx: string, attempt: number): void {\n const delay = ASK_AGAIN_DELAYS_MS[attempt];\n if (delay === undefined || this.deps.later === undefined) {\n return;\n }\n this.deps.later(delay, async () => {\n // Still the same unpaid order (not pruned, not recreated), the transaction\n // not refused meanwhile, and within the live budget - else the sweep has it.\n const order = this.deps.state.orders[key];\n if (\n order === undefined ||\n order.paid !== undefined ||\n !order.reportedTxs.includes(tx) ||\n order.refusedTxs?.includes(tx) === true ||\n !this.takeLiveCheck()\n ) {\n return;\n }\n await this.checkReported(order, tx, attempt + 1);\n });\n }\n\n /**\n * Send a delivered order's status again, at most every `RESEND_EVERY_SECS`,\n * off the queue (it changes no ledger state) and a few at a time: one skipped\n * now is sent when the order is read again.\n */\n private resend(order: MerchantOrder): void {\n const now = this.deps.now();\n const last = this.resentAt.get(order.key);\n if (\n (last !== undefined && now - last < RESEND_EVERY_SECS) ||\n this.repeatsInFlight >= MAX_REPEATS_IN_FLIGHT\n ) {\n return;\n }\n this.resentAt.set(order.key, now);\n this.repeatsInFlight += 1;\n const { deliver, log } = this.deps;\n void deliver(order, [])\n .then((taken) => {\n log(`delivery for ${order.key} sent again: taken by ${taken.length}`);\n })\n .catch((error: unknown) => {\n log(`delivery for ${order.key} not sent again: ${String(error)}`);\n })\n .finally(() => {\n this.repeatsInFlight -= 1;\n });\n }\n\n private takeLiveCheck(): boolean {\n const minute = Math.floor(this.deps.now() / 60);\n const [current, count] = this.liveChecks;\n const used = current === minute ? count : 0;\n if (used >= MAX_LIVE_CHECKS_PER_MINUTE) {\n return false;\n }\n this.liveChecks = [minute, used + 1];\n return true;\n }\n\n /** One catch-up sweep; `allLive` and `queuedAt` were taken when it was queued. */\n async sweep(allLive: boolean, queuedAt: number): Promise<void> {\n const { state, context, save, log, now } = this.deps;\n state.resumeAt = resumePointAfterSweep(allLive, queuedAt, state.resumeAt);\n pruneExpiredOrders(state, now());\n this.seenWraps.prune(readSince(now()));\n for (const [key, at] of this.resentAt) {\n if (now() - at >= RESEND_EVERY_SECS) {\n this.resentAt.delete(key);\n }\n }\n try {\n const result = await this.sweepCatchUp(state, context, now());\n if (result.paid.length > 0) {\n log(`catch-up found ${result.paid.length} payment(s)`);\n }\n for (const account of result.incomplete) {\n log(`warning: the history of ${account} was cut short; older payments may be missed`);\n }\n } finally {\n // Saved before anything is sent, even when the chain could not be read this\n // time: a claim made before the error is on disk before its delivery.\n save();\n await this.deliverPending();\n }\n }\n\n /**\n * Deliver every paid order not yet delivered, all at once (a hung relay costs\n * one deadline, not one per order), each only to the relays that have not\n * taken it yet (the buyer gets no pile of copies while one relay is down).\n * An order counts as delivered per `deliveryDone`, and it is saved.\n */\n async deliverPending(): Promise<void> {\n const { state, save, log, now, deliver, inboxRelayCount } = this.deps;\n const pending = undeliveredOrders(state);\n if (pending.length === 0) {\n return;\n }\n const taken = await Promise.all(\n pending.map((order) => deliver(order, order.deliveredTo ?? []).catch(() => [])),\n );\n const at = now();\n let changed = false;\n pending.forEach((order, index) => {\n const fresh = (taken[index] ?? []).filter(\n (relay) => !(order.deliveredTo ?? []).includes(relay),\n );\n if (fresh.length > 0) {\n changed = true;\n order.deliveredTo = [...(order.deliveredTo ?? []), ...fresh];\n }\n const paidAge = at - (order.paid?.blockTime ?? at);\n if (deliveryDone(order.deliveredTo?.length ?? 0, inboxRelayCount, paidAge)) {\n changed = true;\n order.deliveredAt = at;\n log(`delivered ${order.key} (${order.paid?.signature ?? ''})`);\n } else {\n log(`delivery for ${order.key} taken by ${order.deliveredTo?.length ?? 0}; will retry`);\n }\n });\n if (changed) {\n save();\n }\n }\n}\n","import type { LedgerState } from './ledger';\nimport { type OfferTerms, publishTerms, retireTerms, standingTerms, visibleTerms } from './terms';\n\n/**\n * The date to sign the payout list with: an unchanged list keeps the date it\n * was first signed (a new one would restart every buyer's \"payout recently\n * changed\" cool-down), but only while the relays' newest list is that very\n * one - otherwise re-signing an older date would never replace what buyers read.\n */\nexport function payoutListDate(\n state: LedgerState,\n payouts: string,\n newestOnRelays: number | undefined,\n now: number,\n): number {\n const signed = state.payto;\n return signed !== undefined && signed.payouts === payouts && newestOnRelays === signed.createdAt\n ? signed.createdAt\n : now;\n}\n\n/** Why setup may not publish over what the ledger holds; `undefined` when it may. */\nexport function setupRefusal(state: LedgerState, productD: string): string | undefined {\n if (state.productD !== undefined && state.productD !== productD) {\n return `the product id changed from \"${state.productD}\" to \"${productD}\": the old listing would stay payable with no one taking its orders. Keep the id, or give a new product its own home.`;\n }\n return undefined;\n}\n\nexport interface PublishOutcome {\n /** The listing (kind 30402) reached a relay. */\n listing: boolean;\n /** The owner's payout list (kind 10133) reached a relay. */\n payouts: boolean;\n}\n\n/**\n * Record in the ledger what buyers can read after a publish: the listing's\n * coins and price, paid to the payout list's addresses - each the new one only\n * if it reached a relay. `at` dates the change (a little before now).\n */\nexport function recordPublished(\n state: LedgerState,\n next: readonly OfferTerms[],\n outcome: PublishOutcome,\n at: number,\n payoutList: { createdAt: number; payouts: string },\n productD: string,\n): void {\n const visible = visibleTerms(standingTerms(state.terms), next, outcome.listing, outcome.payouts);\n state.terms = retireTerms(\n state.terms,\n visible.map((terms) => terms.caip19),\n at,\n );\n for (const terms of visible) {\n state.terms = publishTerms(state.terms, terms, at);\n }\n if (outcome.payouts) {\n state.payto = payoutList;\n }\n if (outcome.listing) {\n state.productD = productD;\n }\n}\n","import {\n KIND_INBOX_RELAYS,\n buildPaytoEvent,\n buildProductEvent,\n buildStoreAuthEvent,\n buildStoreProfileEvent,\n encodeProductNaddr,\n parseCaip19,\n priceInSubunits,\n splitNip05,\n} from '@elisym/commerce';\nimport { type NostrEvent, finalizeEvent, getPublicKey } from 'nostr-tools/pure';\nimport type { OfferTerms } from './terms';\n\n/** The nostr.json name commerce reads the owner key from. */\nconst NOSTR_JSON_OWNER_NAME = 'owner';\n\nexport interface StoreConfig {\n /** Store profile name. */\n name: string;\n /** `_@shop.example`: the domain that vouches for the store (level A), or none (level C). */\n nip05?: string;\n product: {\n d: string;\n title: string;\n description: string;\n summary?: string;\n /** USD, e.g. `\"1\"` or `\"49.00\"`: paid 1:1 in a USD coin. */\n priceUsd: string;\n };\n /** One payout per accepted coin: CAIP-19 id and the owner's wallet address. */\n payouts: { caip19: string; address: string; signature?: string }[];\n /** The store's inbox relays (kind 10050): where it reads orders and replies. */\n inboxRelays: string[];\n}\n\nexport interface StoreKeys {\n storeSecretKey: Uint8Array;\n ownerSecretKey: Uint8Array;\n}\n\nexport interface StoreEvents {\n /** Signed, ready to publish: product, profile, inbox list (store key); payouts, authorization (owner key). */\n events: NostrEvent[];\n naddr: string;\n /** The terms these events offer, one per payout: what the ledger records. */\n terms: OfferTerms[];\n /**\n * What the domain's `/.well-known/nostr.json` serves (with CORS). It gives\n * level A only under the domain-wide name `_` (nip05 `_@domain` or a bare\n * domain); a named nip05 such as `shop@domain` stays level C.\n */\n nostrJson: { names: Record<string, string> };\n}\n\n/** Build and sign everything a store publishes, at `createdAt`. */\nexport function buildStoreEvents(\n config: StoreConfig,\n keys: StoreKeys,\n createdAt: number,\n options: {\n hints?: readonly string[];\n /**\n * When the unchanged payout list was first signed: republishing it with a new\n * date would restart every buyer's \"payout recently changed\" cool-down.\n */\n paytoCreatedAt?: number;\n } = {},\n): StoreEvents {\n const storePubkey = getPublicKey(keys.storeSecretKey);\n const ownerPubkey = getPublicKey(keys.ownerSecretKey);\n const price = { amount: config.product.priceUsd, currency: 'USD' };\n const terms: OfferTerms[] = config.payouts.map((payout) => {\n const caip19 = parseCaip19(payout.caip19);\n if (caip19 === undefined) {\n throw new Error(`Not a payable CAIP-19 asset: ${payout.caip19}`);\n }\n return {\n caip19: caip19.id,\n payout: payout.address,\n amount: priceInSubunits(price, caip19.asset).toString(),\n };\n });\n const byStore = (template: Parameters<typeof finalizeEvent>[0]) =>\n finalizeEvent(template, keys.storeSecretKey);\n const byOwner = (template: Parameters<typeof finalizeEvent>[0]) =>\n finalizeEvent(template, keys.ownerSecretKey);\n const events = [\n byStore(\n buildProductEvent({\n d: config.product.d,\n title: config.product.title,\n description: config.product.description,\n ...(config.product.summary === undefined ? {} : { summary: config.product.summary }),\n price,\n accept: config.payouts.map((payout) => payout.caip19),\n createdAt,\n }),\n ),\n byStore(\n buildStoreProfileEvent({\n name: config.name,\n ownerPubkey,\n createdAt,\n ...(config.nip05 === undefined ? {} : { nip05: config.nip05 }),\n }),\n ),\n byStore({\n kind: KIND_INBOX_RELAYS,\n created_at: createdAt,\n tags: config.inboxRelays.map((relay) => ['relay', relay]),\n content: '',\n }),\n byOwner(\n buildPaytoEvent({\n ownerPubkey,\n accept: config.payouts,\n createdAt: options.paytoCreatedAt ?? createdAt,\n }),\n ),\n byOwner(buildStoreAuthEvent({ storePubkey, mode: 'self-host', createdAt })),\n ];\n const local = config.nip05 === undefined ? '_' : (splitNip05(config.nip05)?.local ?? '_');\n // `owner` names the owner key in nostr.json: a store under that name would be lost.\n if (local === NOSTR_JSON_OWNER_NAME) {\n throw new Error(\n `The store's nip05 name cannot be \"${NOSTR_JSON_OWNER_NAME}\": it names the owner`,\n );\n }\n return {\n events,\n naddr: encodeProductNaddr({ storePubkey, d: config.product.d }, [...(options.hints ?? [])]),\n terms,\n nostrJson: { names: { [local]: storePubkey, [NOSTR_JSON_OWNER_NAME]: ownerPubkey } },\n };\n}\n","/**\n * elisym merchant node. `init` makes the home (config template and keys),\n * `setup` checks the inbox relays and publishes the store, `run` takes orders,\n * verifies payments by the direct-mode contract and delivers.\n */\nimport { existsSync, writeFileSync } from 'node:fs';\nimport { KIND_INBOX_RELAYS, KIND_PAYTO, KIND_PRODUCT, splitNip05 } from '@elisym/commerce';\nimport { createSolanaRpc } from '@solana/kit';\nimport { SimplePool } from 'nostr-tools/pool';\nimport { type EventTemplate, finalizeEvent, getPublicKey } from 'nostr-tools/pure';\nimport {\n checkDomain,\n checkInboxRelays,\n newestInboxList,\n newestListing,\n newestPayoutList,\n offerProblems,\n} from './checks';\nimport { type MerchantConfig, configTemplate, loadConfig } from './config';\nimport {\n CATCH_UP_INTERVAL_MS,\n OFFER_RELAYS,\n SOLANA_MEDIUMS,\n TERMS_CLOCK_MARGIN_SECS,\n} from './constants';\nimport {\n type MerchantHome,\n ensureHome,\n heldByRunningMerchant,\n loadOrCreateKeys,\n merchantHome,\n takeLock,\n} from './home';\nimport { storeIdentity } from './intake';\nimport { type LedgerState, type MerchantOrder, loadLedger, saveLedger } from './ledger';\nimport { InboxListener } from './listener';\nimport { publishToRelays } from './publish';\nimport { buildDeliveryReply } from './reply';\nimport { MerchantRuntime } from './runtime';\nimport { payoutListDate, recordPublished, setupRefusal } from './setup-ledger';\nimport { type StoreKeys, buildStoreEvents } from './store-events';\nimport { standingTerms } from './terms';\n\nconst USAGE = `usage: elisym-merchant <command> [--home <dir>]\n\n init [--network devnet|mainnet]\n make the home: a config.json to edit and the store's keys\n setup check the inbox relays and publish the store (after editing config.json)\n run take orders, verify payments, deliver\n orders list the orders: paid, delivered, the buyer's email\n check check the inbox relays, the owner's payout list and the domain\n\nThe home is --home, else $ELISYM_MERCHANT_HOME, else ~/.elisym-merchant.\nIt holds the store's secret keys: keep it private and back it up.`;\n\n/** Answers a relay's NIP-42 challenge with the store key. */\nfunction storeAuth(keys: StoreKeys) {\n return async (template: EventTemplate) => finalizeEvent(template, keys.storeSecretKey);\n}\n\nfunction nowSecs(): number {\n return Math.floor(Date.now() / 1000);\n}\n\nfunction log(message: string): void {\n console.log(`${new Date().toISOString()} ${message}`);\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\ninterface Args {\n command: string | undefined;\n home: string | undefined;\n network: string | undefined;\n}\n\nfunction parseArgs(argv: readonly string[]): Args {\n const args: Args = { command: undefined, home: undefined, network: undefined };\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (arg === '--home' || arg === '--network') {\n const value = argv[index + 1];\n if (value === undefined || value.startsWith('--')) {\n throw new Error(`${arg} needs a value`);\n }\n args[arg === '--home' ? 'home' : 'network'] = value;\n index += 1;\n } else if (args.command === undefined && arg !== undefined && !arg.startsWith('--')) {\n args.command = arg;\n } else {\n throw new Error(`unknown argument ${arg ?? ''}`);\n }\n }\n return args;\n}\n\nfunction init(home: MerchantHome, network: string | undefined): void {\n if (network !== undefined && network !== 'devnet' && network !== 'mainnet') {\n throw new Error('--network is devnet or mainnet');\n }\n ensureHome(home);\n if (existsSync(home.config)) {\n console.log(`config ${home.config} (kept)`);\n } else {\n writeFileSync(\n home.config,\n `${JSON.stringify(configTemplate(network === 'mainnet' ? 'mainnet' : 'devnet'), null, 2)}\\n`,\n { mode: 0o600, flag: 'wx' },\n );\n console.log(`config ${home.config} (edit it)`);\n }\n const keys = loadOrCreateKeys(home, true);\n console.log(`store ${getPublicKey(keys.storeSecretKey)}`);\n console.log(`owner ${getPublicKey(keys.ownerSecretKey)}`);\n console.log('next edit config.json, then run setup');\n}\n\n/**\n * Print what the inbox relays can do; the ones that do not take and serve gift\n * wraps for any key. Every one must: buyers send orders to all of them, and a\n * delivery one of them took counts toward the two a delivery wants.\n */\nasync function reportInboxRelays(\n pool: SimplePool,\n config: MerchantConfig,\n keys: StoreKeys,\n): Promise<string[]> {\n const reader = new SimplePool();\n let verdicts: Awaited<ReturnType<typeof checkInboxRelays>>;\n try {\n verdicts = await checkInboxRelays(\n pool,\n reader,\n config.inboxRelays,\n keys.storeSecretKey,\n storeAuth(keys),\n log,\n nowSecs(),\n );\n } finally {\n reader.destroy();\n }\n for (const verdict of verdicts) {\n let state = 'refuses gift wraps for any key';\n if (verdict.serves) {\n state = 'ok';\n } else if (verdict.accepts) {\n state = 'takes gift wraps but does not serve them back';\n }\n console.log(`relay ${verdict.relay}: ${state}`);\n }\n console.log(\n 'note each inbox relay must keep gift wraps (kind 1059) for at least two days past their date',\n );\n return verdicts.filter((verdict) => !verdict.serves).map((verdict) => verdict.relay);\n}\n\n/** Write the nostr.json a level A domain serves, and check it once; nothing for level C. */\nasync function reportDomain(\n home: MerchantHome,\n config: MerchantConfig,\n nostrJson: { names: Record<string, string> },\n): Promise<void> {\n const split = config.nip05 === undefined ? undefined : splitNip05(config.nip05);\n if (split === undefined) {\n console.log('level C (no nip05)');\n return;\n }\n if (split.local !== '_') {\n // commerce vouches for a store at level A only under the domain-wide name.\n console.log('level C: a named nip05 is not domain-wide; use _@domain or a bare domain for A');\n return;\n }\n writeFileSync(home.nostrJson, `${JSON.stringify(nostrJson)}\\n`);\n console.log(\n `nostr serve ${home.nostrJson} at https://${split.domain}/.well-known/nostr.json with \"Access-Control-Allow-Origin: *\"`,\n );\n const verdict = await checkDomain(split.domain, nostrJson);\n console.log(\n verdict.ok\n ? `level A: ${verdict.url} serves it`\n : `level C until ${verdict.url} serves it: ${verdict.problem ?? ''}`,\n );\n}\n\nasync function setup(home: MerchantHome): Promise<void> {\n // A running merchant rewrites the whole ledger from memory: new terms written\n // under it would be lost, and the old price or payout would stay payable. The\n // lock is held for the whole setup, so a merchant cannot start in between.\n takeLock(home);\n const config = loadConfig(home.config);\n const keys = loadOrCreateKeys(home, false);\n const state = loadLedger(home.ledger);\n const refusal = setupRefusal(state, config.product.d);\n if (refusal !== undefined) {\n throw new Error(refusal);\n }\n const pool = new SimplePool();\n try {\n const failing = await reportInboxRelays(pool, config, keys);\n if (failing.length > 0) {\n throw new Error(\n `these inbox relays do not take and serve gift wraps for any key: ${failing.join(', ')}. Replace them in config.json.`,\n );\n }\n const relays = [...new Set([...OFFER_RELAYS, ...config.inboxRelays])];\n const now = nowSecs();\n const payouts = JSON.stringify(config.payouts);\n const newest = await newestPayoutList(pool, relays, getPublicKey(keys.ownerSecretKey));\n const paytoCreatedAt = payoutListDate(state, payouts, newest?.created_at, now);\n const built = buildStoreEvents(config, keys, now, {\n hints: config.inboxRelays.slice(0, 2),\n paytoCreatedAt,\n });\n const acceptedKinds = new Set<number>();\n // Kinds a default relay took: every page reads those, whatever its naddr's hints.\n const everywhereKinds = new Set<number>();\n for (const event of built.events) {\n const accepted = await publishToRelays(pool, relays, event, storeAuth(keys), log);\n log(`kind ${event.kind}: accepted by ${accepted.length}/${relays.length}`);\n if (accepted.length > 0) {\n acceptedKinds.add(event.kind);\n }\n if (accepted.some((relay) => OFFER_RELAYS.includes(relay))) {\n everywhereKinds.add(event.kind);\n }\n }\n const outcome = {\n listing: acceptedKinds.has(KIND_PRODUCT),\n payouts: acceptedKinds.has(KIND_PAYTO),\n };\n if (!outcome.listing && !outcome.payouts) {\n throw new Error(\n 'neither the listing nor the payout list reached a relay: the ledger is left as it was',\n );\n }\n // Dated a little before now: a local clock running ahead of chain time must not\n // refuse a payment made right after the change.\n recordPublished(\n state,\n built.terms,\n outcome,\n now - TERMS_CLOCK_MARGIN_SECS,\n { createdAt: paytoCreatedAt, payouts },\n config.product.d,\n );\n // Orders can come from the moment the store is published: a later first run\n // reads back from here, not from its own start.\n state.resumeAt ??= now;\n saveLedger(home.ledger, state);\n console.log(`store ${getPublicKey(keys.storeSecretKey)}`);\n console.log(`owner ${getPublicKey(keys.ownerSecretKey)}`);\n console.log(`naddr ${built.naddr}`);\n await reportDomain(home, config, built.nostrJson);\n // Buyers send orders to the inbox list: one that did not go out may leave them\n // writing to relays the node no longer reads.\n const missing = [\n [KIND_PRODUCT, 'the listing'],\n [KIND_PAYTO, 'the payout list'],\n [KIND_INBOX_RELAYS, 'the inbox list'],\n ]\n .filter(([kind]) => !everywhereKinds.has(kind as number))\n .map(([, name]) => name);\n if (missing.length > 0) {\n throw new Error(\n `${missing.join(', ')} reached none of the default relays: buyers may see part of the change (the ledger follows what they see). Run setup again.`,\n );\n }\n } finally {\n pool.destroy();\n }\n}\n\n/**\n * Refuse to run when the relays offer buyers something this node does not\n * honour (see `offersNotHonoured`): a buyer could pay it and never get a delivery.\n */\nasync function refuseOffersNotHonoured(\n pool: SimplePool,\n config: MerchantConfig,\n keys: StoreKeys,\n state: LedgerState,\n): Promise<void> {\n const storePubkey = getPublicKey(keys.storeSecretKey);\n // Judged twice: from the default relays, which every page reads, and with the\n // store's own inbox relays too, which a page reads when its naddr hints them.\n const views = [OFFER_RELAYS, [...new Set([...OFFER_RELAYS, ...config.inboxRelays])]];\n const read = await Promise.all(\n views.map(async (relays) => {\n const [listing, payoutList, inboxList] = await Promise.all([\n newestListing(pool, relays, storePubkey, config.product.d),\n newestPayoutList(pool, relays, getPublicKey(keys.ownerSecretKey)),\n newestInboxList(pool, relays, storePubkey),\n ]);\n return { listing, payoutList, inboxList };\n }),\n );\n const { problems, served } = offerProblems(\n read,\n config.inboxRelays,\n config.network,\n standingTerms(state.terms),\n );\n if (problems.length > 0) {\n throw new Error(\n `the relays offer buyers what this node does not honour: ${problems.join('; ')}. Run setup (it publishes what the config names and records it) before taking orders.`,\n );\n }\n if (!served) {\n log(\n 'warning: no relay served the listing or the payout list; run setup if the store is not published',\n );\n }\n}\n\n/** A stop request's exit code (128 + the signal's number). */\nconst SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143 } as const;\n\n/** Stop at once on a signal (the lock is released on exit). */\nfunction stopOnSignals(): void {\n for (const [signal, code] of Object.entries(SIGNAL_EXIT_CODES)) {\n process.once(signal, () => process.exit(code));\n }\n}\n\n/**\n * Hold a stop request until the ledger is written: stopping between publishing\n * and recording would leave buyers offered terms the ledger refuses. A second\n * request stops at once. Returns the code to exit with afterwards, if any.\n */\nfunction deferSignals(): () => number | undefined {\n let requested: number | undefined;\n for (const [signal, code] of Object.entries(SIGNAL_EXIT_CODES)) {\n process.on(signal, () => {\n if (requested !== undefined) {\n process.exit(code);\n }\n requested = code;\n console.error('stopping once the ledger is written (again to stop now)');\n });\n }\n return () => requested;\n}\n\n/** Publish the delivery of a paid order to the inbox relays not in `skip`; the ones that took it. */\nasync function deliver(\n pool: SimplePool,\n order: MerchantOrder,\n skip: readonly string[],\n config: MerchantConfig,\n keys: StoreKeys,\n): Promise<string[]> {\n const reply = buildDeliveryReply(order, config.product.delivery, keys.storeSecretKey, nowSecs());\n // By convention the store replies on its OWN inbox relays: the buyer key has none.\n return await publishToRelays(\n pool,\n config.inboxRelays.filter((relay) => !skip.includes(relay)),\n reply.recipientWrap,\n storeAuth(keys),\n log,\n );\n}\n\nasync function run(home: MerchantHome): Promise<void> {\n const config = loadConfig(home.config);\n const keys = loadOrCreateKeys(home, false);\n const storePubkey = getPublicKey(keys.storeSecretKey);\n takeLock(home);\n // Pings find a half-open socket, which would otherwise never close.\n const pool = new SimplePool({ enablePing: true });\n const state = loadLedger(home.ledger);\n await refuseOffersNotHonoured(pool, config, keys, state);\n\n // One queue: every ledger change happens in order, and is saved before anything is sent.\n let queue: Promise<void> = Promise.resolve();\n const enqueue = (task: () => Promise<void>) => {\n queue = queue.then(task).catch((error: unknown) => {\n log(`error: ${errorText(error)}`);\n });\n };\n\n const runtime = new MerchantRuntime({\n state,\n store: storeIdentity(storePubkey, config.product.d, [SOLANA_MEDIUMS[config.network]]),\n storeSecretKey: keys.storeSecretKey,\n context: { rpc: createSolanaRpc(config.rpcUrl), network: config.network },\n save: () => saveLedger(home.ledger, state),\n deliver: (order, skip) => deliver(pool, order, skip, config, keys),\n inboxRelayCount: config.inboxRelays.length,\n log,\n now: nowSecs,\n later: (ms, task) => {\n setTimeout(() => enqueue(task), ms);\n },\n });\n const startedAt = nowSecs();\n\n const listener = new InboxListener({\n pool,\n storePubkey,\n auth: storeAuth(keys),\n onWrap: (wrap) => {\n if (runtime.admit(wrap)) {\n enqueue(() => runtime.handleWrap(wrap));\n }\n },\n log,\n now: nowSecs,\n });\n // Resume from the last moment every inbox relay was read through. Recorded before\n // listening, so a run that never reads every relay through does not restart \"from now\".\n state.resumeAt = Math.min(state.resumeAt ?? startedAt, startedAt);\n saveLedger(home.ledger, state);\n const resumeFrom = state.resumeAt;\n for (const relay of config.inboxRelays) {\n listener.listen(relay, resumeFrom);\n }\n log(`store ${storePubkey} listening on ${config.inboxRelays.join(', ')}`);\n\n let sweepQueued = false;\n const sweep = () => {\n // A slow sweep never piles up behind itself on the queue.\n if (sweepQueued) {\n return;\n }\n sweepQueued = true;\n // Every wrap received before now is already on the queue, ahead of this sweep.\n const allLive = listener.allLive(config.inboxRelays);\n const queuedAt = nowSecs();\n enqueue(async () => {\n sweepQueued = false;\n await runtime.sweep(allLive, queuedAt);\n });\n };\n sweep();\n setInterval(sweep, CATCH_UP_INTERVAL_MS);\n}\n\nfunction orderStatus(order: MerchantOrder): string {\n if (order.paid === undefined) {\n return 'open';\n }\n return order.deliveredAt === undefined ? 'paid, delivering' : 'delivered';\n}\n\nfunction listOrders(home: MerchantHome): void {\n const state = loadLedger(home.ledger);\n const all = Object.values(state.orders).sort((left, right) => left.createdAt - right.createdAt);\n for (const order of all) {\n const when = new Date(order.createdAt * 1000).toISOString();\n const paid = order.paid === undefined ? '' : ` ${order.paid.amount} ${order.paid.signature}`;\n const email = order.email === undefined ? '' : ` email=${order.email}`;\n console.log(`${when} ${orderStatus(order)} ${order.key}${paid}${email}`);\n }\n console.log(`${all.length} order(s)`);\n}\n\nasync function check(home: MerchantHome): Promise<void> {\n const config = loadConfig(home.config);\n const keys = loadOrCreateKeys(home, false);\n if (heldByRunningMerchant(home)) {\n console.log('note a merchant is running on this home');\n }\n const pool = new SimplePool();\n try {\n const failing = await reportInboxRelays(pool, config, keys);\n let offers: unknown;\n try {\n await refuseOffersNotHonoured(pool, config, keys, loadLedger(home.ledger));\n } catch (error) {\n offers = error;\n }\n await reportDomain(home, config, buildStoreEvents(config, keys, nowSecs()).nostrJson);\n if (offers !== undefined) {\n throw offers;\n }\n if (failing.length > 0) {\n throw new Error(\n `these inbox relays do not take and serve gift wraps for any key: ${failing.join(', ')}`,\n );\n }\n } finally {\n pool.destroy();\n }\n}\n\nasync function main(): Promise<void> {\n const args = parseArgs(process.argv.slice(2));\n if (args.network !== undefined && args.command !== 'init') {\n throw new Error('--network is for init; the config names the network');\n }\n const home = merchantHome(args.home);\n switch (args.command) {\n case 'init':\n init(home, args.network);\n return;\n case 'setup': {\n const stopRequested = deferSignals();\n let failed = false;\n try {\n await setup(home);\n } catch (error) {\n console.error(`error: ${errorText(error)}`);\n failed = true;\n }\n process.exit(stopRequested() ?? (failed ? 1 : 0));\n return;\n }\n case 'run':\n stopOnSignals();\n await run(home);\n return;\n case 'orders':\n listOrders(home);\n return;\n case 'check':\n await check(home);\n process.exit(0);\n return;\n default:\n console.log(USAGE);\n process.exit(args.command === undefined || args.command === 'help' ? 0 : 1);\n }\n}\n\ntry {\n await main();\n} catch (error) {\n console.error(`error: ${errorText(error)}`);\n process.exit(1);\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/publish.ts","../src/relays.ts","../src/checks.ts","../src/config.ts","../src/ledger.ts","../src/signature.ts","../src/hand.ts","../src/home.ts","../src/terms.ts","../src/tempo.ts","../src/intake.ts","../src/listener.ts","../src/reply.ts","../src/solana.ts","../src/runtime.ts","../src/setup-ledger.ts","../src/store-events.ts","../src/cli.ts"],"names":["log","storeAuth","errorText","LIMITS","parseCaip19","priceInSubunits","address","readFileSync","buildOrderMessage","wrapOrderMessage","generateSecretKey","writeFileSync","renameSync","blockTime","TEMPO_HASH_RE","check","deriveOrderPaymentReference","MAX_FUTURE_SKEW_SECS","KIND_GIFT_WRAP","resolve","deliver","run","getPublicKey","finalizeEvent","KIND_INBOX_RELAYS","splitNip05","newest","KIND_PRODUCT","KIND_PAYTO"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * A payment may pay any price or payout the store offered within this long\n * before the payment's block time: a relay lag or a rotation between the\n * widget's read and the payment must not refuse a correct payment.\n */\nexport const TERMS_WINDOW_SECS = 45 * 60;\n\n/**\n * How far before an order's `created_at` a scan for its payment starts: the\n * rumor may be dated up to 15 minutes ahead (commerce `MAX_FUTURE_SKEW_SECS`).\n */\nexport const ORDER_SCAN_MARGIN_SECS = 30 * 60;\n\n/** How long an unpaid order is caught up (per payout address, not per order). */\nexport const CATCH_UP_SECS = 3 * 24 * 60 * 60;\n\n/** NIP-59 back-dates a gift wrap up to two days: a subscription reaches back that far. */\nexport const WRAP_BACKDATE_SECS = 2 * 24 * 60 * 60;\n\n/** How often a running merchant catches up on its payout addresses. */\nexport const CATCH_UP_INTERVAL_MS = 60_000;\n\n/** The receipt `medium` of each Solana network. */\nexport const SOLANA_MEDIUMS = { mainnet: 'solana', devnet: 'solana-devnet' } as const;\n\n/**\n * Where the store publishes its offer: the relays the checkout always reads\n * (its `DEFAULT_RELAYS`). The store's own inbox relays are added to these.\n */\nexport const OFFER_RELAYS: readonly string[] = [\n 'wss://relay.elisym.network',\n 'wss://relay.damus.io',\n 'wss://nos.lol',\n 'wss://relay.nostr.band',\n];\n\n/** How long one relay may take to connect and answer a publish. */\nexport const PUBLISH_DEADLINE_MS = 20_000;\n\n/** No order is dated before this (2020-09): a payment request refuses such a date. */\nexport const EARLIEST_ORDER_SECS = 1_600_000_000;\n\n/** Receipts kept per order: more are dropped (anyone can send them for free). */\nexport const MAX_RECEIPTS_PER_ORDER = 5;\n\n/**\n * Reported transactions checked again per catch-up, across ALL orders: a landed\n * payment is found by the payout-account scan anyway, so this only speeds up a\n * receipt that came before its transaction, and it must not grow with orders.\n */\nexport const MAX_RECHECKS_PER_SWEEP = 20;\n\n/** Pauses before a closed inbox subscription is opened again, growing to the last. */\nexport const RESUBSCRIBE_BACKOFF_MS: readonly number[] = [1_000, 5_000, 15_000, 60_000];\n\n/**\n * Receipts checked on arrival per minute, across all orders: a fresh order and\n * its receipts are free to send, so the rest wait for the sweep's bounded recheck.\n */\nexport const MAX_LIVE_CHECKS_PER_MINUTE = 20;\n\n/**\n * When a reported transaction is not visible to the node's RPC yet (`ask_again`),\n * it is checked again after these pauses (each within the live budget), not only\n * at the next minute's sweep: the buyer waits on the other side.\n */\nexport const ASK_AGAIN_DELAYS_MS: readonly number[] = [3_000, 10_000, 30_000];\n\n/**\n * A delivered order's status is sent again when its order or a receipt is read\n * again (a relay may have dropped the first one), at most this often per order.\n */\nexport const RESEND_EVERY_SECS = 10 * 60;\n\n/**\n * Statuses sent again at once, off the queue: a restart reads two days of\n * orders back, and a slow relay must not hold new orders behind them.\n */\nexport const MAX_REPEATS_IN_FLIGHT = 4;\n\n/**\n * A delivery counts as done once this many of the store's inbox relays took it\n * (or all of them, when fewer are configured) - one relay may drop it later.\n */\nexport const DELIVERY_RELAYS_WANTED = 2;\n\n/** After this long past the payment, one relay taking the delivery is enough. */\nexport const DELIVERY_SETTLE_SECS = 60 * 60;\n\n/** New terms are dated this much before the local clock, which may run ahead of chain time. */\nexport const TERMS_CLOCK_MARGIN_SECS = 60;\n","import type { NostrEvent } from 'nostr-tools';\nimport type { EventTemplate, VerifiedEvent } from 'nostr-tools/pure';\nimport { PUBLISH_DEADLINE_MS } from './constants';\n\nexport type AuthSigner = (template: EventTemplate) => Promise<VerifiedEvent>;\n\n/** The part of a connected nostr-tools relay a publish uses. */\nexport interface PublishRelay {\n /** Resolves only on the relay's OK true; rejects on a refusal or a timeout. */\n publish(event: NostrEvent): Promise<string>;\n auth(signer: AuthSigner): Promise<string>;\n}\n\nexport interface PublishPool {\n ensureRelay(url: string): Promise<PublishRelay>;\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nasync function publishOne(\n pool: PublishPool,\n url: string,\n event: NostrEvent,\n auth: AuthSigner,\n): Promise<void> {\n const relay = await pool.ensureRelay(url);\n try {\n await relay.publish(event);\n } catch (error) {\n // A relay that takes writes only from an authenticated key asks once; the\n // store key signs and the event goes again. Any other refusal stands.\n if (!errorText(error).startsWith('auth-required')) {\n throw error;\n }\n await relay.auth(auth);\n await relay.publish(event);\n }\n}\n\n/**\n * Publish to each relay on its own and return the ones that answered OK (the\n * pool's own publish counts a connection failure as an answer). Each relay has\n * one overall deadline.\n */\nexport async function publishToRelays(\n pool: PublishPool,\n relays: readonly string[],\n event: NostrEvent,\n auth: AuthSigner,\n log: (message: string) => void,\n deadlineMs = PUBLISH_DEADLINE_MS,\n): Promise<string[]> {\n const accepted: string[] = [];\n await Promise.all(\n relays.map(async (url) => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => reject(new Error('timed out')), deadlineMs);\n });\n try {\n await Promise.race([publishOne(pool, url, event, auth), deadline]);\n accepted.push(url);\n } catch (error) {\n log(`publish to ${url} failed: ${errorText(error)}`);\n } finally {\n clearTimeout(timer);\n }\n }),\n );\n return accepted;\n}\n","import { isPublicHostname } from '@elisym/commerce';\n\n/** The longest relay URL the checkout accepts (its `MAX_RELAY_URL_LENGTH`). */\nconst MAX_RELAY_URL_LENGTH = 256;\n\n/**\n * A relay URL in the one spelling the checkout uses, or `undefined` for one it\n * never contacts: only `wss:` on a public DNS name, no credentials, query or\n * fragment, repeated slashes collapsed and a trailing one dropped (the\n * checkout's `normalizeRelayUrl`).\n */\nexport function checkoutRelaySpelling(value: string | undefined): string | undefined {\n if (value === undefined || value.length > MAX_RELAY_URL_LENGTH || !URL.canParse(value)) {\n return undefined;\n }\n const url = new URL(value);\n if (\n url.protocol !== 'wss:' ||\n url.username !== '' ||\n url.password !== '' ||\n url.search !== '' ||\n url.hash !== '' ||\n !isPublicHostname(url.hostname)\n ) {\n return undefined;\n }\n return `wss://${url.host}${url.pathname.replace(/\\/+/g, '/').replace(/\\/$/, '')}`;\n}\n","import {\n KIND_GIFT_WRAP,\n KIND_INBOX_RELAYS,\n KIND_PAYTO,\n KIND_PRODUCT,\n LIMITS,\n buildOrderMessage,\n parseCaip19,\n parsePayto,\n parseProduct,\n priceInSubunits,\n wrapOrderMessage,\n} from '@elisym/commerce';\nimport type { Network } from '@elisym/pay-core';\nimport type { Filter, NostrEvent } from 'nostr-tools';\nimport {\n type EventTemplate,\n type VerifiedEvent,\n finalizeEvent,\n generateSecretKey,\n getPublicKey,\n} from 'nostr-tools/pure';\nimport { type AuthSigner, type PublishPool, publishToRelays } from './publish';\nimport { checkoutRelaySpelling } from './relays';\nimport type { OfferTerms } from './terms';\n\n/** How long a check waits for a relay to answer a read. */\nconst READ_WAIT_MS = 10_000;\n\n/** The part of nostr-tools' `SimplePool` the checks read with. */\nexport interface QueryPool {\n querySync(\n relays: string[],\n filter: Filter,\n params: { maxWait?: number; onauth?: (template: EventTemplate) => Promise<VerifiedEvent> },\n ): Promise<NostrEvent[]>;\n}\n\nexport interface RelayVerdict {\n relay: string;\n /** Took a gift wrap for a key it never saw. */\n accepts: boolean;\n /** Served it back to that key. */\n serves: boolean;\n}\n\n/**\n * Whether each inbox relay does what the store needs from it: take a gift\n * wrap addressed to any key (the store replies to one-time buyer keys, which\n * have no inbox of their own) and serve it back to that key. A probe wrap to a\n * fresh key is written with the store's auth and read back with the key's, on\n * its own connections (`reader`): a connection authenticates once, and one\n * that did as the store would be served what the store may read.\n */\nexport async function checkInboxRelays(\n writer: PublishPool,\n reader: QueryPool,\n relays: readonly string[],\n storeSecretKey: Uint8Array,\n storeAuth: AuthSigner,\n log: (message: string) => void,\n now: number,\n): Promise<RelayVerdict[]> {\n const recipientSecretKey = generateSecretKey();\n const recipient = getPublicKey(recipientSecretKey);\n const probe = wrapOrderMessage(\n buildOrderMessage(\n {\n type: 'status',\n buyerPubkey: recipient,\n orderId: `probe-${now.toString(36)}`,\n status: 'pending',\n },\n now,\n ),\n storeSecretKey,\n recipient,\n ).recipientWrap;\n const recipientAuth = async (template: EventTemplate) =>\n finalizeEvent(template, recipientSecretKey);\n return await Promise.all(\n relays.map(async (relay) => {\n const accepted = await publishToRelays(writer, [relay], probe, storeAuth, log);\n if (accepted.length === 0) {\n return { relay, accepts: false, serves: false };\n }\n const found = await reader\n .querySync(\n [relay],\n { kinds: [KIND_GIFT_WRAP], '#p': [recipient], ids: [probe.id] },\n { maxWait: READ_WAIT_MS, onauth: recipientAuth },\n )\n .catch(() => []);\n return { relay, accepts: true, serves: found.some((event) => event.id === probe.id) };\n }),\n );\n}\n\nexport interface DomainVerdict {\n url: string;\n ok: boolean;\n problem?: string;\n}\n\n/**\n * Whether `domain` serves `expected` (the store's nostr.json) where commerce\n * reads it, with the CORS header a browser needs to read it from another site.\n */\nexport async function checkDomain(\n domain: string,\n expected: { names: Record<string, string> },\n fetcher: typeof fetch = fetch,\n): Promise<DomainVerdict> {\n const url = `https://${domain}/.well-known/nostr.json?name=_`;\n let response: Response;\n try {\n response = await fetcher(url, { redirect: 'error', signal: AbortSignal.timeout(READ_WAIT_MS) });\n } catch (error) {\n return { url, ok: false, problem: `not reachable (${errorText(error)})` };\n }\n if (!response.ok) {\n return { url, ok: false, problem: `answered ${response.status}` };\n }\n if (response.headers.get('access-control-allow-origin') !== '*') {\n return { url, ok: false, problem: 'no \"Access-Control-Allow-Origin: *\" header' };\n }\n let served: unknown;\n try {\n const text = await response.text();\n if (text.length > LIMITS.MAX_NIP05_DOCUMENT_BYTES) {\n return { url, ok: false, problem: 'the document is too large' };\n }\n served = JSON.parse(text);\n } catch {\n return { url, ok: false, problem: 'not JSON' };\n }\n const names =\n typeof served === 'object' && served !== null && 'names' in served\n ? (served.names as Record<string, unknown>)\n : undefined;\n for (const [name, pubkey] of Object.entries(expected.names)) {\n if (names?.[name] !== pubkey) {\n return { url, ok: false, problem: `\"${name}\" is not ${pubkey}` };\n }\n }\n return { url, ok: true };\n}\n\n/**\n * What buyers are offered that this node does not honour, read from the relays'\n * newest listing (kind 30402) and owner payout list (kind 10133): a payout on\n * another rail or network, an address its ledger does not stand behind, or a\n * coin the listing prices at an amount the ledger does not record (a listing\n * published by a setup that stopped before writing the ledger). A buyer could\n * pay one and never get a delivery. `undefined` when no relay served either.\n */\nexport function offersNotHonoured(\n listing: NostrEvent | undefined,\n payoutList: NostrEvent | undefined,\n network: Network,\n standing: readonly OfferTerms[],\n /** The registry network of the node's Tempo block, when it has one. */\n tempoNetwork?: Network,\n): string[] | undefined {\n if (listing === undefined && payoutList === undefined) {\n return undefined;\n }\n const targets = payoutList === undefined ? [] : parsePayto(payoutList).targets;\n const found = targets\n .filter(\n (target) =>\n (target.caip19.chain.family === 'solana'\n ? target.caip19.chain.network !== network\n : target.caip19.chain.family !== 'evm' ||\n tempoNetwork === undefined ||\n target.caip19.chain.network !== tempoNetwork) ||\n !standing.some(\n (terms) => terms.caip19 === target.caip19.id && terms.payout === target.address,\n ),\n )\n .map((target) => `${target.caip19.id} ${target.address}`);\n const product = listing === undefined ? undefined : parseProduct(listing);\n for (const id of product?.accept ?? []) {\n const caip19 = parseCaip19(id);\n const target = targets.find((candidate) => candidate.caip19.id === caip19?.id);\n // A coin with no payout, or one the widget cannot price, is not payable at all.\n if (caip19 === undefined || target === undefined || product === undefined) {\n continue;\n }\n let amount: string;\n try {\n amount = priceInSubunits(product.price, caip19.asset).toString();\n } catch {\n continue;\n }\n const honoured = standing.some(\n (terms) =>\n terms.caip19 === caip19.id && terms.payout === target.address && terms.amount === amount,\n );\n if (!honoured) {\n found.push(`${caip19.id} at ${amount}`);\n }\n }\n return [...new Set(found)];\n}\n\n/** How many relays of an inbox list the checkout uses (its `STORE_RELAY_CAP`). */\nconst CHECKOUT_INBOX_CAP = 8;\n\n/**\n * The relays the store's published inbox list (kind 10050) sends buyers' orders\n * to that this node does not read (`read`: its configured inbox relays) - an\n * order sent there is never taken. `undefined` when no relay served a list.\n */\nexport function inboxRelaysNotRead(\n inboxList: NostrEvent | undefined,\n read: readonly string[],\n): string[] | undefined {\n if (inboxList === undefined) {\n return undefined;\n }\n const reading = read.map(checkoutRelaySpelling);\n const listed: string[] = [];\n for (const tag of inboxList.tags) {\n const relay = tag[0] === 'relay' ? checkoutRelaySpelling(tag[1]) : undefined;\n if (relay !== undefined && !listed.includes(relay)) {\n listed.push(relay);\n }\n }\n return listed.slice(0, CHECKOUT_INBOX_CAP).filter((relay) => !reading.includes(relay));\n}\n\n/** What one set of relays serves: the newest listing, payout list and inbox list. */\nexport interface RelayView {\n listing: NostrEvent | undefined;\n payoutList: NostrEvent | undefined;\n inboxList: NostrEvent | undefined;\n}\n\n/**\n * Everything the relays offer buyers that this node does not honour, across\n * views (each set of relays a page may read: the defaults every page reads, and\n * with the store's own relays): terms it does not honour, and inbox relays it does not\n * read. `served` is false when no view served a listing or payout list at all.\n */\nexport function offerProblems(\n views: readonly RelayView[],\n inboxRelays: readonly string[],\n network: Network,\n standing: readonly OfferTerms[],\n tempoNetwork?: Network,\n): { problems: string[]; served: boolean } {\n const problems = new Set<string>();\n let served = false;\n for (const view of views) {\n for (const relay of inboxRelaysNotRead(view.inboxList, inboxRelays) ?? []) {\n problems.add(`orders sent to ${relay}, which this node does not read`);\n }\n const notHonoured = offersNotHonoured(\n view.listing,\n view.payoutList,\n network,\n standing,\n tempoNetwork,\n );\n served ||= notHonoured !== undefined;\n for (const offer of notHonoured ?? []) {\n problems.add(offer);\n }\n }\n return { problems: [...problems], served };\n}\n\n/** The store's newest inbox list (kind 10050) the relays serve. */\nexport async function newestInboxList(\n pool: QueryPool,\n relays: readonly string[],\n storePubkey: string,\n): Promise<NostrEvent | undefined> {\n const events = await pool\n .querySync(\n [...relays],\n { kinds: [KIND_INBOX_RELAYS], authors: [storePubkey] },\n { maxWait: READ_WAIT_MS },\n )\n .catch(() => []);\n return newest(\n events.filter((event) => event.pubkey === storePubkey && event.kind === KIND_INBOX_RELAYS),\n );\n}\n\n/** The store's newest listing of product `d` the relays serve (the newest wins, then the lowest id). */\nexport async function newestListing(\n pool: QueryPool,\n relays: readonly string[],\n storePubkey: string,\n d: string,\n): Promise<NostrEvent | undefined> {\n const events = await pool\n .querySync(\n [...relays],\n { kinds: [KIND_PRODUCT], authors: [storePubkey], '#d': [d] },\n { maxWait: READ_WAIT_MS },\n )\n .catch(() => []);\n return newest(\n events.filter(\n (event) =>\n event.pubkey === storePubkey &&\n event.kind === KIND_PRODUCT &&\n event.tags.some((tag) => tag[0] === 'd' && tag[1] === d),\n ),\n );\n}\n\n/** The newest event, and of two in the same second the lowest id (NIP-01), as the checkout picks. */\nexport function newest(events: readonly NostrEvent[]): NostrEvent | undefined {\n return events.reduce<NostrEvent | undefined>(\n (best, event) =>\n best === undefined ||\n event.created_at > best.created_at ||\n (event.created_at === best.created_at && event.id < best.id)\n ? event\n : best,\n undefined,\n );\n}\n\n/** The owner's newest payout list (kind 10133) the relays serve, as the widget picks it. */\nexport async function newestPayoutList(\n pool: QueryPool,\n relays: readonly string[],\n ownerPubkey: string,\n): Promise<NostrEvent | undefined> {\n const events = await pool\n .querySync(\n [...relays],\n { kinds: [KIND_PAYTO], authors: [ownerPubkey] },\n { maxWait: READ_WAIT_MS },\n )\n .catch(() => []);\n return newest(\n events.filter((event) => event.pubkey === ownerPubkey && event.kind === KIND_PAYTO),\n );\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { readFileSync } from 'node:fs';\nimport {\n DELIVERY_METHODS,\n LIMITS,\n canonicalPayoutAddress,\n parseCaip19,\n priceInSubunits,\n splitNip05,\n} from '@elisym/commerce';\nimport { EVM_ASSETS, type Network } from '@elisym/pay-core';\nimport { TEMPO_UNPAYABLE_ADDRESSES } from '@elisym/pay-core/evm';\nimport Decimal from 'decimal.js-light';\nimport { z } from 'zod';\nimport { checkoutRelaySpelling } from './relays';\nimport type { Delivery } from './reply';\nimport type { StoreConfig } from './store-events';\n\nexport type TempoNetwork = 'mainnet' | 'moderato';\n\nexport interface MerchantConfig extends StoreConfig {\n network: Network;\n /**\n * A Solana RPC for the network, server-side (a browser-restricted key will not\n * do). Required only when a Solana payout is configured.\n */\n rpcUrl?: string;\n /** Present when the store takes Tempo payouts: the network, and a server-side RPC. */\n tempo?: { network: TempoNetwork; rpcUrl?: string };\n product: StoreConfig['product'] & {\n /** What the buyer gets once paid: a link (a Blossom URL is one) or text. */\n delivery: Delivery;\n };\n}\n\n/** At most this many inbox relays: each is read and written for every order. */\nconst MAX_INBOX_RELAYS = 5;\n\nfunction isLocalHost(host: string): boolean {\n return host === 'localhost' || host === '127.0.0.1';\n}\n\n/** A URL with one of `secure` as its scheme, or `insecure` on this machine only. */\nfunction urlWith(secure: string, insecure: string) {\n return z.string().refine(\n (value) => {\n if (!URL.canParse(value)) {\n return false;\n }\n const url = new URL(value);\n return url.protocol === secure || (url.protocol === insecure && isLocalHost(url.hostname));\n },\n { message: `must be a ${secure}// URL` },\n );\n}\n\nconst PRICE_RE = /^\\d{1,9}(\\.\\d{1,6})?$/;\n\nconst configSchema = z\n .object({\n name: z.string().trim().min(1).max(100),\n nip05: z\n .string()\n .refine((value) => splitNip05(value) !== undefined, { message: 'is not a nip05 address' })\n // nostr.json names the owner key \"owner\": the store cannot take that name.\n .refine((value) => splitNip05(value)?.local !== 'owner', {\n message: 'cannot use the name \"owner\" (it names the owner key)',\n })\n .optional(),\n network: z.enum(['mainnet', 'devnet']),\n rpcUrl: urlWith('https:', 'http:').optional(),\n tempo: z\n .object({\n network: z.enum(['mainnet', 'moderato']),\n rpcUrl: urlWith('https:', 'http:').optional(),\n })\n .strict()\n .optional(),\n inboxRelays: z\n .array(\n urlWith('wss:', 'ws:').refine(\n (value) => value.startsWith('ws:') || checkoutRelaySpelling(value) !== undefined,\n { message: 'must be a relay the checkout contacts: wss: on a public DNS name' },\n ),\n )\n .min(1)\n .max(MAX_INBOX_RELAYS),\n product: z.object({\n d: z\n .string()\n .regex(/^[A-Za-z0-9._-]{1,64}$/, 'use 1-64 letters, digits, dots, dashes or underscores'),\n title: z.string().trim().min(1).max(200),\n description: z.string().max(LIMITS.MAX_CONTENT_LENGTH),\n summary: z.string().max(LIMITS.MAX_TAG_VALUE_LENGTH).optional(),\n priceUsd: z.string().refine((value) => PRICE_RE.test(value) && new Decimal(value).gt(0), {\n message: 'must be a USD amount above 0, such as \"49\" or \"0.50\"',\n }),\n delivery: z.object({\n method: z.enum(DELIVERY_METHODS),\n value: z.string().min(1).max(LIMITS.MAX_TAG_VALUE_LENGTH),\n }),\n }),\n payouts: z\n .array(\n z.object({\n caip19: z.string(),\n address: z.string(),\n signature: z.string().optional(),\n }),\n )\n .min(1),\n })\n .strict()\n .superRefine((config, context) => {\n // One relay under two spellings would count twice toward a delivery.\n const spellings = config.inboxRelays.map(\n (relay) => checkoutRelaySpelling(relay) ?? relay.replace(/\\/+$/, ''),\n );\n spellings.forEach((spelling, index) => {\n if (spellings.indexOf(spelling) !== index) {\n context.addIssue({\n code: 'custom',\n path: ['inboxRelays', index],\n message: 'is listed twice',\n });\n }\n });\n const seen = new Set<string>();\n let solanaPayouts = 0;\n config.payouts.forEach((payout, index) => {\n const path = ['payouts', index];\n const caip19 = parseCaip19(payout.caip19);\n // The node verifies payments on its configured networks only: a buyer who\n // paid on another rail or network would never get a delivery.\n if (caip19 === undefined) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: 'must be a coin this node can verify',\n });\n return;\n }\n if (caip19.chain.family === 'evm') {\n if (config.tempo === undefined) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: 'is a Tempo coin: add a \"tempo\" block for the node to verify it',\n });\n return;\n }\n const wanted = tempoRegistryNetwork(config.tempo.network);\n if (caip19.chain.network !== wanted) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: `is not on Tempo ${config.tempo.network}`,\n });\n }\n if (\n canonicalPayoutAddress(caip19.chain, payout.address) !== payout.address ||\n !isPayableTempoAddress(payout.address)\n ) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'address'],\n message:\n 'is not a Tempo address a payment can go to (lowercase 0x, not a system or coin address)',\n });\n }\n } else {\n solanaPayouts += 1;\n if (caip19.chain.network !== config.network) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: `is on ${caip19.chain.network}, the node runs on ${config.network}`,\n });\n }\n if (canonicalPayoutAddress(caip19.chain, payout.address) !== payout.address) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'address'],\n message: 'is not a Solana address',\n });\n }\n }\n const price = config.product.priceUsd;\n if (PRICE_RE.test(price) && new Decimal(price).gt(0)) {\n try {\n priceInSubunits({ amount: price, currency: 'USD' }, caip19.asset);\n } catch {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: `${caip19.asset.symbol} cannot be paid a USD price`,\n });\n }\n }\n if (seen.has(caip19.id)) {\n context.addIssue({\n code: 'custom',\n path: [...path, 'caip19'],\n message: 'is listed twice: one payout per coin',\n });\n }\n seen.add(caip19.id);\n });\n if (solanaPayouts > 0 && config.rpcUrl === undefined) {\n context.addIssue({\n code: 'custom',\n path: ['rpcUrl'],\n message: 'is required with a Solana payout',\n });\n }\n });\n\n/** The registry's network name for a Tempo network: Moderato is Tempo's testnet. */\nexport function tempoRegistryNetwork(network: TempoNetwork): Network {\n return network === 'mainnet' ? 'mainnet' : 'devnet';\n}\n\n/** Not a Tempo system address, and not a coin's own contract: money sent there reaches no one. */\nfunction isPayableTempoAddress(address: string): boolean {\n const coins = EVM_ASSETS.flatMap((coin) =>\n coin.mint === undefined ? [] : [coin.mint.toLowerCase()],\n );\n return !TEMPO_UNPAYABLE_ADDRESSES.includes(address) && !coins.includes(address);\n}\n\ntype ParsedConfig = { ok: true; config: MerchantConfig } | { ok: false; problems: string[] };\n\nfunction parseConfig(value: unknown): ParsedConfig {\n const parsed = configSchema.safeParse(value);\n if (parsed.success) {\n const config = parsed.data as MerchantConfig;\n // One spelling everywhere (published, listened on, compared with the default\n // relays): the checkout's. A local ws: test relay stays as written.\n config.inboxRelays = config.inboxRelays.map((relay) => checkoutRelaySpelling(relay) ?? relay);\n return { ok: true, config };\n }\n return {\n ok: false,\n problems: parsed.error.issues.map(\n (issue) => `${issue.path.length === 0 ? 'config' : issue.path.join('.')}: ${issue.message}`,\n ),\n };\n}\n\n/** Every problem with a config, one per line; empty when it is usable. */\nexport function configProblems(value: unknown): string[] {\n const parsed = parseConfig(value);\n return parsed.ok ? [] : parsed.problems;\n}\n\n/** Read and validate the config; throws with every problem found. */\nexport function loadConfig(path: string): MerchantConfig {\n let value: unknown;\n try {\n value = JSON.parse(readFileSync(path, 'utf8'));\n } catch (error) {\n throw new Error(\n `cannot read ${path}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n const parsed = parseConfig(value);\n if (!parsed.ok) {\n throw new Error(`${path} is not usable:\\n- ${parsed.problems.join('\\n- ')}`);\n }\n return parsed.config;\n}\n\n/** The config `init` writes for the operator to fill in. */\nexport function configTemplate(network: Network): MerchantConfig {\n const usdc =\n network === 'mainnet'\n ? 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'\n : 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1/token:4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU';\n return {\n name: 'My store',\n network,\n rpcUrl:\n network === 'mainnet'\n ? 'https://mainnet.helius-rpc.com/?api-key=<a server-side key>'\n : 'https://api.devnet.solana.com',\n inboxRelays: ['wss://relay.elisym.network', 'wss://nos.lol'],\n product: {\n d: 'my-product',\n title: 'My product',\n description: 'What the buyer gets.',\n priceUsd: '10',\n delivery: { method: 'access', value: 'https://example.com/<the link the buyer gets>' },\n },\n payouts: [{ caip19: usdc, address: '<your Solana wallet address>' }],\n };\n}\n","import { readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { MAX_FUTURE_SKEW_SECS } from '@elisym/commerce';\nimport { CATCH_UP_SECS } from './constants';\nimport type { Delivery } from './reply';\nimport type { TermsPeriod } from './terms';\n\n/** A direct-mode order as the merchant holds it. */\nexport interface MerchantOrder {\n /** `<buyer>:<orderId>`: an order id is the buyer's, so it is unique per buyer. */\n key: string;\n buyerPubkey: string;\n orderId: string;\n /** The order rumor: the same rumor again is a no-op, a different one is dropped. */\n rumorId: string;\n /** The rumor's `created_at`: it positions the payment scan, never the price. */\n createdAt: number;\n /** The Solana reference derived from (store, buyer, orderId). */\n reference: string;\n email?: string;\n /** Transactions the buyer reported (kind 17), at most `MAX_RECEIPTS_PER_ORDER`. */\n reportedTxs: string[];\n /** Reported transactions judged finally NOT a payment for this order: never checked again. */\n refusedTxs?: string[];\n /**\n * Tempo: reported hashes whose receipt showed no leg for this order. Not\n * rechecked by the sweep (a report of someone else's hash costs one read), but\n * a catch-up memo match lifts one: a receipt read and a log scan may be\n * answered by different backends.\n */\n noLegTxs?: string[];\n /** Tempo: catch-up matches whose verify said N for every term the leg could pay: not verified again. */\n tempoNoLeg?: string[];\n /** Tempo: a transfer to the payout that the recipient's policy blocked (the money sits with the guard). */\n blockedTx?: string;\n /** Queue position of each reported transaction: when it arrived, then when the sweep last checked it. */\n recheckedAt?: Record<string, number>;\n paid?: {\n signature: string;\n /** Decimal string of subunits the bound transfer paid. */\n amount: string;\n blockTime: number;\n caip19: string;\n medium: string;\n };\n /** Inbox relays that took the delivery so far: a retry goes to the others only. */\n deliveredTo?: string[];\n /** Set once the delivery counts as done (see `deliveryDone`). */\n deliveredAt?: number;\n}\n\n/** The answer the owner sent by hand for an order, exactly as sent (a rerun sends it again). */\nexport interface HandAnswer {\n kind: 'delivered' | 'refunded';\n delivery?: { method: Delivery['method']; value: string };\n tx?: string;\n amount?: string;\n /** What the ledger held for the order when it was closed. */\n reportedTxs: string[];\n refusedTxs: string[];\n noLegTxs: string[];\n}\n\nexport interface LedgerState {\n /** 2 once it holds Tempo data: an older node, which reads 0x hashes as Solana, refuses it. */\n version: 1 | 2;\n orders: Record<string, MerchantOrder>;\n /** Every rumor id already read (orders and receipts alike). */\n seenRumors: Record<string, true>;\n /** Keys of unpaid orders pruned after the catch-up window, or answered by hand: the id stays used. */\n closedOrders?: Record<string, true>;\n /** Orders the owner answered by hand (`deliver` / `refund`). */\n answeredByHand?: Record<string, HandAnswer>;\n /** Payment signature -> the order it paid: each payment credits one order, once. */\n claims: Record<string, string>;\n /** The store's own terms over time, as it published them. */\n terms: TermsPeriod[];\n /**\n * Seconds: the last moment every inbox relay was read through (stored wraps\n * paged to EOSE, live since). A restart reaches back from here, less the\n * two-day wrap back-dating. Never a wrap's own date: the sender sets that.\n */\n resumeAt?: number;\n /**\n * `<account>:<signature>` -> what a landed transaction on a payout account\n * binds: each is fetched and read once, however many orders are open.\n */\n scans: Record<string, ScannedTransaction>;\n /** The product id (`d`) the store published: another one would strand the old listing. */\n productD?: string;\n /** The payouts the owner's 10133 lists, and when it was signed: republished unchanged, it keeps its date. */\n payto?: { createdAt: number; payouts: string };\n}\n\nexport interface ScannedTransaction {\n blockTime: number;\n /** References with a transfer bound to them into the payout (pay-core's binding). */\n references: string[];\n}\n\nexport function emptyLedger(): LedgerState {\n return { version: 1, orders: {}, seenRumors: {}, claims: {}, terms: [], scans: {} };\n}\n\nexport function orderKey(buyerPubkey: string, orderId: string): string {\n return `${buyerPubkey}:${orderId}`;\n}\n\n/**\n * Claim `signature` for the order `key`: true when it is now (or already was)\n * that order's, false when another order holds it. The claim must be saved\n * before the delivery goes out.\n */\nexport function claimPayment(state: LedgerState, signature: string, key: string): boolean {\n const holder = state.claims[signature];\n if (holder !== undefined && holder !== key) {\n return false;\n }\n state.claims[signature] = key;\n return true;\n}\n\n/** Orders still waiting for a payment, within the catch-up window at `now`. */\nexport function openOrders(state: LedgerState, now: number, catchUpSecs: number): MerchantOrder[] {\n return Object.values(state.orders).filter(\n (order) => order.paid === undefined && now - order.createdAt <= catchUpSecs,\n );\n}\n\n/** Orders paid but not yet delivered: a crash between the two resumes here. */\nexport function undeliveredOrders(state: LedgerState): MerchantOrder[] {\n return Object.values(state.orders).filter(\n (order) => order.paid !== undefined && order.deliveredAt === undefined,\n );\n}\n\n/**\n * Drop unpaid orders past the catch-up window (and a skew allowance): nothing\n * scans for them any more, and anyone can post them for free. Their rumor ids\n * stay, so the same order rumor is still a no-op; paid orders always stay, so a\n * claim can never be re-credited to a recreated order.\n */\nexport function pruneExpiredOrders(state: LedgerState, now: number): void {\n for (const [key, order] of Object.entries(state.orders)) {\n if (order.paid === undefined && now - order.createdAt > CATCH_UP_SECS + MAX_FUTURE_SKEW_SECS) {\n delete state.orders[key];\n (state.closedOrders ??= {})[key] = true;\n }\n }\n}\n\n/**\n * Record a transaction the buyer reported for `order`, with its place in the\n * recheck queue: the time it arrived. The queue then runs first in, first out,\n * so reports arriving later - free to send - never go ahead of it.\n */\nexport function recordReport(order: MerchantOrder, tx: string, arrivedAt: number): void {\n order.reportedTxs.push(tx);\n order.recheckedAt = { ...order.recheckedAt, [tx]: arrivedAt };\n}\n\nexport function loadLedger(path: string): LedgerState {\n let text: string;\n try {\n text = readFileSync(path, 'utf8');\n } catch {\n return emptyLedger();\n }\n const state = JSON.parse(text) as LedgerState;\n if (state.version !== 1 && state.version !== 2) {\n throw new Error(`Unknown ledger version in ${path}`);\n }\n state.scans ??= {};\n return state;\n}\n\n/** The ledger now holds Tempo data: from here on only a node that reads it may load it. */\nexport function markTempo(state: LedgerState): void {\n state.version = 2;\n}\n\n/** Write the whole ledger, atomically: a crash leaves the old file or the new one, never half. */\nexport function saveLedger(path: string, state: LedgerState): void {\n const temporary = `${path}.tmp`;\n writeFileSync(temporary, `${JSON.stringify(state, null, 2)}\\n`, { mode: 0o600 });\n renameSync(temporary, path);\n}\n","import { type Signature, isSignature } from '@solana/kit';\n\n/** Whether `value` is a Solana signature: kit's own check throws on text outside base58. */\nexport function isSolanaSignature(value: string): value is Signature {\n try {\n return isSignature(value);\n } catch {\n return false;\n }\n}\n","/**\n * Answering an order by hand: the owner's remedy when \"contact the store\" is\n * the buyer's only way forward (a payment the node refused, a transaction that\n * reverted, a late approval). The rules are pure, so the CLI only sequences them:\n * the close is saved first, then the answer is published.\n */\nimport { type WrappedOrderMessage, buildOrderMessage, wrapOrderMessage } from '@elisym/commerce';\nimport { type HandAnswer, type LedgerState, markTempo } from './ledger';\nimport type { Delivery } from './reply';\nimport { isSolanaSignature } from './signature';\n\nexport type HandRequest =\n | { kind: 'delivered'; delivery: Delivery }\n | { kind: 'refunded'; tx: string; amount: string };\n\nexport type HandPlan =\n | {\n ok: true;\n /** The answer to send: the stored one on a rerun. */\n answer: HandAnswer;\n buyerPubkey: string;\n orderId: string;\n /** A rerun of an answer already saved: nothing is written again. */\n rerun: boolean;\n }\n | { ok: false; problem: string };\n\nconst TEMPO_HASH_RE = /^0x[0-9a-f]{64}$/;\nconst POSITIVE_SUBUNITS_RE = /^[1-9]\\d{0,38}$/;\n\n/** A refund transaction as the ledger spells payments: a Solana signature or a lowercase Tempo hash. */\nfunction isRefundTx(tx: string): boolean {\n return TEMPO_HASH_RE.test(tx) || isSolanaSignature(tx);\n}\n\n/**\n * Judge a hand answer for the order `key` (`<buyer>:<orderId>`): an unpaid\n * order still held, or a key closed by the prune or by an earlier hand answer.\n * A paid order is the node's to deliver; an unknown key is refused; an answer\n * already sent is re-sent as stored, and the opposite one is refused (a widget\n * that heard the first is terminal and would drop it).\n */\nexport function planHandAnswer(state: LedgerState, key: string, request: HandRequest): HandPlan {\n const [buyerPubkey, orderId] = key.split(':');\n if (buyerPubkey === undefined || orderId === undefined || key.split(':').length !== 2) {\n return { ok: false, problem: `${key} is not <buyer>:<orderId>` };\n }\n if (request.kind === 'refunded') {\n if (!isRefundTx(request.tx)) {\n return { ok: false, problem: 'the refund tx is neither a Solana signature nor a Tempo hash' };\n }\n if (!POSITIVE_SUBUNITS_RE.test(request.amount)) {\n return {\n ok: false,\n problem:\n 'the refund amount must be subunits above 0 (an unpaid order is released with deliver, never a zero refund)',\n };\n }\n }\n const stored = state.answeredByHand?.[key];\n if (stored !== undefined) {\n if (stored.kind !== request.kind) {\n return {\n ok: false,\n problem: `${key} was already answered as ${stored.kind}: the other answer is refused`,\n };\n }\n return { ok: true, answer: stored, buyerPubkey, orderId, rerun: true };\n }\n const order = state.orders[key];\n if (order === undefined && state.closedOrders?.[key] !== true) {\n return { ok: false, problem: `no order ${key} in the ledger` };\n }\n if (order?.paid !== undefined) {\n return {\n ok: false,\n problem: `${key} is paid: the node delivers it itself (a refund of a delivered order is not handled here)`,\n };\n }\n const answer: HandAnswer = {\n kind: request.kind,\n ...(request.kind === 'delivered'\n ? { delivery: { ...request.delivery } }\n : { tx: request.tx, amount: request.amount }),\n reportedTxs: [...(order?.reportedTxs ?? [])],\n refusedTxs: [...(order?.refusedTxs ?? [])],\n noLegTxs: [...(order?.noLegTxs ?? [])],\n };\n return { ok: true, answer, buyerPubkey, orderId, rerun: false };\n}\n\n/**\n * Close the order in the ledger: gone from `orders` (with everything kept on it),\n * its key closed - never credited, never reusable, also by a node older than\n * this command - and the answer kept as sent.\n */\nexport function applyHandAnswer(state: LedgerState, key: string, answer: HandAnswer): void {\n delete state.orders[key];\n (state.closedOrders ??= {})[key] = true;\n (state.answeredByHand ??= {})[key] = answer;\n if (answer.tx !== undefined && TEMPO_HASH_RE.test(answer.tx)) {\n markTempo(state);\n }\n}\n\n/** The signed status of a hand answer: `completed` with the delivery, or `cancelled` with the refund. */\nexport function buildHandAnswer(\n plan: Extract<HandPlan, { ok: true }>,\n storeSecretKey: Uint8Array,\n createdAt: number,\n): WrappedOrderMessage {\n const { answer } = plan;\n if (answer.kind === 'delivered' && answer.delivery === undefined) {\n throw new Error('A hand delivery carries what was delivered');\n }\n const rumor = buildOrderMessage(\n answer.kind === 'delivered'\n ? {\n type: 'status',\n buyerPubkey: plan.buyerPubkey,\n orderId: plan.orderId,\n status: 'completed',\n ...(answer.delivery === undefined ? {} : { delivery: answer.delivery }),\n }\n : {\n type: 'status',\n buyerPubkey: plan.buyerPubkey,\n orderId: plan.orderId,\n status: 'cancelled',\n refund: { tx: answer.tx ?? '', amount: answer.amount ?? '' },\n },\n createdAt,\n );\n return wrapOrderMessage(rumor, storeSecretKey, plan.buyerPubkey);\n}\n","import { randomBytes } from 'node:crypto';\nimport {\n chmodSync,\n linkSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n utimesSync,\n writeFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { generateSecretKey } from 'nostr-tools/pure';\nimport { bytesToHex, hexToBytes } from 'nostr-tools/utils';\nimport type { StoreKeys } from './store-events';\n\n/**\n * Where a merchant keeps its state: `config.json` (the operator's), `keys.json`\n * (the store and owner secret keys), `ledger.json`, `run.lock` and the\n * `nostr.json` a level A domain serves.\n */\nexport interface MerchantHome {\n dir: string;\n config: string;\n keys: string;\n ledger: string;\n lock: string;\n nostrJson: string;\n}\n\nexport const HOME_ENV = 'ELISYM_MERCHANT_HOME';\nconst DEFAULT_HOME_NAME = '.elisym-merchant';\n\n/** `--home <dir>`, else `$ELISYM_MERCHANT_HOME`, else `~/.elisym-merchant`. */\nexport function merchantHome(\n flag: string | undefined,\n env: Readonly<Record<string, string | undefined>> = process.env,\n): MerchantHome {\n const chosen = flag ?? env[HOME_ENV];\n const dir = resolve(\n chosen === undefined || chosen === '' ? join(homedir(), DEFAULT_HOME_NAME) : chosen,\n );\n return {\n dir,\n config: join(dir, 'config.json'),\n keys: join(dir, 'keys.json'),\n ledger: join(dir, 'ledger.json'),\n lock: join(dir, 'run.lock'),\n nostrJson: join(dir, 'nostr.json'),\n };\n}\n\n/** Create the home, readable by its owner only (it holds secret keys). */\nexport function ensureHome(home: MerchantHome): void {\n mkdirSync(home.dir, { recursive: true, mode: 0o700 });\n try {\n // One that already existed (a Docker volume, say) is narrowed too.\n chmodSync(home.dir, 0o700);\n } catch {\n // Not ours to change: the files in it are still written 0600.\n }\n}\n\nfunction isMissing(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\n/**\n * The store's keys. Only a missing file mints new ones (and only with\n * `create`): an unreadable one must never replace the store's identity.\n */\nexport function loadOrCreateKeys(home: MerchantHome, create: boolean): StoreKeys {\n let text: string | undefined;\n try {\n text = readFileSync(home.keys, 'utf8');\n } catch (error) {\n if (!isMissing(error)) {\n throw error;\n }\n }\n if (text !== undefined) {\n const stored = JSON.parse(text) as { store: string; owner: string };\n return { storeSecretKey: hexToBytes(stored.store), ownerSecretKey: hexToBytes(stored.owner) };\n }\n if (!create) {\n throw new Error(`no store keys in ${home.dir}: run init first`);\n }\n const keys = { storeSecretKey: generateSecretKey(), ownerSecretKey: generateSecretKey() };\n ensureHome(home);\n writeFileSync(\n home.keys,\n `${JSON.stringify({ store: bytesToHex(keys.storeSecretKey), owner: bytesToHex(keys.ownerSecretKey) })}\\n`,\n { mode: 0o600, flag: 'wx' },\n );\n return keys;\n}\n\n/** A lock nobody refreshed for this long was left by a process that is gone. */\nexport const LOCK_STALE_MS = 90_000;\n\n/** How often the holder refreshes its lock. */\nconst LOCK_HEARTBEAT_MS = 20_000;\n\n/**\n * Whether a running merchant holds the home: its lock was refreshed lately.\n * Freshness, not a PID: a PID says nothing across containers or hosts sharing\n * a mounted home (and in a container the node always has the same one).\n */\nexport function heldByRunningMerchant(home: MerchantHome, now: number = Date.now()): boolean {\n try {\n return now - statSync(home.lock).mtimeMs < LOCK_STALE_MS;\n } catch {\n return false;\n }\n}\n\nfunction createLock(home: MerchantHome, token: string): boolean {\n try {\n writeFileSync(home.lock, token, { flag: 'wx', mode: 0o600 });\n return true;\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'EEXIST') {\n return false;\n }\n throw error;\n }\n}\n\nfunction heldError(home: MerchantHome): Error {\n return new Error(\n `another merchant holds ${home.lock}; a node that stopped without releasing it frees it ${LOCK_STALE_MS / 1000} s after its last refresh`,\n );\n}\n\n/**\n * Take the home for this process: refreshed while it runs, released on exit.\n * A stale lock is moved aside under a name of this process's own first, so of\n * two processes breaking it at once only one goes on; one that turns out fresh\n * (taken meanwhile) is put back.\n */\nexport function takeLock(\n home: MerchantHome,\n options: {\n /**\n * Called when the lock turned out not to be this process's any more (it was\n * stopped past `LOCK_STALE_MS` and another took the home): by default it\n * exits, since its ledger in memory would overwrite the other's.\n */\n onLost?: () => void;\n /** When the existing lock is judged; tests move it. */\n judgedAt?: number;\n } = {},\n): () => void {\n ensureHome(home);\n const token = `${process.pid}-${randomBytes(8).toString('hex')}`;\n if (!createLock(home, token)) {\n if (heldByRunningMerchant(home, options.judgedAt)) {\n throw heldError(home);\n }\n const aside = `${home.lock}.${token}`;\n try {\n renameSync(home.lock, aside);\n } catch {\n throw heldError(home);\n }\n if (Date.now() - statSync(aside).mtimeMs < LOCK_STALE_MS) {\n try {\n linkSync(aside, home.lock);\n } catch {\n // Someone holds the name again: that lock stands.\n }\n rmSync(aside, { force: true });\n throw heldError(home);\n }\n rmSync(aside, { force: true });\n if (!createLock(home, token)) {\n throw heldError(home);\n }\n }\n const ours = () => {\n try {\n return readFileSync(home.lock, 'utf8') === token;\n } catch {\n return false;\n }\n };\n const onLost =\n options.onLost ??\n (() => {\n console.error(`error: ${home.lock} was taken by another process; stopping`);\n process.exit(1);\n });\n const heartbeat = setInterval(() => {\n try {\n if (!ours()) {\n clearInterval(heartbeat);\n onLost();\n return;\n }\n const now = new Date();\n utimesSync(home.lock, now, now);\n } catch {\n // Gone between the read and the touch: the next beat finds it lost.\n }\n }, LOCK_HEARTBEAT_MS);\n heartbeat.unref();\n const release = () => {\n clearInterval(heartbeat);\n process.removeListener('exit', release);\n if (ours()) {\n rmSync(home.lock, { force: true });\n }\n };\n process.once('exit', release);\n return release;\n}\n","import { TERMS_WINDOW_SECS } from './constants';\n\n/** What the store asked for one product in one coin: pay `amount` to `payout`. */\nexport interface OfferTerms {\n /** CAIP-19 id of the coin. */\n caip19: string;\n /** The owner's payout address for it (the wallet, not a token account). */\n payout: string;\n /** Decimal string of the coin's subunits (quantity 1). */\n amount: string;\n}\n\n/** Terms as published, and when they were replaced (absent while they stand). */\nexport interface TermsPeriod {\n terms: OfferTerms;\n /** Seconds: when the store published these terms. */\n from: number;\n /** Seconds: when newer terms replaced them. */\n until?: number;\n}\n\nfunction sameTerms(left: OfferTerms, right: OfferTerms): boolean {\n return (\n left.caip19 === right.caip19 && left.payout === right.payout && left.amount === right.amount\n );\n}\n\n/**\n * Record newly published terms for their coin: the standing terms of that coin\n * end now. Publishing the same terms again changes nothing.\n */\nexport function publishTerms(\n periods: readonly TermsPeriod[],\n terms: OfferTerms,\n at: number,\n): TermsPeriod[] {\n const standing = periods.find(\n (period) => period.until === undefined && period.terms.caip19 === terms.caip19,\n );\n if (standing !== undefined && sameTerms(standing.terms, terms)) {\n return [...periods];\n }\n return [\n ...periods.map((period) =>\n period === standing ? { ...period, until: Math.max(at, period.from) } : period,\n ),\n { terms, from: at },\n ];\n}\n\n/**\n * End the standing terms of every coin not in `offered`: a coin dropped from the\n * offer stops being payable once the window after `at` has passed.\n */\nexport function retireTerms(\n periods: readonly TermsPeriod[],\n offered: readonly string[],\n at: number,\n): TermsPeriod[] {\n return periods.map((period) =>\n period.until === undefined && !offered.includes(period.terms.caip19)\n ? { ...period, until: Math.max(at, period.from) }\n : period,\n );\n}\n\n/**\n * Every set of terms a payment made at `blockTime` may pay: offered at some\n * moment between `blockTime - TERMS_WINDOW_SECS` and `blockTime`. The window\n * hangs on the block time, which the chain sets - never on the order's\n * `created_at`, which the buyer signs: a back-dated order must not reach an\n * older, cheaper price.\n */\nexport function termsAt(periods: readonly TermsPeriod[], blockTime: number): OfferTerms[] {\n const earliest = blockTime - TERMS_WINDOW_SECS;\n const found: OfferTerms[] = [];\n for (const period of periods) {\n const offered =\n period.from <= blockTime && (period.until === undefined || period.until > earliest);\n if (offered && !found.some((terms) => sameTerms(terms, period.terms))) {\n found.push(period.terms);\n }\n }\n return found;\n}\n\n/** Every distinct set of terms still in reach of a payment made at or after `since`. */\nexport function termsSince(periods: readonly TermsPeriod[], since: number): OfferTerms[] {\n const earliest = since - TERMS_WINDOW_SECS;\n const found: OfferTerms[] = [];\n for (const period of periods) {\n if (\n (period.until === undefined || period.until > earliest) &&\n !found.some((terms) => sameTerms(terms, period.terms))\n ) {\n found.push(period.terms);\n }\n }\n return found;\n}\n\n/** The terms standing now: the newest of each coin, not yet replaced. */\nexport function standingTerms(periods: readonly TermsPeriod[]): OfferTerms[] {\n return periods.filter((period) => period.until === undefined).map((period) => period.terms);\n}\n\n/**\n * The terms buyers can read once a publish went out in part: the coins and\n * price of the listing (`listingOut`: the new ones, else the standing ones),\n * paid to the addresses of the payout list (`payoutsOut`: the new ones, else\n * the standing ones). A coin with no payout on either side cannot be paid.\n */\nexport function visibleTerms(\n standing: readonly OfferTerms[],\n next: readonly OfferTerms[],\n listingOut: boolean,\n payoutsOut: boolean,\n): OfferTerms[] {\n const listed = listingOut ? next : standing;\n const payouts = payoutsOut ? next : standing;\n const visible: OfferTerms[] = [];\n for (const { caip19, amount } of listed) {\n const payout = payouts.find((terms) => terms.caip19 === caip19)?.payout;\n if (payout !== undefined) {\n visible.push({ caip19, payout, amount });\n }\n }\n return visible;\n}\n","/**\n * Verifying Tempo payments for direct-mode orders: the merchant side of the\n * contract. A payment is bound to the order by its derived memo, pays terms the\n * store offered within the window before the leg's block time, lands at or\n * above the order's floor, and is claimed once by its settlement id.\n *\n * A reported hash is pre-read (one receipt) before any full verify, so a report\n * of someone else's hash costs one read; catch-up finds payments by memo per\n * (coin, payout address), never one scan per order.\n */\nimport { deriveOrderPaymentReference, parseCaip19 } from '@elisym/commerce';\nimport { type ChainConfig, type ParsedPaymentRequestV2, chainByCaip2 } from '@elisym/pay-core';\nimport {\n type Eip1193Client,\n type TempoTransferLog,\n composeTempoPaymentRequest,\n createJsonRpcClient,\n listTempoLogs,\n readBlockByNumber,\n readFinalizedBlock,\n readTempoReceiptLegs,\n verifyTempoPayment,\n} from '@elisym/pay-core/evm';\nimport type { MerchantConfig } from './config';\nimport { CATCH_UP_SECS, MAX_RECHECKS_PER_SWEEP, ORDER_SCAN_MARGIN_SECS } from './constants';\nimport {\n type LedgerState,\n type MerchantOrder,\n claimPayment,\n markTempo,\n openOrders,\n} from './ledger';\nimport type { CatchUpResult, PaymentCheck } from './solana';\nimport { type OfferTerms, termsAt, termsSince } from './terms';\n\nexport interface TempoContext {\n client: Eip1193Client;\n chain: ChainConfig;\n /** The receipt medium of the chain: `tempo` or `tempo-moderato`. */\n medium: string;\n storePubkey: string;\n /** Block timestamps read so far (a restart costs a few binary-search reads). */\n samples?: Map<number, number>;\n}\n\n/** How a reported Tempo hash came out, beyond Solana's verdicts. */\nexport type TempoCheck =\n | PaymentCheck\n /** Its receipt (or every term's verify) showed no leg for this order: set aside, not refused. */\n | { kind: 'no_leg' }\n /** A transfer to the payout that the recipient's policy blocked: noted for the owner. */\n | { kind: 'blocked' };\n\n/**\n * The Tempo context of a config with a `tempo` block: its chain from the\n * registry, the operator's RPC or the chain's public one, and the medium.\n */\nexport function tempoContextFor(\n config: Pick<MerchantConfig, 'tempo'>,\n storePubkey: string,\n): TempoContext | undefined {\n if (config.tempo === undefined) {\n return undefined;\n }\n const chain = chainByCaip2(config.tempo.network === 'mainnet' ? 'eip155:4217' : 'eip155:42431');\n const url = config.tempo.rpcUrl ?? chain?.rpcUrls[0];\n if (chain === undefined || url === undefined) {\n return undefined;\n }\n return {\n client: createJsonRpcClient(url),\n chain,\n medium: config.tempo.network === 'mainnet' ? 'tempo' : 'tempo-moderato',\n storePubkey,\n };\n}\n\n/** Block timestamps kept at most (the binary search's cache). */\nconst MAX_BLOCK_SAMPLES = 10_000;\n\n/** A Tempo hash as the ledger keeps it: one spelling. */\nexport const TEMPO_HASH_RE = /^0x[0-9a-f]{64}$/;\n\n/** The rumor may be dated up to 15 minutes ahead: the scan starts this far before it. */\nconst FLOOR_MARGIN_SECS = Math.max(ORDER_SCAN_MARGIN_SECS, 900);\n\nexport function tempoMemo(order: MerchantOrder, storePubkey: string): string {\n return deriveOrderPaymentReference({\n storePubkey,\n buyerPubkey: order.buyerPubkey,\n orderId: order.orderId,\n }).tempo;\n}\n\ninterface TempoTerms {\n terms: OfferTerms;\n token: string;\n}\n\nfunction tempoTerms(terms: readonly OfferTerms[], context: TempoContext): TempoTerms[] {\n return terms.flatMap((each) => {\n const caip19 = parseCaip19(each.caip19);\n const mint = caip19?.asset.mint;\n if (caip19?.chain.caip2 !== context.chain.caip2 || mint === undefined) {\n return [];\n }\n return [{ terms: each, token: mint.toLowerCase() }];\n });\n}\n\nasync function blockTime(context: TempoContext, number: number): Promise<number | undefined> {\n const cached = context.samples?.get(number);\n if (cached !== undefined) {\n return cached;\n }\n const block = await readBlockByNumber(context.client, number);\n if (block === null) {\n return undefined;\n }\n const samples = (context.samples ??= new Map());\n // Bounded: a restart costs a few binary-search reads, never unbounded memory.\n if (samples.size >= MAX_BLOCK_SAMPLES) {\n samples.clear();\n }\n samples.set(number, block.timestamp);\n return block.timestamp;\n}\n\n/**\n * The newest finalized block at or before `time`, clamped to the catch-up\n * lookback: a binary search over block timestamps. `undefined` when the chain\n * could not be read.\n */\nexport async function blockAtTime(\n context: TempoContext,\n time: number,\n): Promise<{ number: number; timestamp: number } | undefined> {\n const head = await readFinalizedBlock(context.client);\n if (head === null) {\n return undefined;\n }\n const target = Math.max(time, head.timestamp - CATCH_UP_SECS - FLOOR_MARGIN_SECS);\n if (head.timestamp <= target) {\n return head;\n }\n // Start from the closest samples already read around the target: a sweep's\n // searches for nearby times then cost a few reads, not a full search each.\n let low = 0;\n let high = head.number;\n let found = { number: 0, timestamp: 0 };\n for (const [number, at] of context.samples ?? []) {\n if (number > high || number < low) {\n continue;\n }\n if (at <= target && number >= low) {\n low = number;\n found = { number, timestamp: at };\n } else if (at > target && number <= high) {\n high = number;\n }\n }\n while (low <= high) {\n const middle = Math.floor((low + high) / 2);\n const at = await blockTime(context, middle);\n if (at === undefined) {\n return undefined;\n }\n if (at <= target) {\n found = { number: middle, timestamp: at };\n low = middle + 1;\n } else {\n high = middle - 1;\n }\n }\n return found;\n}\n\n/** The floor of an order's scan: the finalized block at its `created_at` less the margin. */\nexport function orderFloor(context: TempoContext, order: MerchantOrder) {\n return blockAtTime(context, order.createdAt - FLOOR_MARGIN_SECS);\n}\n\ntype TermVerdict = 'paid' | 'ask' | 'refused' | 'no_leg' | 'claimed';\n\n/**\n * Verify `hash` for `order` against each candidate term. Any PAID credits;\n * else any ASK asks again (it wins over refusals, as on Solana); else all R\n * refuses; else (N, or a mix of R and N) there is no leg. `satisfies` marks the\n * terms a leg the caller already decoded could pay: an N for one of those\n * contradicts the caller's own read and counts as ASK.\n */\nasync function verifyTerms(\n state: LedgerState,\n order: MerchantOrder,\n hash: string,\n context: TempoContext,\n candidates: readonly TempoTerms[],\n floor: { number: number; timestamp: number },\n satisfies: (terms: TempoTerms) => boolean,\n): Promise<TermVerdict> {\n const memo = tempoMemo(order, context.storePubkey);\n const verdicts: TermVerdict[] = [];\n for (const candidate of candidates) {\n const caip19 = parseCaip19(candidate.terms.caip19);\n if (caip19 === undefined) {\n continue;\n }\n let request: ParsedPaymentRequestV2;\n try {\n request = composeTempoPaymentRequest({\n chain: context.chain,\n asset: caip19.asset,\n recipient: candidate.terms.payout,\n amount: BigInt(candidate.terms.amount),\n feeBps: 0,\n treasury: candidate.terms.payout,\n memo,\n createdAt: floor.timestamp,\n });\n } catch {\n continue;\n }\n const result = await verifyTempoPayment(context.client, request, {\n txSignature: hash,\n fromBlock: floor.number,\n pollBudgetMs: 0,\n });\n if (result.outcome === 'verified') {\n const leg: TempoTransferLog = result.providerLeg;\n const at = await blockTime(context, leg.blockNumber);\n if (at === undefined) {\n verdicts.push('ask');\n continue;\n }\n const offered = termsAt(state.terms, at).some(\n (standing) =>\n standing.caip19 === candidate.terms.caip19 &&\n standing.payout === candidate.terms.payout &&\n standing.amount === candidate.terms.amount,\n );\n if (leg.blockNumber < floor.number || !offered) {\n verdicts.push('refused');\n continue;\n }\n if (!claimPayment(state, result.settlementId, order.key)) {\n return 'claimed';\n }\n markTempo(state);\n order.paid = {\n signature: leg.transactionHash,\n amount: leg.amount.toString(),\n blockTime: at,\n caip19: candidate.terms.caip19,\n medium: context.medium,\n };\n return 'paid';\n }\n if (\n result.outcome === 'refused' &&\n (result.code === 'reverted' || result.code === 'no_provider_leg')\n ) {\n verdicts.push(satisfies(candidate) ? 'ask' : 'no_leg');\n continue;\n }\n verdicts.push('ask');\n }\n if (verdicts.includes('ask')) {\n return 'ask';\n }\n if (verdicts.length > 0 && verdicts.every((verdict) => verdict === 'refused')) {\n return 'refused';\n }\n return 'no_leg';\n}\n\nfunction asCheck(verdict: TermVerdict, order: MerchantOrder): TempoCheck {\n switch (verdict) {\n case 'paid':\n return { kind: 'paid', order };\n case 'claimed':\n return { kind: 'refused', reason: 'claimed_by_another_order' };\n case 'refused':\n return { kind: 'refused', reason: 'not_a_payment_for_this_order' };\n case 'no_leg':\n return { kind: 'no_leg' };\n case 'ask':\n return { kind: 'ask_again' };\n }\n return { kind: 'ask_again' };\n}\n\n/**\n * Check one hash a buyer reported for `order`. The receipt is read first\n * (trusted as a verify by hash trusts one): no receipt asks again, a trusted\n * receipt with no leg for this order sets the hash aside (`no_leg`), a guard log\n * with no transfer notes `blocked`. Only a hash with a leg is verified in full.\n */\nexport async function checkTempoPayment(\n state: LedgerState,\n order: MerchantOrder,\n hash: string,\n context: TempoContext,\n): Promise<TempoCheck> {\n if (order.paid !== undefined) {\n return order.paid.signature === hash\n ? { kind: 'paid', order }\n : { kind: 'refused', reason: 'order_already_paid' };\n }\n const candidates = tempoTerms(\n termsSince(state.terms, order.createdAt - ORDER_SCAN_MARGIN_SECS),\n context,\n );\n if (candidates.length === 0) {\n return { kind: 'refused', reason: 'not_a_payment_for_this_order' };\n }\n const minAmount = candidates.reduce(\n (lowest, candidate) =>\n BigInt(candidate.terms.amount) < lowest ? BigInt(candidate.terms.amount) : lowest,\n BigInt(candidates[0]?.terms.amount ?? '0'),\n );\n const pre = await readTempoReceiptLegs(context.client, hash, {\n chain: context.chain,\n tokens: [...new Set(candidates.map((candidate) => candidate.token))],\n recipients: [...new Set(candidates.map((candidate) => candidate.terms.payout))],\n memo: tempoMemo(order, context.storePubkey),\n minAmount,\n });\n if (pre.kind === 'unreadable' || pre.kind === 'absent') {\n return { kind: 'ask_again' };\n }\n if (pre.kind === 'none') {\n return { kind: 'no_leg' };\n }\n // Transfer legs first: only a receipt with none of them is a blocked note.\n const named = candidates.filter((candidate) =>\n pre.transfers.some((leg) => leg.token === candidate.token && leg.to === candidate.terms.payout),\n );\n if (named.length === 0) {\n if (pre.blocked.length > 0) {\n order.blockedTx = hash;\n markTempo(state);\n return { kind: 'blocked' };\n }\n return { kind: 'no_leg' };\n }\n const floor = await orderFloor(context, order);\n if (floor === undefined) {\n return { kind: 'ask_again' };\n }\n return asCheck(await verifyTerms(state, order, hash, context, named, floor, () => false), order);\n}\n\n/** Keep what a reported hash came out as: refused and set-aside hashes are not rechecked. */\nexport function recordTempoCheck(\n state: LedgerState,\n order: MerchantOrder,\n hash: string,\n check: TempoCheck,\n): void {\n if (check.kind === 'refused') {\n order.refusedTxs = [...(order.refusedTxs ?? []), hash];\n } else if (check.kind === 'no_leg' && order.noLegTxs?.includes(hash) !== true) {\n order.noLegTxs = [...(order.noLegTxs ?? []), hash];\n }\n markTempo(state);\n}\n\n/**\n * Catch up on every open order at once, per (coin, payout address): one memo\n * scan from the oldest open order's floor, matched locally against the open\n * orders' derived memos. A match goes straight to verify (no pre-read), also\n * when its hash sits in `noLegTxs`; an order's cached N for that hash is not\n * verified again; an ASK is verified again, oldest check first, within the\n * sweep's budget.\n */\nexport async function catchUpTempo(\n state: LedgerState,\n context: TempoContext,\n now: number,\n): Promise<CatchUpResult> {\n const result: CatchUpResult = { paid: [], incomplete: [] };\n const open = openOrders(state, now, CATCH_UP_SECS);\n if (open.length === 0) {\n return result;\n }\n // Reported hashes still to judge (asked again), first in first out, within the budget.\n const reported: { order: MerchantOrder; hash: string; checkedAt: number }[] = [];\n for (const order of open) {\n for (const hash of order.reportedTxs) {\n if (\n TEMPO_HASH_RE.test(hash) &&\n order.refusedTxs?.includes(hash) !== true &&\n order.noLegTxs?.includes(hash) !== true &&\n order.blockedTx !== hash\n ) {\n reported.push({ order, hash, checkedAt: order.recheckedAt?.[hash] ?? 0 });\n }\n }\n }\n reported.sort((left, right) => left.checkedAt - right.checkedAt);\n for (const { order, hash } of reported.slice(0, MAX_RECHECKS_PER_SWEEP)) {\n if (order.paid !== undefined) {\n continue;\n }\n order.recheckedAt = { ...order.recheckedAt, [hash]: now };\n const check = await checkTempoPayment(state, order, hash, context);\n recordTempoCheck(state, order, hash, check);\n if (check.kind === 'paid') {\n result.paid.push(order);\n }\n }\n const oldest = Math.min(...open.map((order) => order.createdAt));\n const candidates = tempoTerms(termsSince(state.terms, oldest - ORDER_SCAN_MARGIN_SECS), context);\n if (candidates.length === 0) {\n return result;\n }\n const floor = await blockAtTime(context, oldest - FLOOR_MARGIN_SECS);\n if (floor === undefined) {\n return result;\n }\n const byMemo = new Map(open.map((order) => [tempoMemo(order, context.storePubkey), order]));\n const matches: { order: MerchantOrder; leg: TempoTransferLog; checkedAt: number }[] = [];\n const pairs = new Map<string, TempoTerms[]>();\n for (const candidate of candidates) {\n const key = `${candidate.token}:${candidate.terms.payout}`;\n pairs.set(key, [...(pairs.get(key) ?? []), candidate]);\n }\n for (const [key, terms] of pairs) {\n const [token, payout] = key.split(':') as [string, string];\n const minAmount = terms.reduce(\n (lowest, each) => (BigInt(each.terms.amount) < lowest ? BigInt(each.terms.amount) : lowest),\n BigInt(terms[0]?.terms.amount ?? '0'),\n );\n const scan = await listTempoLogs(context.client, {\n token,\n event: 'TransferWithMemo',\n to: payout,\n fromBlock: floor.number,\n minAmount,\n });\n if (!scan.complete) {\n result.incomplete.push(`${context.chain.caip2} ${token} ${payout}`);\n }\n for (const leg of scan.candidates) {\n const order = leg.memo === undefined ? undefined : byMemo.get(leg.memo);\n if (\n order === undefined ||\n order.paid !== undefined ||\n order.refusedTxs?.includes(leg.transactionHash) === true ||\n order.tempoNoLeg?.includes(leg.transactionHash) === true\n ) {\n continue;\n }\n matches.push({ order, leg, checkedAt: order.recheckedAt?.[leg.transactionHash] ?? 0 });\n }\n }\n matches.sort((left, right) => left.checkedAt - right.checkedAt);\n for (const { order, leg } of matches.slice(0, MAX_RECHECKS_PER_SWEEP)) {\n if (order.paid !== undefined) {\n continue;\n }\n const hash = leg.transactionHash;\n order.recheckedAt = { ...order.recheckedAt, [hash]: now };\n const orderFloorBlock = await orderFloor(context, order);\n if (orderFloorBlock === undefined) {\n continue;\n }\n const orderTerms = tempoTerms(\n termsSince(state.terms, order.createdAt - ORDER_SCAN_MARGIN_SECS),\n context,\n );\n const verdict = await verifyTerms(\n state,\n order,\n hash,\n context,\n orderTerms,\n orderFloorBlock,\n (candidate) =>\n candidate.token === leg.token &&\n candidate.terms.payout === leg.to &&\n leg.amount >= BigInt(candidate.terms.amount),\n );\n markTempo(state);\n // A match lifts a hash the pre-read set aside.\n if (order.noLegTxs?.includes(hash) === true) {\n order.noLegTxs = order.noLegTxs.filter((each) => each !== hash);\n }\n if (verdict === 'paid') {\n result.paid.push(order);\n } else if (verdict === 'refused') {\n order.refusedTxs = [...(order.refusedTxs ?? []), hash];\n } else if (verdict === 'no_leg') {\n order.tempoNoLeg = [...(order.tempoNoLeg ?? []), hash];\n }\n }\n return result;\n}\n","import {\n type UnwrappedOrderMessage,\n deriveOrderPaymentReference,\n productAddress,\n} from '@elisym/commerce';\nimport { EARLIEST_ORDER_SECS, MAX_RECEIPTS_PER_ORDER } from './constants';\nimport { type LedgerState, type MerchantOrder, markTempo, orderKey, recordReport } from './ledger';\nimport { isSolanaSignature } from './signature';\nimport { TEMPO_HASH_RE } from './tempo';\n\nexport interface StoreIdentity {\n storePubkey: string;\n /** The one product this store sells in direct mode: `30402:<store>:<d>`. */\n productAddress: string;\n /** Receipt mediums the store takes, e.g. `solana-devnet`. */\n mediums: readonly string[];\n}\n\nexport type IntakeResult =\n | { kind: 'ignored'; reason: IgnoreReason }\n | { kind: 'order'; order: MerchantOrder }\n /** `isNew`: the order had not reported this transaction before. */\n | { kind: 'receipt'; order: MerchantOrder; tx: string; isNew: boolean };\n\nexport type IgnoreReason =\n /** The same rumor again (a resumed widget republishes it byte for byte). */\n | 'seen'\n /** Addressed to another key, or naming another store. */\n | 'not_for_this_store'\n /** Not one item of this store's own product at quantity 1, or dated before any payment could be. */\n | 'not_a_direct_order'\n /** A different order rumor under an order id this buyer already used here: dropped silently. */\n | 'order_id_reused'\n /** A receipt for an order this store does not hold. */\n | 'unknown_order'\n /** A receipt under another reference, on a rail the store does not take, or naming no transaction. */\n | 'foreign_payment'\n /** More receipts for one order than the store keeps. */\n | 'too_many_receipts'\n /** A message type the merchant does not act on (status, payment request). */\n | 'not_handled';\n\nexport function storeIdentity(\n storePubkey: string,\n d: string,\n mediums: readonly string[],\n): StoreIdentity {\n return { storePubkey, productAddress: productAddress({ storePubkey, d }), mediums };\n}\n\n/**\n * Take one unwrapped order message into the ledger. The buyer is the SEAL\n * signer (`senderPubkey`), never the one-time wrap key; the reference is\n * derived here, never taken from the buyer.\n */\nexport function intake(\n state: LedgerState,\n unwrapped: UnwrappedOrderMessage,\n store: StoreIdentity,\n now: number = Math.floor(Date.now() / 1000),\n): IntakeResult {\n if (state.seenRumors[unwrapped.rumorId] === true) {\n return { kind: 'ignored', reason: 'seen' };\n }\n const { message } = unwrapped;\n if (unwrapped.recipientPubkey !== store.storePubkey) {\n return { kind: 'ignored', reason: 'not_for_this_store' };\n }\n if (message.type === 'order') {\n if (message.storePubkey !== store.storePubkey) {\n return { kind: 'ignored', reason: 'not_for_this_store' };\n }\n const [item, ...rest] = message.items;\n if (\n unwrapped.createdAt < EARLIEST_ORDER_SECS ||\n item === undefined ||\n rest.length > 0 ||\n item.product !== store.productAddress ||\n item.quantity !== 1\n ) {\n return { kind: 'ignored', reason: 'not_a_direct_order' };\n }\n const key = orderKey(unwrapped.senderPubkey, message.orderId);\n state.seenRumors[unwrapped.rumorId] = true;\n if (state.orders[key] !== undefined || state.closedOrders?.[key] === true) {\n return { kind: 'ignored', reason: 'order_id_reused' };\n }\n const reference = deriveOrderPaymentReference({\n storePubkey: store.storePubkey,\n buyerPubkey: unwrapped.senderPubkey,\n orderId: message.orderId,\n });\n const order: MerchantOrder = {\n key,\n buyerPubkey: unwrapped.senderPubkey,\n orderId: message.orderId,\n rumorId: unwrapped.rumorId,\n createdAt: unwrapped.createdAt,\n reference: reference.solana,\n reportedTxs: [],\n ...(message.email === undefined ? {} : { email: message.email }),\n };\n state.orders[key] = order;\n return { kind: 'order', order };\n }\n if (message.type === 'receipt') {\n if (message.storePubkey !== store.storePubkey) {\n return { kind: 'ignored', reason: 'not_for_this_store' };\n }\n const order = state.orders[orderKey(unwrapped.senderPubkey, message.orderId)];\n if (order === undefined) {\n return { kind: 'ignored', reason: 'unknown_order' };\n }\n const { medium, reference, tx } = message.payment;\n // The medium names the rail, and the rail decides the reference and the tx\n // spelling: a Tempo receipt carries this order's memo and a lowercase hash.\n const tempo = medium.startsWith('tempo');\n const expected = tempo\n ? deriveOrderPaymentReference({\n storePubkey: store.storePubkey,\n buyerPubkey: order.buyerPubkey,\n orderId: order.orderId,\n }).tempo\n : order.reference;\n if (\n reference !== expected ||\n !store.mediums.includes(medium) ||\n !(tempo ? TEMPO_HASH_RE.test(tx) : isSolanaSignature(tx))\n ) {\n return { kind: 'ignored', reason: 'foreign_payment' };\n }\n if (!order.reportedTxs.includes(tx) && order.reportedTxs.length >= MAX_RECEIPTS_PER_ORDER) {\n return { kind: 'ignored', reason: 'too_many_receipts' };\n }\n state.seenRumors[unwrapped.rumorId] = true;\n const isNew = !order.reportedTxs.includes(tx);\n if (isNew) {\n recordReport(order, tx, now);\n if (tempo) {\n markTempo(state);\n }\n }\n return { kind: 'receipt', order, tx, isNew };\n }\n return { kind: 'ignored', reason: 'not_handled' };\n}\n","import { KIND_GIFT_WRAP, MAX_FUTURE_SKEW_SECS } from '@elisym/commerce';\nimport type { Filter, NostrEvent } from 'nostr-tools';\nimport type { EventTemplate, VerifiedEvent } from 'nostr-tools/pure';\nimport { RESUBSCRIBE_BACKOFF_MS, WRAP_BACKDATE_SECS } from './constants';\n\n/** The close reason nostr-tools gives a `subscribeEose` that reached EOSE (or its own timeout). */\nconst EOSE_CLOSE_REASON = 'closed automatically on eose';\n\n/** How long one backfill page may take before it counts as not read. */\nexport const PAGE_WAIT_MS = 30_000;\n\n/**\n * Passed as `maxWait`: longer than `PAGE_WAIT_MS`, so the library's own EOSE\n * timeout - which it reports exactly like a real EOSE - never ends a page first.\n */\nconst LIBRARY_WAIT_MS = PAGE_WAIT_MS + 15_000;\n\n/** A failed backfill is tried again after this long, while its subscription is open. */\nconst BACKFILL_RETRY_MS = 30_000;\n\ninterface SubscribeParams {\n maxWait?: number;\n onauth?: (template: EventTemplate) => Promise<VerifiedEvent>;\n onevent: (event: NostrEvent) => void;\n oneose?: () => void;\n onclose?: (reasons: string[]) => void;\n}\n\n/** The part of nostr-tools' `SimplePool` the listener uses. */\nexport interface ListenerPool {\n subscribe(relays: string[], filter: Filter, params: SubscribeParams): { close(): void };\n subscribeEose(relays: string[], filter: Filter, params: SubscribeParams): { close(): void };\n}\n\nexport interface ListenerOptions {\n pool: ListenerPool;\n storePubkey: string;\n auth: (template: EventTemplate) => Promise<VerifiedEvent>;\n onWrap: (wrap: NostrEvent) => void;\n log: (message: string) => void;\n now: () => number;\n /** Timers, so tests can run them; returns a cancel function. */\n setTimer?: (task: () => void, ms: number) => () => void;\n}\n\n/**\n * The resume point after a sweep: the moment it was queued, if every inbox\n * relay was read through and live then (every wrap received earlier is ahead of\n * the sweep on the queue); otherwise the old one stays.\n */\nexport function resumePointAfterSweep(\n allLive: boolean,\n queuedAt: number,\n current: number | undefined,\n): number | undefined {\n return allLive ? queuedAt : current;\n}\n\n/**\n * Wrap ids already handed on, dropped once older than any read could reach:\n * a wrap read again (the live burst overlapping the backfill, a reconnect\n * re-reading its window) is not unwrapped a second time.\n */\nexport class SeenWraps {\n private readonly seen = new Map<string, number>();\n\n /** True the first time a wrap id is offered, false after. */\n admit(wrap: Pick<NostrEvent, 'id' | 'created_at'>): boolean {\n if (this.seen.has(wrap.id)) {\n return false;\n }\n this.seen.set(wrap.id, wrap.created_at);\n return true;\n }\n\n /** Let a wrap be offered again (one that could not be acted on yet). */\n forget(id: string): void {\n this.seen.delete(id);\n }\n\n /** Forget wraps dated before `oldestReadable`: no read reaches them any more. */\n prune(oldestReadable: number): void {\n for (const [id, createdAt] of this.seen) {\n if (createdAt < oldestReadable) {\n this.seen.delete(id);\n }\n }\n }\n\n get size(): number {\n return this.seen.size;\n }\n}\n\n/**\n * Where a read that must reach every wrap sent since `from` starts: NIP-59\n * dates each wrap at a random moment up to two days back, and the rumor inside\n * may be dated up to the skew allowance ahead.\n */\nexport function readSince(from: number): number {\n return from - WRAP_BACKDATE_SECS - MAX_FUTURE_SKEW_SECS;\n}\n\nexport function wrapFilter(storePubkey: string, since: number, until?: number): Filter {\n return {\n kinds: [KIND_GIFT_WRAP],\n '#p': [storePubkey],\n since,\n ...(until === undefined ? {} : { until }),\n };\n}\n\n/**\n * The next backfill page after one that returned `received` wraps, the oldest\n * dated `oldest`, or `undefined` when the history down to `since` is read.\n * `until` is inclusive: a page that did not move below `until` (a flood of\n * wraps sharing one second) steps one second down rather than stopping.\n */\nexport function nextPageUntil(\n since: number,\n until: number,\n received: number,\n oldest: number,\n): number | undefined {\n if (received === 0 || oldest <= since) {\n return undefined;\n }\n const next = oldest < until ? oldest : until - 1;\n return next > since ? next : undefined;\n}\n\n/**\n * One subscription per store inbox relay, kept alive, plus a paged backfill of\n * what the relay stored before it opened. A relay counts as read through only\n * once a backfill reached a genuine end on a subscription that is still open.\n */\nexport class InboxListener {\n private readonly live = new Set<string>();\n private readonly attempts = new Map<string, number>();\n private readonly setTimer: (task: () => void, ms: number) => () => void;\n\n constructor(private readonly options: ListenerOptions) {\n this.setTimer =\n options.setTimer ??\n ((task, ms) => {\n const handle = setTimeout(task, ms);\n return () => clearTimeout(handle);\n });\n }\n\n /** Whether every one of `relays` is currently read through and listening. */\n allLive(relays: readonly string[]): boolean {\n return relays.every((relay) => this.live.has(relay));\n }\n\n isLive(relay: string): boolean {\n return this.live.has(relay);\n }\n\n /** Listen on `relay` for every wrap sent since `from`. */\n listen(relay: string, from: number): void {\n const { pool, storePubkey, auth, onWrap, log, now } = this.options;\n const since = readSince(from);\n const openedAt = now();\n let closed = false;\n let readThrough = false;\n const runBackfill = () => {\n if (closed) {\n return;\n }\n void this.backfill(relay, since, openedAt).then((done) => {\n if (closed) {\n return;\n }\n if (done) {\n readThrough = true;\n this.attempts.set(relay, 0);\n this.live.add(relay);\n return;\n }\n log(`could not read the stored wraps of ${relay}; trying again`);\n this.setTimer(runBackfill, BACKFILL_RETRY_MS);\n });\n };\n pool.subscribe([relay], wrapFilter(storePubkey, since), {\n onauth: auth,\n onevent: onWrap,\n // nostr-tools also calls this right before `onclose` when a subscription\n // fails: the backfill starts on the next turn, and only if still open.\n oneose: () => this.setTimer(runBackfill, 0),\n onclose: (reasons) => {\n closed = true;\n this.live.delete(relay);\n const attempt = this.attempts.get(relay) ?? 0;\n this.attempts.set(relay, attempt + 1);\n const pause =\n RESUBSCRIBE_BACKOFF_MS[Math.min(attempt, RESUBSCRIBE_BACKOFF_MS.length - 1)] ?? 60_000;\n // Reach back from the close only if this subscription read the stored history.\n const resumeFrom = readThrough ? now() : from;\n log(`subscription on ${relay} closed (${reasons.join(', ')}); again in ${pause} ms`);\n this.setTimer(() => this.listen(relay, resumeFrom), pause);\n },\n });\n }\n\n /** Page backwards through `relay`'s stored wraps in `[since, until]`; true only when read to the end. */\n backfill(relay: string, since: number, until: number): Promise<boolean> {\n const { pool, storePubkey, auth, onWrap } = this.options;\n return new Promise((resolve) => {\n let received = 0;\n let oldest = until;\n let timedOut = false;\n let cancelTimer: (() => void) | undefined;\n const subscription = pool.subscribeEose([relay], wrapFilter(storePubkey, since, until), {\n maxWait: LIBRARY_WAIT_MS,\n onauth: auth,\n onevent: (wrap) => {\n received += 1;\n oldest = Math.min(oldest, wrap.created_at);\n onWrap(wrap);\n },\n onclose: (reasons) => {\n cancelTimer?.();\n if (timedOut || !reasons.every((reason) => reason === EOSE_CLOSE_REASON)) {\n resolve(false);\n return;\n }\n const next = nextPageUntil(since, until, received, oldest);\n if (next === undefined) {\n resolve(true);\n } else {\n void this.backfill(relay, since, next).then(resolve);\n }\n },\n });\n cancelTimer = this.setTimer(() => {\n timedOut = true;\n subscription.close();\n }, PAGE_WAIT_MS);\n });\n }\n}\n","import { type WrappedOrderMessage, buildOrderMessage, wrapOrderMessage } from '@elisym/commerce';\nimport { DELIVERY_RELAYS_WANTED, DELIVERY_SETTLE_SECS } from './constants';\nimport type { MerchantOrder } from './ledger';\n\nexport interface Delivery {\n method: 'download' | 'license' | 'access' | 'webhook' | 'api';\n /** Shown to the buyer as text, or opened as a link only when it is `https:`. */\n value: string;\n}\n\n/**\n * The store's `completed` status for a paid order, sealed by the store key and\n * gift-wrapped to the buyer (the seal signer of the order). It carries the\n * payment the store credited, so the buyer's widget can show what was counted.\n */\nexport function buildDeliveryReply(\n order: MerchantOrder,\n delivery: Delivery,\n storeSecretKey: Uint8Array,\n createdAt: number,\n): WrappedOrderMessage {\n if (order.paid === undefined) {\n throw new Error('Only a paid order is delivered');\n }\n const rumor = buildOrderMessage(\n {\n type: 'status',\n buyerPubkey: order.buyerPubkey,\n orderId: order.orderId,\n status: 'completed',\n delivery,\n receipt: {\n medium: order.paid.medium,\n tx: order.paid.signature,\n amount: order.paid.amount,\n fee: '0',\n },\n },\n createdAt,\n );\n return wrapOrderMessage(rumor, storeSecretKey, order.buyerPubkey);\n}\n\n/**\n * Whether a delivery that `accepted` of the store's `relays` inbox relays took\n * counts as done: two of them (all, when fewer are configured), since one may\n * drop it later; once the payment is `paidAgeSecs` past `DELIVERY_SETTLE_SECS`,\n * any one - a relay down for good must not keep it pending forever.\n */\nexport function deliveryDone(accepted: number, relays: number, paidAgeSecs: number): boolean {\n if (accepted === 0) {\n return false;\n }\n return (\n accepted >= Math.min(DELIVERY_RELAYS_WANTED, relays) || paidAgeSecs >= DELIVERY_SETTLE_SECS\n );\n}\n","import { parseCaip19 } from '@elisym/commerce';\nimport {\n type Asset,\n type DirectInstruction,\n type Network,\n ELISYM_PROTOCOL_TAG,\n boundTransferAmount,\n composeSolanaPaymentRequest,\n directInstructionsFromRpcTransaction,\n listReferenceSignatures,\n verifyDirectSolanaPayment,\n} from '@elisym/pay-core';\nimport { TOKEN_PROGRAM_ADDRESS, findAssociatedTokenPda } from '@solana-program/token';\nimport { type Rpc, type Signature, type SolanaRpcApi, address } from '@solana/kit';\nimport {\n CATCH_UP_SECS,\n MAX_RECHECKS_PER_SWEEP,\n ORDER_SCAN_MARGIN_SECS,\n SOLANA_MEDIUMS,\n TERMS_WINDOW_SECS,\n} from './constants';\nimport {\n type LedgerState,\n type MerchantOrder,\n type ScannedTransaction,\n claimPayment,\n openOrders,\n} from './ledger';\nimport { isSolanaSignature } from './signature';\nimport { type OfferTerms, termsAt, termsSince } from './terms';\n\nexport interface SolanaContext {\n rpc: Rpc<SolanaRpcApi>;\n network: Network;\n}\n\nexport type PaymentCheck =\n | { kind: 'paid'; order: MerchantOrder }\n /** Nothing final was learned (a node error, a page not readable, not landed yet). */\n | { kind: 'ask_again' }\n | {\n kind: 'refused';\n reason: 'claimed_by_another_order' | 'not_a_payment_for_this_order' | 'order_already_paid';\n };\n\n/** The Solana coin of `terms` on this network, or `undefined` for another chain or network. */\nfunction solanaAsset(terms: OfferTerms, network: Network): Asset | undefined {\n const caip19 = parseCaip19(terms.caip19);\n if (\n caip19 === undefined ||\n caip19.chain.family !== 'solana' ||\n caip19.chain.network !== network\n ) {\n return undefined;\n }\n return caip19.asset;\n}\n\nconst ASK_AGAIN_REASONS: readonly string[] = ['rpc_error', 'unreadable', 'not_found'];\n\n/**\n * Check one transaction against one order, per the direct-mode contract: the\n * payment is bound to the order's derived reference at the instruction level,\n * pays terms the store offered within the window before the payment's block\n * time, and is claimed once. On `paid` the ledger holds the claim and the\n * payment; the caller saves it before delivering.\n */\nexport async function checkPayment(\n state: LedgerState,\n order: MerchantOrder,\n signature: string,\n context: SolanaContext,\n): Promise<PaymentCheck> {\n const holder = state.claims[signature];\n if (holder !== undefined && holder !== order.key) {\n return { kind: 'refused', reason: 'claimed_by_another_order' };\n }\n // An order is paid once: a second payment is kept for a refund by hand, never credited.\n if (order.paid !== undefined) {\n return order.paid.signature === signature\n ? { kind: 'paid', order }\n : { kind: 'refused', reason: 'order_already_paid' };\n }\n const candidates = termsSince(state.terms, order.createdAt - ORDER_SCAN_MARGIN_SECS);\n let askAgain = false;\n for (const terms of candidates) {\n const asset = solanaAsset(terms, context.network);\n if (asset === undefined) {\n continue;\n }\n const request = composeSolanaPaymentRequest({\n recipient: terms.payout,\n amount: BigInt(terms.amount),\n asset,\n network: context.network,\n reference: order.reference,\n createdAt: order.createdAt,\n });\n const verdict = await verifyDirectSolanaPayment(context.rpc, request, signature);\n if (!verdict.verified) {\n askAgain ||= ASK_AGAIN_REASONS.includes(verdict.reason);\n continue;\n }\n // A null block time is judged again later, never guessed.\n if (verdict.blockTime === null) {\n askAgain = true;\n continue;\n }\n const offered = termsAt(state.terms, verdict.blockTime).some(\n (standing) =>\n standing.caip19 === terms.caip19 &&\n standing.payout === terms.payout &&\n standing.amount === terms.amount,\n );\n if (!offered) {\n continue;\n }\n if (!claimPayment(state, signature, order.key)) {\n return { kind: 'refused', reason: 'claimed_by_another_order' };\n }\n order.paid = {\n signature,\n amount: verdict.amount.toString(),\n blockTime: verdict.blockTime,\n caip19: terms.caip19,\n medium: SOLANA_MEDIUMS[context.network],\n };\n return { kind: 'paid', order };\n }\n return askAgain\n ? { kind: 'ask_again' }\n : { kind: 'refused', reason: 'not_a_payment_for_this_order' };\n}\n\n/** The account a payout's payments land in: the wallet for SOL, its associated token account otherwise. */\nexport async function receivingAccount(terms: OfferTerms, asset: Asset): Promise<string> {\n if (asset.mint === undefined) {\n return terms.payout;\n }\n const [account] = await findAssociatedTokenPda({\n owner: address(terms.payout),\n mint: address(asset.mint),\n tokenProgram:\n asset.tokenProgram === undefined ? TOKEN_PROGRAM_ADDRESS : address(asset.tokenProgram),\n });\n return account;\n}\n\n/**\n * The references a transaction binds a transfer to, into `terms.payout`: every\n * account placed just before the protocol tag is a candidate, and pay-core's\n * binding decides. Read without knowing any order, so one read serves them all.\n */\nasync function boundReferences(\n instructions: readonly DirectInstruction[],\n terms: OfferTerms,\n asset: Asset,\n): Promise<string[]> {\n const candidates = new Set<string>();\n for (const instruction of instructions) {\n const { accounts } = instruction;\n const tag = accounts[accounts.length - 1];\n const reference = accounts[accounts.length - 2];\n if (tag?.address === ELISYM_PROTOCOL_TAG && reference !== undefined) {\n candidates.add(reference.address);\n }\n }\n const bound: string[] = [];\n for (const reference of candidates) {\n const amount = await boundTransferAmount(instructions, {\n reference,\n recipient: terms.payout,\n asset,\n });\n if (amount > 0n) {\n bound.push(reference);\n }\n }\n return bound;\n}\n\n/** Read one landed transaction of a payout account, or `undefined` when it cannot be judged yet. */\nasync function scanTransaction(\n signature: Signature,\n terms: OfferTerms,\n asset: Asset,\n context: SolanaContext,\n): Promise<ScannedTransaction | undefined> {\n let transaction: unknown;\n try {\n transaction = await context.rpc\n .getTransaction(signature, {\n commitment: 'confirmed',\n encoding: 'json',\n maxSupportedTransactionVersion: 0,\n })\n .send();\n } catch {\n return undefined;\n }\n if (transaction === null || typeof transaction !== 'object') {\n return undefined;\n }\n const blockTime: unknown = Reflect.get(transaction, 'blockTime');\n // A null block time is judged again later: never cached, never guessed.\n if (typeof blockTime !== 'number' && typeof blockTime !== 'bigint') {\n return undefined;\n }\n let instructions: DirectInstruction[];\n try {\n instructions = directInstructionsFromRpcTransaction(transaction);\n } catch {\n return undefined;\n }\n return {\n blockTime: Number(blockTime),\n references: await boundReferences(instructions, terms, asset),\n };\n}\n\nexport interface CatchUpResult {\n paid: MerchantOrder[];\n /** Receiving accounts whose history was cut short by the page cap: older payments may be missed. */\n incomplete: string[];\n}\n\n/**\n * Catch up on every open order at once, per payout ADDRESS (anyone can post\n * orders for free, so never one scan per order): list the payout's receiving\n * account back to the oldest open order, read each landed transaction ONCE\n * (the ledger keeps what it binds), and match its references to the open\n * orders locally. Transactions the buyers reported are checked again too.\n */\nexport async function catchUp(\n state: LedgerState,\n context: SolanaContext,\n now: number,\n): Promise<CatchUpResult> {\n const result: CatchUpResult = { paid: [], incomplete: [] };\n const open = openOrders(state, now, CATCH_UP_SECS);\n forgetOldScans(state, now);\n if (open.length === 0) {\n return result;\n }\n const byReference = new Map(open.map((order) => [order.reference, order]));\n // A transaction finally refused for an order is remembered and never checked\n // for it again, whether it came from a receipt or from the account scan.\n const credit = async (order: MerchantOrder, signature: string) => {\n if (\n order.paid !== undefined ||\n order.refusedTxs?.includes(signature) === true ||\n state.claims[signature] !== undefined\n ) {\n return;\n }\n const check = await checkPayment(state, order, signature, context);\n if (check.kind === 'paid') {\n result.paid.push(order);\n } else if (check.kind === 'refused') {\n order.refusedTxs = [...(order.refusedTxs ?? []), signature];\n }\n };\n // Reported transactions not yet judged, first in first out (queue position:\n // arrival, then last check), under one budget for the whole sweep: every one\n // is reached within a few sweeps, and fresh reports cannot jump ahead of it.\n const pending: { order: MerchantOrder; signature: string; checkedAt: number }[] = [];\n for (const order of open) {\n for (const signature of order.reportedTxs) {\n // Only Solana signatures: a reported Tempo hash is the Tempo catch-up's.\n if (\n order.paid === undefined &&\n isSolanaSignature(signature) &&\n order.refusedTxs?.includes(signature) !== true &&\n state.claims[signature] === undefined\n ) {\n // Its place in the queue: when it arrived, then when it was last checked.\n pending.push({ order, signature, checkedAt: order.recheckedAt?.[signature] ?? 0 });\n }\n }\n }\n pending.sort((left, right) => left.checkedAt - right.checkedAt);\n for (const { order, signature } of pending.slice(0, MAX_RECHECKS_PER_SWEEP)) {\n order.recheckedAt = { ...order.recheckedAt, [signature]: now };\n await credit(order, signature);\n }\n let oldest = Number.POSITIVE_INFINITY;\n for (const order of open) {\n oldest = Math.min(oldest, order.createdAt);\n }\n oldest -= ORDER_SCAN_MARGIN_SECS;\n const scannedAccounts = new Set<string>();\n for (const terms of termsSince(state.terms, oldest)) {\n const asset = solanaAsset(terms, context.network);\n if (asset === undefined) {\n continue;\n }\n const account = await receivingAccount(terms, asset);\n if (scannedAccounts.has(account)) {\n continue;\n }\n scannedAccounts.add(account);\n const listing = await listReferenceSignatures(context.rpc, account, {\n notBefore: oldest,\n commitment: 'confirmed',\n });\n if (!listing.complete) {\n result.incomplete.push(account);\n }\n for (const entry of listing.signatures) {\n // A listing page may reach below the floor; no open order needs those rows,\n // and reading them would repeat every sweep (they fall out of the memo).\n if (\n entry.failed ||\n !isSolanaSignature(entry.signature) ||\n (entry.blockTime !== null && entry.blockTime < oldest)\n ) {\n continue;\n }\n const memo = `${account}:${entry.signature}`;\n let scan: ScannedTransaction | undefined = state.scans[memo];\n if (scan === undefined) {\n scan = await scanTransaction(entry.signature, terms, asset, context);\n if (scan === undefined) {\n continue;\n }\n state.scans[memo] = scan;\n }\n for (const reference of scan.references) {\n const order = byReference.get(reference);\n if (order !== undefined) {\n await credit(order, entry.signature);\n }\n }\n }\n }\n return result;\n}\n\n/** Drop what the ledger remembers of transactions no open order can reach any more. */\nfunction forgetOldScans(state: LedgerState, now: number): void {\n const horizon = now - CATCH_UP_SECS - ORDER_SCAN_MARGIN_SECS - TERMS_WINDOW_SECS;\n for (const [memo, scan] of Object.entries(state.scans)) {\n if (scan.blockTime < horizon) {\n delete state.scans[memo];\n }\n }\n}\n","import { MAX_FUTURE_SKEW_SECS, unwrapOrderMessage } from '@elisym/commerce';\nimport type { NostrEvent } from 'nostr-tools';\nimport {\n ASK_AGAIN_DELAYS_MS,\n MAX_LIVE_CHECKS_PER_MINUTE,\n MAX_REPEATS_IN_FLIGHT,\n RESEND_EVERY_SECS,\n} from './constants';\nimport { type StoreIdentity, intake } from './intake';\nimport {\n type LedgerState,\n type MerchantOrder,\n orderKey,\n pruneExpiredOrders,\n undeliveredOrders,\n} from './ledger';\nimport { SeenWraps, readSince, resumePointAfterSweep } from './listener';\nimport { deliveryDone } from './reply';\nimport {\n type CatchUpResult,\n type PaymentCheck,\n type SolanaContext,\n catchUp,\n checkPayment,\n} from './solana';\nimport {\n TEMPO_HASH_RE,\n type TempoCheck,\n type TempoContext,\n catchUpTempo,\n checkTempoPayment,\n recordTempoCheck,\n} from './tempo';\n\nexport interface RuntimeDeps {\n state: LedgerState;\n store: StoreIdentity;\n storeSecretKey: Uint8Array;\n context: SolanaContext;\n /** Write the ledger to disk. */\n save: () => void;\n /**\n * Publish the delivery of one paid order to the store's inbox relays, except\n * `skip` (they took it already); resolves to the relays that took it now.\n */\n deliver: (order: MerchantOrder, skip: readonly string[]) => Promise<string[]>;\n /** How many inbox relays the store has: a delivery wants two of them (see `deliveryDone`). */\n inboxRelayCount: number;\n log: (message: string) => void;\n now: () => number;\n /**\n * Run `task` on the merchant's queue after `ms`: a reported transaction the\n * RPC does not see yet is checked again soon. Without it, only sweeps do.\n */\n later?: (ms: number, task: () => Promise<void>) => void;\n /** Replaceable in tests. */\n checkPayment?: typeof checkPayment;\n catchUp?: (state: LedgerState, context: SolanaContext, now: number) => Promise<CatchUpResult>;\n /** Present when the store takes Tempo payouts (the `tempo` config block). */\n tempo?: TempoContext;\n checkTempoPayment?: typeof checkTempoPayment;\n catchUpTempo?: typeof catchUpTempo;\n}\n\n/** A reported transaction this order has already judged: never checked again. */\nfunction settled(order: MerchantOrder, tx: string): boolean {\n return (\n order.refusedTxs?.includes(tx) === true ||\n order.noLegTxs?.includes(tx) === true ||\n order.blockedTx === tx\n );\n}\n\n/**\n * What the running merchant does with each wrap and on each sweep. The caller\n * runs every task on ONE queue, so ledger changes happen in order; every change\n * is saved before anything is sent.\n */\nexport class MerchantRuntime {\n readonly seenWraps = new SeenWraps();\n private readonly check: typeof checkPayment;\n /** Live checks in the current minute: `[minute, count]`. */\n private liveChecks: [number, number] = [0, 0];\n private readonly sweepCatchUp: NonNullable<RuntimeDeps['catchUp']>;\n /** When each delivered order's status was last sent again (this run only). */\n private readonly resentAt = new Map<string, number>();\n private repeatsInFlight = 0;\n\n constructor(private readonly deps: RuntimeDeps) {\n this.check = deps.checkPayment ?? checkPayment;\n this.sweepCatchUp = deps.catchUp ?? catchUp;\n }\n\n /**\n * Whether a wrap goes on the queue: not one dated further ahead than any\n * genuine wrap can be (NIP-59 only back-dates; nothing would ever prune it),\n * and not one already handed on (the live burst overlapping the backfill, a\n * reconnect re-reading its window).\n */\n admit(wrap: NostrEvent): boolean {\n if (wrap.created_at > this.deps.now() + MAX_FUTURE_SKEW_SECS) {\n return false;\n }\n return this.seenWraps.admit(wrap);\n }\n\n /** Take one wrap in: an order is recorded; a receipt's transaction is checked. */\n async handleWrap(wrap: NostrEvent): Promise<void> {\n const { state, store, storeSecretKey, save, log } = this.deps;\n const unwrapped = unwrapOrderMessage(wrap, storeSecretKey);\n if (unwrapped === undefined) {\n return;\n }\n const result = intake(state, unwrapped, store, this.deps.now());\n // Read again for an order already delivered: the buyer may never have got it.\n const { message } = unwrapped;\n const again =\n (result.kind === 'ignored' && result.reason === 'seen') || result.kind === 'receipt';\n if (again && (message.type === 'order' || message.type === 'receipt')) {\n const known = state.orders[orderKey(unwrapped.senderPubkey, message.orderId)];\n if (known?.deliveredAt !== undefined && message.storePubkey === store.storePubkey) {\n if (result.kind === 'receipt') {\n save();\n }\n this.resend(known);\n return;\n }\n }\n if (result.kind === 'ignored') {\n // A receipt that came before its order is read again when it is re-sent\n // or re-read, once the order is in.\n if (result.reason === 'unknown_order') {\n this.seenWraps.forget(wrap.id);\n }\n return;\n }\n save();\n if (result.kind === 'order') {\n log(`order ${result.order.key}`);\n return;\n }\n // Only a transaction the order reports for the first time is checked at once,\n // and only within a per-minute budget: orders and receipts are free to send,\n // so the rest wait for the sweep's bounded recheck.\n if (!result.isNew || settled(result.order, result.tx) || !this.takeLiveCheck()) {\n return;\n }\n await this.checkReported(result.order, result.tx, 0);\n }\n\n /** Check one reported transaction now; one the RPC does not see yet is tried again soon. */\n private async checkReported(order: MerchantOrder, tx: string, attempt: number): Promise<void> {\n const { state, context, save, log } = this.deps;\n let check: PaymentCheck | TempoCheck;\n // Dispatched by the transaction's format: a 0x hash is Tempo's.\n if (TEMPO_HASH_RE.test(tx)) {\n if (this.deps.tempo === undefined) {\n log(`receipt ${order.key} ${tx}: a Tempo payment, and this node has no tempo block`);\n return;\n }\n check = await (this.deps.checkTempoPayment ?? checkTempoPayment)(\n state,\n order,\n tx,\n this.deps.tempo,\n );\n recordTempoCheck(state, order, tx, check);\n } else {\n check = await this.check(state, order, tx, context);\n if (check.kind === 'refused') {\n order.refusedTxs = [...(order.refusedTxs ?? []), tx];\n }\n }\n log(`receipt ${order.key} ${tx}: ${check.kind}`);\n save();\n if (check.kind === 'paid') {\n await this.deliverPending();\n } else if (check.kind === 'ask_again') {\n this.askAgain(order.key, tx, attempt);\n }\n }\n\n private askAgain(key: string, tx: string, attempt: number): void {\n const delay = ASK_AGAIN_DELAYS_MS[attempt];\n if (delay === undefined || this.deps.later === undefined) {\n return;\n }\n this.deps.later(delay, async () => {\n // Still the same unpaid order (not pruned, not recreated), the transaction\n // not refused meanwhile, and within the live budget - else the sweep has it.\n const order = this.deps.state.orders[key];\n if (\n order === undefined ||\n order.paid !== undefined ||\n !order.reportedTxs.includes(tx) ||\n settled(order, tx) ||\n !this.takeLiveCheck()\n ) {\n return;\n }\n await this.checkReported(order, tx, attempt + 1);\n });\n }\n\n /**\n * Send a delivered order's status again, at most every `RESEND_EVERY_SECS`,\n * off the queue (it changes no ledger state) and a few at a time: one skipped\n * now is sent when the order is read again.\n */\n private resend(order: MerchantOrder): void {\n const now = this.deps.now();\n const last = this.resentAt.get(order.key);\n if (\n (last !== undefined && now - last < RESEND_EVERY_SECS) ||\n this.repeatsInFlight >= MAX_REPEATS_IN_FLIGHT\n ) {\n return;\n }\n this.resentAt.set(order.key, now);\n this.repeatsInFlight += 1;\n const { deliver, log } = this.deps;\n void deliver(order, [])\n .then((taken) => {\n log(`delivery for ${order.key} sent again: taken by ${taken.length}`);\n })\n .catch((error: unknown) => {\n log(`delivery for ${order.key} not sent again: ${String(error)}`);\n })\n .finally(() => {\n this.repeatsInFlight -= 1;\n });\n }\n\n private takeLiveCheck(): boolean {\n const minute = Math.floor(this.deps.now() / 60);\n const [current, count] = this.liveChecks;\n const used = current === minute ? count : 0;\n if (used >= MAX_LIVE_CHECKS_PER_MINUTE) {\n return false;\n }\n this.liveChecks = [minute, used + 1];\n return true;\n }\n\n /** One catch-up sweep; `allLive` and `queuedAt` were taken when it was queued. */\n async sweep(allLive: boolean, queuedAt: number): Promise<void> {\n const { state, context, save, log, now } = this.deps;\n state.resumeAt = resumePointAfterSweep(allLive, queuedAt, state.resumeAt);\n pruneExpiredOrders(state, now());\n this.seenWraps.prune(readSince(now()));\n for (const [key, at] of this.resentAt) {\n if (now() - at >= RESEND_EVERY_SECS) {\n this.resentAt.delete(key);\n }\n }\n try {\n // Each rail on its own: one rail's RPC failing never stops the other's catch-up.\n const tempo = this.deps.tempo;\n const rails: { rail: string; run: () => Promise<CatchUpResult> }[] = [\n { rail: 'solana', run: () => this.sweepCatchUp(state, context, now()) },\n ];\n if (tempo !== undefined) {\n rails.push({\n rail: 'tempo',\n run: () => (this.deps.catchUpTempo ?? catchUpTempo)(state, tempo, now()),\n });\n }\n const results: CatchUpResult[] = [];\n for (const { rail, run } of rails) {\n try {\n results.push(await run());\n } catch (error) {\n log(\n `${rail} catch-up failed this time: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n for (const result of results) {\n if (result.paid.length > 0) {\n log(`catch-up found ${result.paid.length} payment(s)`);\n }\n for (const account of result.incomplete) {\n log(`warning: the history of ${account} was cut short; older payments may be missed`);\n }\n }\n } finally {\n // Saved before anything is sent, even when the chain could not be read this\n // time: a claim made before the error is on disk before its delivery.\n save();\n await this.deliverPending();\n }\n }\n\n /**\n * Deliver every paid order not yet delivered, all at once (a hung relay costs\n * one deadline, not one per order), each only to the relays that have not\n * taken it yet (the buyer gets no pile of copies while one relay is down).\n * An order counts as delivered per `deliveryDone`, and it is saved.\n */\n async deliverPending(): Promise<void> {\n const { state, save, log, now, deliver, inboxRelayCount } = this.deps;\n const pending = undeliveredOrders(state);\n if (pending.length === 0) {\n return;\n }\n const taken = await Promise.all(\n pending.map((order) => deliver(order, order.deliveredTo ?? []).catch(() => [])),\n );\n const at = now();\n let changed = false;\n pending.forEach((order, index) => {\n const fresh = (taken[index] ?? []).filter(\n (relay) => !(order.deliveredTo ?? []).includes(relay),\n );\n if (fresh.length > 0) {\n changed = true;\n order.deliveredTo = [...(order.deliveredTo ?? []), ...fresh];\n }\n const paidAge = at - (order.paid?.blockTime ?? at);\n if (deliveryDone(order.deliveredTo?.length ?? 0, inboxRelayCount, paidAge)) {\n changed = true;\n order.deliveredAt = at;\n log(`delivered ${order.key} (${order.paid?.signature ?? ''})`);\n } else {\n log(`delivery for ${order.key} taken by ${order.deliveredTo?.length ?? 0}; will retry`);\n }\n });\n if (changed) {\n save();\n }\n }\n}\n","import type { LedgerState } from './ledger';\nimport { type OfferTerms, publishTerms, retireTerms, standingTerms, visibleTerms } from './terms';\n\n/**\n * The date to sign the payout list with: an unchanged list keeps the date it\n * was first signed (a new one would restart every buyer's \"payout recently\n * changed\" cool-down), but only while the relays' newest list is that very\n * one - otherwise re-signing an older date would never replace what buyers read.\n */\nexport function payoutListDate(\n state: LedgerState,\n payouts: string,\n newestOnRelays: number | undefined,\n now: number,\n): number {\n const signed = state.payto;\n return signed !== undefined && signed.payouts === payouts && newestOnRelays === signed.createdAt\n ? signed.createdAt\n : now;\n}\n\n/** Why setup may not publish over what the ledger holds; `undefined` when it may. */\nexport function setupRefusal(state: LedgerState, productD: string): string | undefined {\n if (state.productD !== undefined && state.productD !== productD) {\n return `the product id changed from \"${state.productD}\" to \"${productD}\": the old listing would stay payable with no one taking its orders. Keep the id, or give a new product its own home.`;\n }\n return undefined;\n}\n\nexport interface PublishOutcome {\n /** The listing (kind 30402) reached a relay. */\n listing: boolean;\n /** The owner's payout list (kind 10133) reached a relay. */\n payouts: boolean;\n}\n\n/**\n * Record in the ledger what buyers can read after a publish: the listing's\n * coins and price, paid to the payout list's addresses - each the new one only\n * if it reached a relay. `at` dates the change (a little before now).\n */\nexport function recordPublished(\n state: LedgerState,\n next: readonly OfferTerms[],\n outcome: PublishOutcome,\n at: number,\n payoutList: { createdAt: number; payouts: string },\n productD: string,\n): void {\n const visible = visibleTerms(standingTerms(state.terms), next, outcome.listing, outcome.payouts);\n state.terms = retireTerms(\n state.terms,\n visible.map((terms) => terms.caip19),\n at,\n );\n for (const terms of visible) {\n state.terms = publishTerms(state.terms, terms, at);\n }\n if (outcome.payouts) {\n state.payto = payoutList;\n }\n if (outcome.listing) {\n state.productD = productD;\n }\n}\n","import {\n KIND_INBOX_RELAYS,\n buildPaytoEvent,\n buildProductEvent,\n buildStoreAuthEvent,\n buildStoreProfileEvent,\n encodeProductNaddr,\n parseCaip19,\n priceInSubunits,\n splitNip05,\n} from '@elisym/commerce';\nimport { type NostrEvent, finalizeEvent, getPublicKey } from 'nostr-tools/pure';\nimport type { OfferTerms } from './terms';\n\n/** The nostr.json name commerce reads the owner key from. */\nconst NOSTR_JSON_OWNER_NAME = 'owner';\n\nexport interface StoreConfig {\n /** Store profile name. */\n name: string;\n /** `_@shop.example`: the domain that vouches for the store (level A), or none (level C). */\n nip05?: string;\n product: {\n d: string;\n title: string;\n description: string;\n summary?: string;\n /** USD, e.g. `\"1\"` or `\"49.00\"`: paid 1:1 in a USD coin. */\n priceUsd: string;\n };\n /** One payout per accepted coin: CAIP-19 id and the owner's wallet address. */\n payouts: { caip19: string; address: string; signature?: string }[];\n /** The store's inbox relays (kind 10050): where it reads orders and replies. */\n inboxRelays: string[];\n}\n\nexport interface StoreKeys {\n storeSecretKey: Uint8Array;\n ownerSecretKey: Uint8Array;\n}\n\nexport interface StoreEvents {\n /** Signed, ready to publish: product, profile, inbox list (store key); payouts, authorization (owner key). */\n events: NostrEvent[];\n naddr: string;\n /** The terms these events offer, one per payout: what the ledger records. */\n terms: OfferTerms[];\n /**\n * What the domain's `/.well-known/nostr.json` serves (with CORS). It gives\n * level A only under the domain-wide name `_` (nip05 `_@domain` or a bare\n * domain); a named nip05 such as `shop@domain` stays level C.\n */\n nostrJson: { names: Record<string, string> };\n}\n\n/** Build and sign everything a store publishes, at `createdAt`. */\nexport function buildStoreEvents(\n config: StoreConfig,\n keys: StoreKeys,\n createdAt: number,\n options: {\n hints?: readonly string[];\n /**\n * When the unchanged payout list was first signed: republishing it with a new\n * date would restart every buyer's \"payout recently changed\" cool-down.\n */\n paytoCreatedAt?: number;\n } = {},\n): StoreEvents {\n const storePubkey = getPublicKey(keys.storeSecretKey);\n const ownerPubkey = getPublicKey(keys.ownerSecretKey);\n const price = { amount: config.product.priceUsd, currency: 'USD' };\n const terms: OfferTerms[] = config.payouts.map((payout) => {\n const caip19 = parseCaip19(payout.caip19);\n if (caip19 === undefined) {\n throw new Error(`Not a payable CAIP-19 asset: ${payout.caip19}`);\n }\n return {\n caip19: caip19.id,\n payout: payout.address,\n amount: priceInSubunits(price, caip19.asset).toString(),\n };\n });\n const byStore = (template: Parameters<typeof finalizeEvent>[0]) =>\n finalizeEvent(template, keys.storeSecretKey);\n const byOwner = (template: Parameters<typeof finalizeEvent>[0]) =>\n finalizeEvent(template, keys.ownerSecretKey);\n const events = [\n byStore(\n buildProductEvent({\n d: config.product.d,\n title: config.product.title,\n description: config.product.description,\n ...(config.product.summary === undefined ? {} : { summary: config.product.summary }),\n price,\n accept: config.payouts.map((payout) => payout.caip19),\n createdAt,\n }),\n ),\n byStore(\n buildStoreProfileEvent({\n name: config.name,\n ownerPubkey,\n createdAt,\n ...(config.nip05 === undefined ? {} : { nip05: config.nip05 }),\n }),\n ),\n byStore({\n kind: KIND_INBOX_RELAYS,\n created_at: createdAt,\n tags: config.inboxRelays.map((relay) => ['relay', relay]),\n content: '',\n }),\n byOwner(\n buildPaytoEvent({\n ownerPubkey,\n accept: config.payouts,\n createdAt: options.paytoCreatedAt ?? createdAt,\n }),\n ),\n byOwner(buildStoreAuthEvent({ storePubkey, mode: 'self-host', createdAt })),\n ];\n const local = config.nip05 === undefined ? '_' : (splitNip05(config.nip05)?.local ?? '_');\n // `owner` names the owner key in nostr.json: a store under that name would be lost.\n if (local === NOSTR_JSON_OWNER_NAME) {\n throw new Error(\n `The store's nip05 name cannot be \"${NOSTR_JSON_OWNER_NAME}\": it names the owner`,\n );\n }\n return {\n events,\n naddr: encodeProductNaddr({ storePubkey, d: config.product.d }, [...(options.hints ?? [])]),\n terms,\n nostrJson: { names: { [local]: storePubkey, [NOSTR_JSON_OWNER_NAME]: ownerPubkey } },\n };\n}\n","/**\n * elisym merchant node. `init` makes the home (config template and keys),\n * `setup` checks the inbox relays and publishes the store, `run` takes orders,\n * verifies payments by the direct-mode contract and delivers.\n */\nimport { existsSync, writeFileSync } from 'node:fs';\nimport { createInterface } from 'node:readline/promises';\nimport { KIND_INBOX_RELAYS, KIND_PAYTO, KIND_PRODUCT, splitNip05 } from '@elisym/commerce';\nimport { createSolanaRpc } from '@solana/kit';\nimport { SimplePool } from 'nostr-tools/pool';\nimport { type EventTemplate, finalizeEvent, getPublicKey } from 'nostr-tools/pure';\nimport {\n checkDomain,\n checkInboxRelays,\n newestInboxList,\n newestListing,\n newestPayoutList,\n offerProblems,\n} from './checks';\nimport { type MerchantConfig, configTemplate, loadConfig, tempoRegistryNetwork } from './config';\nimport {\n CATCH_UP_INTERVAL_MS,\n OFFER_RELAYS,\n SOLANA_MEDIUMS,\n TERMS_CLOCK_MARGIN_SECS,\n} from './constants';\nimport { type HandRequest, applyHandAnswer, buildHandAnswer, planHandAnswer } from './hand';\nimport {\n type MerchantHome,\n ensureHome,\n heldByRunningMerchant,\n loadOrCreateKeys,\n merchantHome,\n takeLock,\n} from './home';\nimport { storeIdentity } from './intake';\nimport { type LedgerState, type MerchantOrder, loadLedger, saveLedger } from './ledger';\nimport { InboxListener } from './listener';\nimport { publishToRelays } from './publish';\nimport { buildDeliveryReply, deliveryDone } from './reply';\nimport { MerchantRuntime } from './runtime';\nimport { payoutListDate, recordPublished, setupRefusal } from './setup-ledger';\nimport { type StoreKeys, buildStoreEvents } from './store-events';\nimport { tempoContextFor } from './tempo';\nimport { standingTerms } from './terms';\n\nconst USAGE = `usage: elisym-merchant <command> [--home <dir>]\n\n init [--network devnet|mainnet]\n make the home: a config.json to edit and the store's keys\n setup check the inbox relays and publish the store (after editing config.json)\n run take orders, verify payments, deliver\n orders list the orders: paid, delivered, the buyer's email\n check check the inbox relays, the owner's payout list and the domain\n deliver <buyer>:<orderId> [--yes]\n answer an unpaid order by hand with the configured delivery\n refund <buyer>:<orderId> --tx <refund tx> --amount <subunits> [--yes]\n answer an unpaid order by hand with a refund you already sent\n (both need the node stopped; --yes skips the confirmation)\n\nThe home is --home, else $ELISYM_MERCHANT_HOME, else ~/.elisym-merchant.\nIt holds the store's secret keys: keep it private and back it up.`;\n\n/** Answers a relay's NIP-42 challenge with the store key. */\nfunction storeAuth(keys: StoreKeys) {\n return async (template: EventTemplate) => finalizeEvent(template, keys.storeSecretKey);\n}\n\nfunction nowSecs(): number {\n return Math.floor(Date.now() / 1000);\n}\n\nfunction log(message: string): void {\n console.log(`${new Date().toISOString()} ${message}`);\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\ninterface Args {\n command: string | undefined;\n /** The order key of `deliver` / `refund`. */\n target: string | undefined;\n home: string | undefined;\n network: string | undefined;\n tx: string | undefined;\n amount: string | undefined;\n yes: boolean;\n}\n\nconst VALUE_FLAGS = {\n '--home': 'home',\n '--network': 'network',\n '--tx': 'tx',\n '--amount': 'amount',\n} as const;\n\nfunction isValueFlag(arg: string): arg is keyof typeof VALUE_FLAGS {\n return arg in VALUE_FLAGS;\n}\n\nfunction parseArgs(argv: readonly string[]): Args {\n const args: Args = {\n command: undefined,\n target: undefined,\n home: undefined,\n network: undefined,\n tx: undefined,\n amount: undefined,\n yes: false,\n };\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n if (arg !== undefined && isValueFlag(arg)) {\n const value = argv[index + 1];\n if (value === undefined || value.startsWith('--')) {\n throw new Error(`${arg} needs a value`);\n }\n args[VALUE_FLAGS[arg]] = value;\n index += 1;\n } else if (arg === '--yes') {\n args.yes = true;\n } else if (args.command === undefined && arg !== undefined && !arg.startsWith('--')) {\n args.command = arg;\n } else if (\n (args.command === 'deliver' || args.command === 'refund') &&\n args.target === undefined &&\n arg !== undefined &&\n !arg.startsWith('--')\n ) {\n args.target = arg;\n } else {\n throw new Error(`unknown argument ${arg ?? ''}`);\n }\n }\n return args;\n}\n\nfunction init(home: MerchantHome, network: string | undefined): void {\n if (network !== undefined && network !== 'devnet' && network !== 'mainnet') {\n throw new Error('--network is devnet or mainnet');\n }\n ensureHome(home);\n if (existsSync(home.config)) {\n console.log(`config ${home.config} (kept)`);\n } else {\n writeFileSync(\n home.config,\n `${JSON.stringify(configTemplate(network === 'mainnet' ? 'mainnet' : 'devnet'), null, 2)}\\n`,\n { mode: 0o600, flag: 'wx' },\n );\n console.log(`config ${home.config} (edit it)`);\n }\n const keys = loadOrCreateKeys(home, true);\n console.log(`store ${getPublicKey(keys.storeSecretKey)}`);\n console.log(`owner ${getPublicKey(keys.ownerSecretKey)}`);\n console.log('next edit config.json, then run setup');\n}\n\n/**\n * Print what the inbox relays can do; the ones that do not take and serve gift\n * wraps for any key. Every one must: buyers send orders to all of them, and a\n * delivery one of them took counts toward the two a delivery wants.\n */\nasync function reportInboxRelays(\n pool: SimplePool,\n config: MerchantConfig,\n keys: StoreKeys,\n): Promise<string[]> {\n const reader = new SimplePool();\n let verdicts: Awaited<ReturnType<typeof checkInboxRelays>>;\n try {\n verdicts = await checkInboxRelays(\n pool,\n reader,\n config.inboxRelays,\n keys.storeSecretKey,\n storeAuth(keys),\n log,\n nowSecs(),\n );\n } finally {\n reader.destroy();\n }\n for (const verdict of verdicts) {\n let state = 'refuses gift wraps for any key';\n if (verdict.serves) {\n state = 'ok';\n } else if (verdict.accepts) {\n state = 'takes gift wraps but does not serve them back';\n }\n console.log(`relay ${verdict.relay}: ${state}`);\n }\n console.log(\n 'note each inbox relay must keep gift wraps (kind 1059) for at least two days past their date',\n );\n return verdicts.filter((verdict) => !verdict.serves).map((verdict) => verdict.relay);\n}\n\n/** Write the nostr.json a level A domain serves, and check it once; nothing for level C. */\nasync function reportDomain(\n home: MerchantHome,\n config: MerchantConfig,\n nostrJson: { names: Record<string, string> },\n): Promise<void> {\n const split = config.nip05 === undefined ? undefined : splitNip05(config.nip05);\n if (split === undefined) {\n console.log('level C (no nip05)');\n return;\n }\n if (split.local !== '_') {\n // commerce vouches for a store at level A only under the domain-wide name.\n console.log('level C: a named nip05 is not domain-wide; use _@domain or a bare domain for A');\n return;\n }\n writeFileSync(home.nostrJson, `${JSON.stringify(nostrJson)}\\n`);\n console.log(\n `nostr serve ${home.nostrJson} at https://${split.domain}/.well-known/nostr.json with \"Access-Control-Allow-Origin: *\"`,\n );\n const verdict = await checkDomain(split.domain, nostrJson);\n console.log(\n verdict.ok\n ? `level A: ${verdict.url} serves it`\n : `level C until ${verdict.url} serves it: ${verdict.problem ?? ''}`,\n );\n}\n\nasync function setup(home: MerchantHome): Promise<void> {\n // A running merchant rewrites the whole ledger from memory: new terms written\n // under it would be lost, and the old price or payout would stay payable. The\n // lock is held for the whole setup, so a merchant cannot start in between.\n takeLock(home);\n const config = loadConfig(home.config);\n const keys = loadOrCreateKeys(home, false);\n const state = loadLedger(home.ledger);\n const refusal = setupRefusal(state, config.product.d);\n if (refusal !== undefined) {\n throw new Error(refusal);\n }\n const pool = new SimplePool();\n try {\n const failing = await reportInboxRelays(pool, config, keys);\n if (failing.length > 0) {\n throw new Error(\n `these inbox relays do not take and serve gift wraps for any key: ${failing.join(', ')}. Replace them in config.json.`,\n );\n }\n const relays = [...new Set([...OFFER_RELAYS, ...config.inboxRelays])];\n const now = nowSecs();\n const payouts = JSON.stringify(config.payouts);\n const newest = await newestPayoutList(pool, relays, getPublicKey(keys.ownerSecretKey));\n const paytoCreatedAt = payoutListDate(state, payouts, newest?.created_at, now);\n const built = buildStoreEvents(config, keys, now, {\n hints: config.inboxRelays.slice(0, 2),\n paytoCreatedAt,\n });\n const acceptedKinds = new Set<number>();\n // Kinds a default relay took: every page reads those, whatever its naddr's hints.\n const everywhereKinds = new Set<number>();\n for (const event of built.events) {\n const accepted = await publishToRelays(pool, relays, event, storeAuth(keys), log);\n log(`kind ${event.kind}: accepted by ${accepted.length}/${relays.length}`);\n if (accepted.length > 0) {\n acceptedKinds.add(event.kind);\n }\n if (accepted.some((relay) => OFFER_RELAYS.includes(relay))) {\n everywhereKinds.add(event.kind);\n }\n }\n const outcome = {\n listing: acceptedKinds.has(KIND_PRODUCT),\n payouts: acceptedKinds.has(KIND_PAYTO),\n };\n if (!outcome.listing && !outcome.payouts) {\n throw new Error(\n 'neither the listing nor the payout list reached a relay: the ledger is left as it was',\n );\n }\n // Dated a little before now: a local clock running ahead of chain time must not\n // refuse a payment made right after the change.\n recordPublished(\n state,\n built.terms,\n outcome,\n now - TERMS_CLOCK_MARGIN_SECS,\n { createdAt: paytoCreatedAt, payouts },\n config.product.d,\n );\n // Orders can come from the moment the store is published: a later first run\n // reads back from here, not from its own start.\n state.resumeAt ??= now;\n saveLedger(home.ledger, state);\n console.log(`store ${getPublicKey(keys.storeSecretKey)}`);\n console.log(`owner ${getPublicKey(keys.ownerSecretKey)}`);\n console.log(`naddr ${built.naddr}`);\n await reportDomain(home, config, built.nostrJson);\n // Buyers send orders to the inbox list: one that did not go out may leave them\n // writing to relays the node no longer reads.\n const missing = [\n [KIND_PRODUCT, 'the listing'],\n [KIND_PAYTO, 'the payout list'],\n [KIND_INBOX_RELAYS, 'the inbox list'],\n ]\n .filter(([kind]) => !everywhereKinds.has(kind as number))\n .map(([, name]) => name);\n if (missing.length > 0) {\n throw new Error(\n `${missing.join(', ')} reached none of the default relays: buyers may see part of the change (the ledger follows what they see). Run setup again.`,\n );\n }\n } finally {\n pool.destroy();\n }\n}\n\n/**\n * Refuse to run when the relays offer buyers something this node does not\n * honour (see `offersNotHonoured`): a buyer could pay it and never get a delivery.\n */\nasync function refuseOffersNotHonoured(\n pool: SimplePool,\n config: MerchantConfig,\n keys: StoreKeys,\n state: LedgerState,\n): Promise<void> {\n const storePubkey = getPublicKey(keys.storeSecretKey);\n // Judged twice: from the default relays, which every page reads, and with the\n // store's own inbox relays too, which a page reads when its naddr hints them.\n const views = [OFFER_RELAYS, [...new Set([...OFFER_RELAYS, ...config.inboxRelays])]];\n const read = await Promise.all(\n views.map(async (relays) => {\n const [listing, payoutList, inboxList] = await Promise.all([\n newestListing(pool, relays, storePubkey, config.product.d),\n newestPayoutList(pool, relays, getPublicKey(keys.ownerSecretKey)),\n newestInboxList(pool, relays, storePubkey),\n ]);\n return { listing, payoutList, inboxList };\n }),\n );\n const { problems, served } = offerProblems(\n read,\n config.inboxRelays,\n config.network,\n standingTerms(state.terms),\n config.tempo === undefined ? undefined : tempoRegistryNetwork(config.tempo.network),\n );\n if (problems.length > 0) {\n throw new Error(\n `the relays offer buyers what this node does not honour: ${problems.join('; ')}. Run setup (it publishes what the config names and records it) before taking orders.`,\n );\n }\n if (!served) {\n log(\n 'warning: no relay served the listing or the payout list; run setup if the store is not published',\n );\n }\n}\n\n/** A stop request's exit code (128 + the signal's number). */\nconst SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143 } as const;\n\n/** Stop at once on a signal (the lock is released on exit). */\nfunction stopOnSignals(): void {\n for (const [signal, code] of Object.entries(SIGNAL_EXIT_CODES)) {\n process.once(signal, () => process.exit(code));\n }\n}\n\n/**\n * Hold a stop request until the ledger is written: stopping between publishing\n * and recording would leave buyers offered terms the ledger refuses. A second\n * request stops at once. Returns the code to exit with afterwards, if any.\n */\nfunction deferSignals(): () => number | undefined {\n let requested: number | undefined;\n for (const [signal, code] of Object.entries(SIGNAL_EXIT_CODES)) {\n process.on(signal, () => {\n if (requested !== undefined) {\n process.exit(code);\n }\n requested = code;\n console.error('stopping once the ledger is written (again to stop now)');\n });\n }\n return () => requested;\n}\n\n/** Publish the delivery of a paid order to the inbox relays not in `skip`; the ones that took it. */\nasync function deliver(\n pool: SimplePool,\n order: MerchantOrder,\n skip: readonly string[],\n config: MerchantConfig,\n keys: StoreKeys,\n): Promise<string[]> {\n const reply = buildDeliveryReply(order, config.product.delivery, keys.storeSecretKey, nowSecs());\n // By convention the store replies on its OWN inbox relays: the buyer key has none.\n return await publishToRelays(\n pool,\n config.inboxRelays.filter((relay) => !skip.includes(relay)),\n reply.recipientWrap,\n storeAuth(keys),\n log,\n );\n}\n\nasync function run(home: MerchantHome): Promise<void> {\n const config = loadConfig(home.config);\n const keys = loadOrCreateKeys(home, false);\n const storePubkey = getPublicKey(keys.storeSecretKey);\n takeLock(home);\n // Pings find a half-open socket, which would otherwise never close.\n const pool = new SimplePool({ enablePing: true });\n const state = loadLedger(home.ledger);\n await refuseOffersNotHonoured(pool, config, keys, state);\n\n // One queue: every ledger change happens in order, and is saved before anything is sent.\n let queue: Promise<void> = Promise.resolve();\n const enqueue = (task: () => Promise<void>) => {\n queue = queue.then(task).catch((error: unknown) => {\n log(`error: ${errorText(error)}`);\n });\n };\n\n const tempo = tempoContextFor(config, storePubkey);\n const mediums = [\n ...(config.rpcUrl === undefined ? [] : [SOLANA_MEDIUMS[config.network]]),\n ...(tempo === undefined ? [] : [tempo.medium]),\n ];\n const runtime = new MerchantRuntime({\n state,\n store: storeIdentity(storePubkey, config.product.d, mediums),\n storeSecretKey: keys.storeSecretKey,\n // With no Solana payout the Solana catch-up has no terms to scan and reads nothing.\n context: {\n rpc: createSolanaRpc(config.rpcUrl ?? 'https://api.devnet.solana.com'),\n network: config.network,\n },\n ...(tempo === undefined ? {} : { tempo }),\n // No Solana payout configured: the Solana sweep reads nothing (no cluster to guess).\n ...(config.rpcUrl === undefined ? { catchUp: async () => ({ paid: [], incomplete: [] }) } : {}),\n save: () => saveLedger(home.ledger, state),\n deliver: (order, skip) => deliver(pool, order, skip, config, keys),\n inboxRelayCount: config.inboxRelays.length,\n log,\n now: nowSecs,\n later: (ms, task) => {\n setTimeout(() => enqueue(task), ms);\n },\n });\n const startedAt = nowSecs();\n\n const listener = new InboxListener({\n pool,\n storePubkey,\n auth: storeAuth(keys),\n onWrap: (wrap) => {\n if (runtime.admit(wrap)) {\n enqueue(() => runtime.handleWrap(wrap));\n }\n },\n log,\n now: nowSecs,\n });\n // Resume from the last moment every inbox relay was read through. Recorded before\n // listening, so a run that never reads every relay through does not restart \"from now\".\n state.resumeAt = Math.min(state.resumeAt ?? startedAt, startedAt);\n saveLedger(home.ledger, state);\n const resumeFrom = state.resumeAt;\n for (const relay of config.inboxRelays) {\n listener.listen(relay, resumeFrom);\n }\n log(`store ${storePubkey} listening on ${config.inboxRelays.join(', ')}`);\n\n let sweepQueued = false;\n const sweep = () => {\n // A slow sweep never piles up behind itself on the queue.\n if (sweepQueued) {\n return;\n }\n sweepQueued = true;\n // Every wrap received before now is already on the queue, ahead of this sweep.\n const allLive = listener.allLive(config.inboxRelays);\n const queuedAt = nowSecs();\n enqueue(async () => {\n sweepQueued = false;\n await runtime.sweep(allLive, queuedAt);\n });\n };\n sweep();\n setInterval(sweep, CATCH_UP_INTERVAL_MS);\n}\n\nfunction orderStatus(order: MerchantOrder): string {\n if (order.paid === undefined) {\n return 'open';\n }\n return order.deliveredAt === undefined ? 'paid, delivering' : 'delivered';\n}\n\nfunction listOrders(home: MerchantHome): void {\n const state = loadLedger(home.ledger);\n const all = Object.values(state.orders).sort((left, right) => left.createdAt - right.createdAt);\n for (const order of all) {\n const when = new Date(order.createdAt * 1000).toISOString();\n const paid = order.paid === undefined ? '' : ` ${order.paid.amount} ${order.paid.signature}`;\n const email = order.email === undefined ? '' : ` email=${order.email}`;\n console.log(`${when} ${orderStatus(order)} ${order.key}${paid}${email}`);\n }\n console.log(`${all.length} order(s)`);\n for (const [key, answer] of Object.entries(state.answeredByHand ?? {})) {\n const detail =\n answer.kind === 'delivered'\n ? (answer.delivery?.value ?? '')\n : `${answer.amount ?? ''} in ${answer.tx ?? ''}`;\n console.log(`answered by hand: ${key} ${answer.kind} ${detail}`);\n }\n}\n\nasync function check(home: MerchantHome): Promise<void> {\n const config = loadConfig(home.config);\n const keys = loadOrCreateKeys(home, false);\n if (heldByRunningMerchant(home)) {\n console.log('note a merchant is running on this home');\n }\n const pool = new SimplePool();\n try {\n const failing = await reportInboxRelays(pool, config, keys);\n let offers: unknown;\n try {\n await refuseOffersNotHonoured(pool, config, keys, loadLedger(home.ledger));\n } catch (error) {\n offers = error;\n }\n await reportDomain(home, config, buildStoreEvents(config, keys, nowSecs()).nostrJson);\n if (offers !== undefined) {\n throw offers;\n }\n if (failing.length > 0) {\n throw new Error(\n `these inbox relays do not take and serve gift wraps for any key: ${failing.join(', ')}`,\n );\n }\n } finally {\n pool.destroy();\n }\n}\n\n/** Ask on a terminal; without one, refuse rather than wait or assume. */\nasync function confirmed(question: string, yes: boolean): Promise<boolean> {\n if (yes) {\n return true;\n }\n if (!process.stdin.isTTY) {\n throw new Error('no terminal to confirm on: pass --yes to answer without asking');\n }\n const prompt = createInterface({ input: process.stdin, output: process.stdout });\n try {\n const answer = await prompt.question(`${question} [y/N] `);\n return answer.trim().toLowerCase() === 'y';\n } finally {\n prompt.close();\n }\n}\n\n/**\n * Answer an order by hand. The node must be stopped (the lock): a running node\n * rewrites the ledger from memory. The close is saved first, then the answer\n * published to the store's inbox relays; below the delivery threshold the\n * command fails, and a rerun sends the same answer again.\n */\nasync function answerByHand(home: MerchantHome, args: Args): Promise<void> {\n const key = args.target;\n if (key === undefined) {\n throw new Error(`${args.command ?? ''} needs the order: <buyer>:<orderId> (see orders)`);\n }\n const config = loadConfig(home.config);\n const keys = loadOrCreateKeys(home, false);\n takeLock(home);\n const state = loadLedger(home.ledger);\n const request: HandRequest =\n args.command === 'deliver'\n ? { kind: 'delivered', delivery: config.product.delivery }\n : { kind: 'refunded', tx: args.tx ?? '', amount: args.amount ?? '' };\n const plan = planHandAnswer(state, key, request);\n if (!plan.ok) {\n throw new Error(plan.problem);\n }\n const order = state.orders[key];\n const held = order ?? plan.answer;\n console.log(`order ${key}${order === undefined ? ' (closed)' : ''}`);\n console.log(`reported ${held.reportedTxs.join(', ') || '-'}`);\n console.log(`refused ${(held.refusedTxs ?? []).join(', ') || '-'}`);\n console.log(`no leg ${(held.noLegTxs ?? []).join(', ') || '-'}`);\n if (order?.blockedTx !== undefined) {\n console.log(`blocked ${order.blockedTx}`);\n }\n const what =\n plan.answer.kind === 'delivered'\n ? `deliver \"${plan.answer.delivery?.value ?? ''}\"`\n : `report a refund of ${plan.answer.amount ?? ''} in ${plan.answer.tx ?? ''}`;\n if (\n !(await confirmed(`${plan.rerun ? 'Send again' : 'Close the order and'} ${what}?`, args.yes))\n ) {\n throw new Error('not confirmed: nothing was sent');\n }\n if (!plan.rerun) {\n applyHandAnswer(state, key, plan.answer);\n saveLedger(home.ledger, state);\n }\n const pool = new SimplePool();\n try {\n const wrap = buildHandAnswer(plan, keys.storeSecretKey, nowSecs());\n const taken = await publishToRelays(\n pool,\n config.inboxRelays,\n wrap.recipientWrap,\n storeAuth(keys),\n log,\n );\n console.log(\n `taken by ${taken.length} of ${config.inboxRelays.length}: ${taken.join(', ') || '-'}`,\n );\n if (!deliveryDone(taken.length, config.inboxRelays.length, 0)) {\n throw new Error('too few inbox relays took it: run the same command again to send it again');\n }\n } finally {\n pool.destroy();\n }\n}\n\nasync function main(): Promise<void> {\n const args = parseArgs(process.argv.slice(2));\n if (args.network !== undefined && args.command !== 'init') {\n throw new Error('--network is for init; the config names the network');\n }\n const home = merchantHome(args.home);\n switch (args.command) {\n case 'init':\n init(home, args.network);\n return;\n case 'setup': {\n const stopRequested = deferSignals();\n let failed = false;\n try {\n await setup(home);\n } catch (error) {\n console.error(`error: ${errorText(error)}`);\n failed = true;\n }\n process.exit(stopRequested() ?? (failed ? 1 : 0));\n return;\n }\n case 'run':\n stopOnSignals();\n await run(home);\n return;\n case 'orders':\n listOrders(home);\n return;\n case 'check':\n await check(home);\n process.exit(0);\n return;\n case 'deliver':\n case 'refund':\n await answerByHand(home, args);\n process.exit(0);\n return;\n default:\n console.log(USAGE);\n process.exit(args.command === undefined || args.command === 'help' ? 0 : 1);\n }\n}\n\ntry {\n await main();\n} catch (error) {\n console.error(`error: ${errorText(error)}`);\n process.exit(1);\n}\n"]}