@elisym/commerce 0.2.0 → 0.3.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/README.md +10 -0
- package/dist/buyer.d.ts +921 -0
- package/dist/buyer.js +1799 -0
- package/dist/buyer.js.map +1 -0
- package/dist/chunk-DYXVY6VD.js +1464 -0
- package/dist/chunk-DYXVY6VD.js.map +1 -0
- package/dist/index.d.ts +6 -557
- package/dist/index.js +1 -1462
- package/dist/index.js.map +1 -1
- package/dist/verify-offer-BZ_a9x3L.d.ts +558 -0
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/buyer/constants.ts","../src/buyer/events.ts","../src/buyer/relays.ts","../src/buyer/inbox.ts","../src/buyer/local-wallet.ts","../src/buyer/offer.ts","../src/buyer/order-record.ts","../src/buyer/order-flow.ts","../src/buyer/order-store.ts","../src/buyer/solana-pay.ts","../src/buyer/purchase.ts","../src/buyer/relay-client.ts"],"names":["productAddress","getTransactionEncoder","getTransactionDecoder","written"],"mappings":"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","file":"buyer.js","sourcesContent":["/**\n * Relays the widget always queries for the offer and the store's inbox list,\n * outside the cap on store-named relays: the store's own relays hold neither the\n * owner's payout list nor its authorization, and the store key must not choose\n * where those reads go.\n */\nexport const DEFAULT_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/** At most this many relays named by the store (its inbox list, naddr hints). */\nexport const STORE_RELAY_CAP = 8;\n\n/** A relay URL longer than this is not one. */\nexport const MAX_RELAY_URL_LENGTH = 256;\n\n/** An offer snapshot older than this is verified again before ordering or paying. */\nexport const OFFER_SNAPSHOT_MAX_AGE_SECS = 120;\n\n/** Store inbox relays that must acknowledge the order before the wallet opens. */\nexport const ORDER_ACK_TARGET = 2;\n\n/** How long one relay query waits before it answers with what it has. */\nexport const RELAY_QUERY_MAX_WAIT_MS = 4000;\n\n/** The most one relay's query may take in all, AUTH and a re-subscription included. */\nexport const RELAY_QUERY_DEADLINE_MS = 15_000;\n\n/** How long a publish waits to connect to one relay. */\nexport const RELAY_CONNECT_MAX_WAIT_MS = 6000;\n\n/**\n * The most one relay's publish may take in all: connect, OK, AUTH and a retry.\n * The OK itself is bounded by the relay library's own publish timeout.\n */\nexport const RELAY_PUBLISH_DEADLINE_MS = 20_000;\n\n/** Pauses before a closed long-lived subscription is opened again, growing to the last. */\nexport const SUBSCRIBE_RETRY_MAX_MS = 60_000;\nexport const SUBSCRIBE_RETRY_MS: readonly number[] = [1_000, 5_000, 15_000, SUBSCRIBE_RETRY_MAX_MS];\n\n/**\n * How long a subscription must stay open past its EOSE before a close starts the\n * pauses over: a relay that drops right after EOSE is not retried every second.\n */\nexport const SUBSCRIBE_STABLE_MS = 30_000;\n\n/** Tries of an order-record write that lost a race with another tab. */\nexport const STORE_WRITE_ATTEMPTS = 5;\n\n/** The device clock may differ from chain time by at most this much to order. */\nexport const MAX_CLOCK_SKEW_SECS = 5 * 60;\n\n/** NIP-59 back-dates a gift wrap up to two days: a read for replies reaches back that far. */\nexport const WRAP_BACKDATE_SECS = 2 * 24 * 60 * 60;\n\n/** The merchant keeps catching up on an order's payments this long after it (plan: 3 days). */\nexport const MERCHANT_CATCH_UP_SECS = 3 * 24 * 60 * 60;\n\n/** No wallet request, first or retry, this close to the end of the merchant's catch-up. */\nexport const PAY_CUTOFF_SECS = 60 * 60;\n\n/**\n * A payment is looked for back to the order's `created_at` minus this margin\n * (the merchant's own scan margin): the order is dated by the chain, a block a\n * little behind it may hold the payment.\n */\nexport const PAYMENT_SCAN_MARGIN_SECS = 30 * 60;\n\n/** Compute units the payment transaction asks for: what pay-core's own builder uses. */\nexport const SOLANA_COMPUTE_UNIT_LIMIT = 200_000;\n","import type { NostrEvent } from 'nostr-tools';\nimport { verifyEvent } from 'nostr-tools/pure';\nimport { MAX_FUTURE_SKEW_SECS } from '../index';\n\n/** Whether a value from a relay has the NIP-01 field types. */\nexport function isEventShaped(event: unknown): event is NostrEvent {\n if (typeof event !== 'object' || event === null) {\n return false;\n }\n const record: Record<string, unknown> = { ...event };\n const { id, pubkey, created_at: createdAt, kind, tags, content, sig } = record;\n return (\n typeof id === 'string' &&\n typeof pubkey === 'string' &&\n typeof createdAt === 'number' &&\n Number.isInteger(createdAt) &&\n typeof kind === 'number' &&\n Number.isInteger(kind) &&\n typeof content === 'string' &&\n typeof sig === 'string' &&\n Array.isArray(tags) &&\n tags.every((tag) => Array.isArray(tag) && tag.every((item) => typeof item === 'string'))\n );\n}\n\n/**\n * Whether an event's id is its hash and its signature is genuine, checked every\n * time on a fresh object: `verifyEvent` caches its verdict on the object it is\n * given, and a spread copy of a genuine event would carry that cache.\n */\nexport function isGenuineEvent(event: unknown): event is NostrEvent {\n if (!isEventShaped(event)) {\n return false;\n }\n return verifyEvent({\n id: event.id,\n pubkey: event.pubkey,\n created_at: event.created_at,\n kind: event.kind,\n tags: event.tags,\n content: event.content,\n sig: event.sig,\n });\n}\n\n/**\n * The newest genuine event of `kind` by `author` among everything the relays\n * returned, or `undefined`. An event dated further ahead than the skew\n * allowance is ignored, so a far-future copy cannot pin an old value; a tie on\n * `created_at` goes to the lowest id (NIP-01).\n */\nexport function newestGenuine(\n events: readonly unknown[],\n kind: number,\n author: string,\n now: number,\n): NostrEvent | undefined {\n let newest: NostrEvent | undefined;\n for (const event of events) {\n if (\n !isEventShaped(event) ||\n event.kind !== kind ||\n event.pubkey !== author ||\n event.created_at > now + MAX_FUTURE_SKEW_SECS ||\n !isGenuineEvent(event)\n ) {\n continue;\n }\n if (\n newest === undefined ||\n event.created_at > newest.created_at ||\n (event.created_at === newest.created_at && event.id < newest.id)\n ) {\n newest = event;\n }\n }\n return newest;\n}\n\nexport function nowSecs(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { isPublicHostname } from '../index';\nimport { DEFAULT_RELAYS, MAX_RELAY_URL_LENGTH, STORE_RELAY_CAP } from './constants';\n\n/**\n * A store-named relay URL the widget may connect to, in one spelling, or\n * `undefined`. Only `wss:` on a public DNS name: the URL comes from the store\n * (its inbox list) or the page (naddr hints), so a loopback, private or IP\n * literal host - or plain `ws:` - is never contacted.\n */\nexport function normalizeRelayUrl(value: unknown): string | undefined {\n if (typeof value !== 'string' || value.length === 0 || value.length > MAX_RELAY_URL_LENGTH) {\n return undefined;\n }\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return undefined;\n }\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 // Repeated slashes are one relay to the pool, so they are one relay here.\n const path = url.pathname.replace(/\\/+/g, '/').replace(/\\/$/, '');\n return `wss://${url.host}${path}`;\n}\n\n/**\n * The server a relay URL reaches (host and port): `wss://r.example.com` and\n * `wss://r.example.com/inbox` are usually one relay, and count once.\n */\nexport function relayHost(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return url;\n }\n}\n\n/** Each usable URL once, in the order given. */\nexport function uniqueRelays(values: readonly unknown[]): string[] {\n const relays: string[] = [];\n for (const value of values) {\n const relay = normalizeRelayUrl(value);\n if (relay !== undefined && !relays.includes(relay)) {\n relays.push(relay);\n }\n }\n return relays;\n}\n\nexport interface StoreRelaySources {\n /** The relays of the store's current inbox list (kind 10050): where it reads and replies. */\n inbox?: readonly unknown[];\n /** Older inbox relays that acknowledged this order: kept for republishing only. */\n acknowledged?: readonly unknown[];\n /** Relay hints from the product naddr. */\n hints?: readonly unknown[];\n}\n\n/**\n * The store-named relays, capped at `STORE_RELAY_CAP` in a fixed priority: the\n * current inbox first (the widget listens there), then old relays that\n * acknowledged the order, then naddr hints - so a page's hints can never crowd\n * out the store's inbox.\n */\nexport function storeRelays(sources: StoreRelaySources): string[] {\n return uniqueRelays([\n ...(sources.inbox ?? []),\n ...(sources.acknowledged ?? []),\n ...(sources.hints ?? []),\n ]).slice(0, STORE_RELAY_CAP);\n}\n\n/**\n * Where the offer and the store's inbox list are read: the default relays,\n * always and outside the cap, plus the capped store-named ones.\n */\nexport function readRelays(sources: StoreRelaySources): string[] {\n const named = storeRelays(sources);\n return [...DEFAULT_RELAYS, ...named.filter((relay) => !DEFAULT_RELAYS.includes(relay))];\n}\n","import type { NostrEvent } from 'nostr-tools';\nimport { KIND_INBOX_RELAYS } from '../index';\nimport { STORE_RELAY_CAP } from './constants';\nimport { newestGenuine, nowSecs } from './events';\nimport type { RelayClient } from './relay-client';\nimport { type StoreRelaySources, readRelays, uniqueRelays } from './relays';\n\nexport interface StoreInbox {\n /** The store's inbox relays the widget may use, capped, in the store's order. */\n relays: string[];\n /** The kind 10050 they came from. */\n event: NostrEvent;\n}\n\n/**\n * The store's inbox relays from the newest genuine kind 10050 signed by the store\n * key among everything the relays returned - the same rule as for the payout list,\n * since a stale copy from one relay would send the order where the merchant no\n * longer reads. `undefined` when there is none, or it names no usable relay: the\n * widget then refuses before ordering.\n */\nexport function newestStoreInbox(\n events: readonly unknown[],\n storePubkey: string,\n now: number = nowSecs(),\n): StoreInbox | undefined {\n const event = newestGenuine(events, KIND_INBOX_RELAYS, storePubkey, now);\n if (event === undefined) {\n return undefined;\n }\n const relays = uniqueRelays(\n event.tags.filter((tag) => tag[0] === 'relay').map((tag) => tag[1]),\n ).slice(0, STORE_RELAY_CAP);\n return relays.length === 0 ? undefined : { relays, event };\n}\n\n/**\n * Read the store's inbox list from the default relays - always, outside the cap -\n * plus the capped store-named relays, and pick it by `newestStoreInbox`.\n */\nexport async function readStoreInbox(\n client: RelayClient,\n sources: StoreRelaySources,\n storePubkey: string,\n now?: number,\n): Promise<StoreInbox | undefined> {\n const events = await client.query(readRelays(sources), [\n { kinds: [KIND_INBOX_RELAYS], authors: [storePubkey] },\n ]);\n return newestStoreInbox(events, storePubkey, now);\n}\n","import {\n type KeyPairSigner,\n type Rpc,\n type SolanaRpcApi,\n getTransactionDecoder,\n getTransactionEncoder,\n partiallySignTransaction,\n} from '@solana/kit';\nimport type { SolanaWallet } from './solana-pay';\n\n/**\n * A wallet backed by a key in this process (the MCP's agent keypair): it signs\n * exactly the wire transaction it is handed, and nothing else - the core checks\n * the signed bytes as it does a browser wallet's.\n */\nexport function localSolanaWallet(signer: KeyPairSigner): SolanaWallet {\n return {\n address: signer.address,\n async signTransaction(bytes) {\n const decoded = getTransactionDecoder().decode(bytes);\n const signed = await partiallySignTransaction([signer.keyPair], decoded);\n return new Uint8Array(getTransactionEncoder().encode(signed));\n },\n };\n}\n\n/** Chain time from a finalized block (the newest may not have its time yet), in seconds. */\nexport async function readChainTime(rpc: Rpc<SolanaRpcApi>): Promise<number> {\n const slot = await rpc.getSlot({ commitment: 'finalized' }).send();\n for (let back = 0n; back < 5n; back += 1n) {\n const time = await rpc.getBlockTime(slot - back).send();\n if (time !== null) {\n return Number(time);\n }\n }\n throw new Error('no block time');\n}\n","import type { ChainFamily, Network } from '@elisym/pay-core';\nimport {\n type DomainKeys,\n type FetchLike,\n type OfferRefusal,\n type OfferWarning,\n type PayoutTarget,\n type VerifiedOffer,\n decodeProductNaddr,\n priceInSubunits,\n productAddress,\n verifyOffer,\n} from '../index';\nimport { OFFER_SNAPSHOT_MAX_AGE_SECS } from './constants';\nimport { nowSecs } from './events';\nimport type { RelayClient } from './relay-client';\nimport { readRelays, uniqueRelays } from './relays';\n\n/** Warnings the buyer must confirm, for the exact payout, before paying. */\nexport const CONFIRM_WARNINGS: readonly OfferWarning[] = [\n 'payout_recently_changed',\n 'payout_changed',\n];\n\n/** A payout the widget can pay: priced in that coin's subunits. */\nexport interface PricedPayout {\n target: PayoutTarget;\n /** The product's price in the coin's subunits (quantity 1). */\n amount: bigint;\n}\n\nexport type WidgetRefusal =\n | OfferRefusal\n /** The page's origin is opaque or not an http(s) origin. */\n | 'bad_page_origin'\n /** No payout the widget can price and pay on the allowed rails and networks. */\n | 'no_payable_payout';\n\nexport type LoadedOffer =\n | {\n ok: true;\n offer: VerifiedOffer;\n /** `30402:<store>:<d>`: the key the widget's records are indexed by. */\n productAddress: string;\n payouts: PricedPayout[];\n /** Warnings that need an explicit confirmation before paying. */\n confirm: OfferWarning[];\n /** Warnings that are only shown. */\n notices: OfferWarning[];\n /** The naddr's usable relay hints (store-named, so capped with the inbox later). */\n hints: string[];\n /** Where the offer was read: the default relays plus the capped hints. */\n relays: string[];\n /** When this snapshot was taken (seconds). */\n snapshotAt: number;\n }\n | { ok: false; refusal: WidgetRefusal; message: string };\n\nexport interface StorePins {\n /** The owner pinned at the first purchase from this store. */\n pinnedOwnerPubkey?: string;\n /** Every payout of every verified offer that delivered from this store. */\n knownPayouts?: readonly { caip19: string; address: string }[];\n}\n\nexport interface LoadOfferOptions {\n client: RelayClient;\n /** The embedding page's origin, from the accepted `hello`. */\n pageOrigin: string;\n /** Set by the page's `strict-origin` attribute: also refuse at levels B and C. */\n strictOrigin?: boolean;\n pins?: StorePins;\n /** Rails the widget can pay on now: required, so a new rail is offered only once it is built. */\n families: readonly ChainFamily[];\n /** The page's `network` attribute: only payouts on this network are offered. */\n network?: Network;\n now?: number;\n /** Domain lookups (nostr.json, DoH); defaults to the global `fetch`. */\n fetch?: FetchLike;\n resolveDomain?: (nip05: string) => Promise<DomainKeys | undefined>;\n}\n\n/** Whether `value` is a real http(s) origin, in its canonical spelling. */\nexport function isPageOrigin(value: unknown): value is string {\n if (typeof value !== 'string' || value === 'null') {\n return false;\n }\n try {\n const url = new URL(value);\n return (url.protocol === 'https:' || url.protocol === 'http:') && url.origin === value;\n } catch {\n return false;\n }\n}\n\n/** Whether a snapshot taken at `snapshotAt` must be verified again before use. */\nexport function isSnapshotStale(snapshotAt: number, now: number = nowSecs()): boolean {\n return now - snapshotAt > OFFER_SNAPSHOT_MAX_AGE_SECS;\n}\n\nfunction refuse(refusal: WidgetRefusal, message: string): LoadedOffer {\n return { ok: false, refusal, message };\n}\n\n/**\n * Verify the offer behind `naddr` for this page and apply the widget's own\n * policy on top: a level A store the page is not on is refused (not only warned\n * about), and only payouts the widget can price and pay are offered.\n */\nexport async function loadOffer(naddr: string, options: LoadOfferOptions): Promise<LoadedOffer> {\n if (!isPageOrigin(options.pageOrigin)) {\n return refuse('bad_page_origin', 'The page embedding the checkout has no usable origin');\n }\n return loadVerified(naddr, options, options.pageOrigin);\n}\n\n/**\n * The offer for a buyer that is not a web page (an AI agent through the MCP):\n * the same verification, with no page origin, so no origin rule applies. The\n * caller shows the trust level and the verified domain to its user instead.\n */\nexport function loadOfferForAgent(\n naddr: string,\n options: Omit<LoadOfferOptions, 'pageOrigin' | 'strictOrigin'>,\n): Promise<LoadedOffer> {\n return loadVerified(naddr, options, undefined);\n}\n\nasync function loadVerified(\n naddr: string,\n options: Omit<LoadOfferOptions, 'pageOrigin'>,\n pageOrigin: string | undefined,\n): Promise<LoadedOffer> {\n const pointer = decodeProductNaddr(naddr);\n if (pointer === undefined) {\n return refuse('bad_pointer', 'Not a product naddr');\n }\n const now = options.now ?? nowSecs();\n const hints = uniqueRelays(pointer.relays);\n const relays = readRelays({ hints });\n const verification = await verifyOffer(\n naddr,\n {\n fetchEvents: (filters) => options.client.query(relays, filters),\n ...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n ...(options.resolveDomain === undefined ? {} : { resolveDomain: options.resolveDomain }),\n },\n {\n now,\n ...(pageOrigin === undefined ? {} : { pageOrigin }),\n ...(options.strictOrigin === true ? { strictOrigin: true } : {}),\n ...(options.pins?.pinnedOwnerPubkey === undefined\n ? {}\n : { pinnedOwnerPubkey: options.pins.pinnedOwnerPubkey }),\n ...(options.pins?.knownPayouts === undefined\n ? {}\n : { knownPayouts: options.pins.knownPayouts }),\n },\n );\n if (!verification.ok) {\n return refuse(verification.refusal, verification.message);\n }\n const { offer } = verification;\n // A level A store vouches for one domain; a page elsewhere is refused by default.\n if (offer.warnings.includes('origin_mismatch')) {\n return refuse('origin_mismatch', 'This store does not sell on this site');\n }\n const payouts: PricedPayout[] = [];\n for (const target of offer.payouts) {\n const { chain, asset } = target.caip19;\n if (!options.families.includes(chain.family)) {\n continue;\n }\n if (options.network !== undefined && chain.network !== options.network) {\n continue;\n }\n let amount: bigint;\n try {\n amount = priceInSubunits(offer.product.price, asset);\n } catch {\n continue;\n }\n if (amount > 0n) {\n payouts.push({ target, amount });\n }\n }\n if (payouts.length === 0) {\n return refuse('no_payable_payout', 'This product cannot be paid here');\n }\n return {\n ok: true,\n offer,\n productAddress: productAddress(offer.product),\n payouts,\n confirm: offer.warnings.filter((warning) => CONFIRM_WARNINGS.includes(warning)),\n notices: offer.warnings.filter((warning) => !CONFIRM_WARNINGS.includes(warning)),\n hints,\n relays,\n snapshotAt: now,\n };\n}\n","import type { NostrEvent } from 'nostr-tools';\nimport type { VerifiedOffer } from '../index';\n\n/**\n * Where one order stands. The order is sent and acknowledged BEFORE any wallet\n * opens (`created` -> `ordered`); a payment attempt holds a marker (`paying`);\n * a payment found on chain waits for the store (`paid`).\n */\nexport type OrderState =\n /** Written, the order not yet acknowledged by the store's inbox relays. */\n | 'created'\n /** Acknowledged; no payment attempt holds a marker. */\n | 'ordered'\n /** A payment attempt holds the marker. */\n | 'paying'\n /** The payment was found on chain; waiting for the store's status. */\n | 'paid'\n /** The store delivered. */\n | 'completed'\n /** The store cancelled with a refund. */\n | 'refunded'\n /** No payment by the deadline: a new order may start (it is still reconciled). */\n | 'ended-unpaid'\n /** Tempo: the money sits with the recipient's transfer policy guard. */\n | 'blocked';\n\nexport type PaymentMarker =\n | {\n rail: 'solana';\n /** Random per attempt: every clear or replace is a compare-and-swap on it. */\n attemptId: string;\n setAt: number;\n /** The blockhash the widget set; the widget broadcasts only a message with this lifetime. */\n blockhash: string;\n /** Decimal string: the attempt is over once `finalized` passes this height. */\n lastValidBlockHeight: string;\n /**\n * Decimal string: the slot the blockhash was read at. Nothing of this attempt can\n * sit below it, so an RPC whose ledger starts above it cannot prove \"not paid\".\n */\n slot?: string;\n /** The signature of the transaction the wallet signed, once known. */\n signature?: string;\n /**\n * The signed wire transaction (base64), written with its signature BEFORE the\n * first broadcast and rebroadcast until it lands or its blockhash expires.\n */\n signedTransaction?: string;\n }\n | {\n rail: 'tempo';\n attemptId: string;\n setAt: number;\n /** Decimal string: the finalized block read before the wallet call. */\n floorBlock: string;\n /** The hash the wallet returned. */\n txHash?: string;\n /** A bundle id (`wallet_sendCalls`): approved, the hash comes later. */\n bundleId?: string;\n };\n\nexport interface OrderStatus {\n status: 'pending' | 'confirmed' | 'completed' | 'cancelled';\n /** When the widget accepted it (seconds). */\n at: number;\n delivery?: string;\n refunded?: boolean;\n}\n\nexport interface OrderRecord {\n orderId: string;\n /** `30402:<store>:<d>`: records are indexed by it, never by the naddr string. */\n productAddress: string;\n storePubkey: string;\n /** The one-time buyer key for this order (hex). */\n buyerSecretKey: string;\n buyerPubkey: string;\n /** The order rumor's `created_at` (chain time, seconds). */\n createdAt: number;\n /** Bumped on every write: a writer states the version it judged. */\n version: number;\n state: OrderState;\n payout: { caip19: string; address: string };\n /** Decimal string of subunits. */\n amount: string;\n /** The receipt's `medium`: `solana`, `solana-devnet`, `tempo`, `tempo-moderato`. */\n medium: string;\n /** The derived payment reference (base58) or memo (0x hex). */\n reference: string;\n /** The verified offer the order was placed against. */\n offer: VerifiedOffer;\n /** The composed payment request, written once before the first marker. */\n paymentRequest?: string;\n /** Signed wraps, republished byte for byte on resume. */\n orderWrap?: NostrEvent;\n receiptWrap?: NostrEvent;\n /** The store inbox relays the order went to. */\n inboxRelays: string[];\n /** Relays that answered OK to the order wrap. */\n acknowledgedRelays: string[];\n marker?: PaymentMarker;\n /** The transaction that paid, once found. */\n paidTx?: string;\n status?: OrderStatus;\n}\n\nexport const TERMINAL_STATES: readonly OrderState[] = ['completed', 'refunded'];\n\nexport function isTerminal(record: Pick<OrderRecord, 'state'>): boolean {\n return TERMINAL_STATES.includes(record.state);\n}\n\n/**\n * Whether the record keeps any other order for the same product from paying: a\n * set marker until the attempt provably ended (`ended-unpaid`, or `blocked` on\n * Tempo), and a found payment until the store answers. \"No stored signature\" is\n * never \"never sent\" on its own.\n */\nexport function holdsPayExclusion(\n record: Pick<OrderRecord, 'state' | 'marker' | 'paidTx'>,\n): boolean {\n if (isTerminal(record)) {\n return false;\n }\n // A found payment holds it until the store answers, whatever the state says.\n if (record.state === 'paid' || record.paidTx !== undefined) {\n return true;\n }\n if (record.state === 'ended-unpaid' || record.state === 'blocked') {\n return false;\n }\n return record.marker !== undefined;\n}\n\n/**\n * Which record of a product to show first, lowest rank first: a live order with\n * news (a payment found, a blocked payment, a store answer); then an order still\n * in progress; then a finished purchase; then an order that ended unpaid. A\n * finished purchase never hides a newer order in progress (a repeat purchase),\n * and neither does an order the store cancelled that holds no payment attempt.\n */\nfunction showRank(record: OrderRecord): number {\n if (isTerminal(record)) {\n return 2;\n }\n if (record.state === 'ended-unpaid') {\n return 3;\n }\n if (record.state === 'paid' || record.state === 'blocked' || record.paidTx !== undefined) {\n return 0;\n }\n const cancelled = record.status?.status === 'cancelled';\n return record.status !== undefined && (!cancelled || holdsPayExclusion(record)) ? 0 : 1;\n}\n\nfunction newer(left: OrderRecord, right: OrderRecord): OrderRecord {\n if (left.createdAt !== right.createdAt) {\n return left.createdAt > right.createdAt ? left : right;\n }\n return left.orderId < right.orderId ? left : right;\n}\n\n/**\n * The record the widget shows for a product: the best rank (`showRank`), then\n * the newest within it.\n */\nexport function recordToShow(records: readonly OrderRecord[]): OrderRecord | undefined {\n let shown: OrderRecord | undefined;\n for (const record of records) {\n if (shown === undefined || showRank(record) < showRank(shown)) {\n shown = record;\n } else if (showRank(record) === showRank(shown)) {\n shown = newer(shown, record);\n }\n }\n return shown;\n}\n","import type { ChainConfig } from '@elisym/pay-core';\nimport type { NostrEvent } from 'nostr-tools';\nimport { generateSecretKey, getPublicKey } from 'nostr-tools/pure';\nimport { bytesToHex, hexToBytes } from 'nostr-tools/utils';\nimport {\n KIND_GIFT_WRAP,\n MAX_FUTURE_SKEW_SECS,\n type OrderStatusMessage,\n type OfferWarning,\n buildOrderMessage,\n deriveOrderPaymentReference,\n unwrapOrderMessage,\n wrapOrderMessage,\n} from '../index';\nimport { MAX_CLOCK_SKEW_SECS, STORE_WRITE_ATTEMPTS, WRAP_BACKDATE_SECS } from './constants';\nimport { readStoreInbox } from './inbox';\nimport { type LoadedOffer, type PricedPayout, isSnapshotStale } from './offer';\nimport { type OrderRecord, type OrderStatus, isTerminal } from './order-record';\nimport type { OrderStore, StoreWrite } from './order-store';\nimport type { RelayClient } from './relay-client';\nimport { storeRelays } from './relays';\n\ntype ReadyOffer = Extract<LoadedOffer, { ok: true }>;\n\n/** The receipt `medium` of a chain: `solana`, `solana-devnet`, `tempo`, `tempo-moderato`. */\nexport function mediumOf(chain: Pick<ChainConfig, 'slug' | 'network'>): string {\n if (chain.network === 'mainnet') {\n return chain.slug;\n }\n return chain.slug === 'tempo' ? 'tempo-moderato' : `${chain.slug}-${chain.network}`;\n}\n\n/**\n * Whether the device clock is close enough to chain time to order: the rumor is\n * dated by the chain, but the seal and the wrap by the device, and the widget\n * drops a store status dated ahead of it - a slow clock would lose the delivery.\n */\nexport function clockAgrees(chainTime: number, deviceTime: number): boolean {\n return Math.abs(chainTime - deviceTime) <= MAX_CLOCK_SKEW_SECS;\n}\n\n/**\n * How a fresh offer compares with the one the buyer confirmed: the same payout\n * and price and no new warning to confirm (`same`); something the buyer must\n * look at again (`changed`); or the chosen payout is gone (`gone`).\n */\nexport function compareOffers(\n shown: PricedPayout,\n confirmed: readonly OfferWarning[],\n fresh: ReadyOffer,\n): 'same' | 'changed' | 'gone' {\n const match = fresh.payouts.find(\n (payout) =>\n payout.target.caip19.id === shown.target.caip19.id &&\n payout.target.address === shown.target.address,\n );\n if (match === undefined) {\n return 'gone';\n }\n if (match.amount !== shown.amount) {\n return 'changed';\n }\n return fresh.confirm.every((warning) => confirmed.includes(warning)) ? 'same' : 'changed';\n}\n\nexport interface PlaceOrderInput {\n /** A FRESH verified offer (at most two minutes old). */\n offer: ReadyOffer;\n payout: PricedPayout;\n email?: string;\n /** Chain time read just before ordering (seconds). */\n chainTime: number;\n /** The device clock at the same moment (seconds). */\n deviceTime: number;\n}\n\nexport interface OrderDeps {\n store: OrderStore;\n /** Reads (the offer, the inbox list): no key. */\n readClient: RelayClient;\n /**\n * A NEW client for one order's writes, answering AUTH with its buyer key. The\n * callee owns it and closes it when done, so it must never be one the caller\n * also listens with.\n */\n clientFor: (buyerSecretKey: Uint8Array) => RelayClient;\n}\n\nexport type PlaceOrderResult =\n | { ok: true; record: OrderRecord }\n | {\n ok: false;\n reason:\n /** The device clock is too far from chain time. */\n | 'clock_skew'\n /** The offer is older than two minutes, or the payout is not one of its own: verify again. */\n | 'stale_offer'\n /** The store names no usable inbox relay: nowhere to send the order. */\n | 'no_store_inbox'\n /** The order went out but too few inbox relays took it; `resume` may try again. */\n | 'not_acknowledged';\n record?: OrderRecord;\n };\n\n/**\n * Place a direct-mode order: a fresh one-time buyer key, a random order id, the\n * reference derived from them, the order sealed and gift-wrapped to the store,\n * recorded, then sent to the store's CURRENT inbox relays. It counts as placed\n * only once enough of them said OK - the wallet opens only after that, since the\n * merchant cannot attribute a payment without its order.\n */\nexport async function placeOrder(\n input: PlaceOrderInput,\n deps: OrderDeps,\n): Promise<PlaceOrderResult> {\n const { offer, payout } = input;\n if (!clockAgrees(input.chainTime, input.deviceTime)) {\n return { ok: false, reason: 'clock_skew' };\n }\n // The order is placed at the price and payout of THIS fresh offer, nothing older.\n const offered = offer.payouts.some(\n (candidate) =>\n candidate.target.caip19.id === payout.target.caip19.id &&\n candidate.target.address === payout.target.address &&\n candidate.amount === payout.amount,\n );\n if (isSnapshotStale(offer.snapshotAt, input.deviceTime) || !offered) {\n return { ok: false, reason: 'stale_offer' };\n }\n const storePubkey = offer.offer.storePubkey;\n const inbox = await readStoreInbox(\n deps.readClient,\n { hints: offer.hints },\n storePubkey,\n input.deviceTime,\n );\n if (inbox === undefined) {\n return { ok: false, reason: 'no_store_inbox' };\n }\n const buyerKey = generateSecretKey();\n const buyerPubkey = getPublicKey(buyerKey);\n const orderId = crypto.randomUUID();\n const reference = deriveOrderPaymentReference({ storePubkey, buyerPubkey, orderId });\n const rumor = buildOrderMessage(\n {\n type: 'order',\n storePubkey,\n orderId,\n items: [{ product: offer.productAddress, quantity: 1 }],\n total: {\n amount: offer.offer.product.price.amount,\n currency: offer.offer.product.price.currency,\n },\n ...(input.email === undefined ? {} : { email: input.email }),\n },\n input.chainTime,\n );\n const wrapped = wrapOrderMessage(rumor, buyerKey, storePubkey);\n const chain = payout.target.caip19.chain;\n const record: OrderRecord = {\n orderId,\n productAddress: offer.productAddress,\n storePubkey,\n buyerSecretKey: bytesToHex(buyerKey),\n buyerPubkey,\n createdAt: input.chainTime,\n version: 1,\n state: 'created',\n payout: { caip19: payout.target.caip19.id, address: payout.target.address },\n amount: payout.amount.toString(),\n medium: mediumOf(chain),\n reference: chain.family === 'solana' ? reference.solana : reference.tempo,\n offer: offer.offer,\n // Kept before it is sent: a crash in between is resumed by sending the same wrap.\n orderWrap: wrapped.recipientWrap,\n inboxRelays: inbox.relays,\n acknowledgedRelays: [],\n };\n await deps.store.add(record);\n return acknowledge(record, inbox.relays, inbox.relays, deps);\n}\n\n/**\n * Send the order wrap to `sendTo` and, once enough of the store's CURRENT inbox\n * relays (`inbox`) took it, move the record to `ordered`. Relays that left the\n * inbox may still hold the order, but never count.\n */\nasync function acknowledge(\n record: OrderRecord,\n sendTo: readonly string[],\n inbox: readonly string[],\n deps: OrderDeps,\n): Promise<PlaceOrderResult> {\n if (record.orderWrap === undefined) {\n return { ok: false, reason: 'not_acknowledged', record };\n }\n const client = deps.clientFor(hexToBytes(record.buyerSecretKey));\n try {\n const sent = await client.publish(sendTo, record.orderWrap);\n let current = record;\n // Another tab may write the record meanwhile: merge this tab's acknowledgements\n // into what is stored and try again, a bounded number of times.\n for (let attempt = 0; attempt < STORE_WRITE_ATTEMPTS; attempt += 1) {\n const acknowledged = [...new Set([...current.acknowledgedRelays, ...sent.accepted])];\n const written = await deps.store.update(current.orderId, current.version, {\n state: 'ordered',\n inboxRelays: [...inbox],\n acknowledgedRelays: acknowledged,\n });\n if (written.ok) {\n return { ok: true, record: await settleHeldStatus(deps.store, written.record) };\n }\n if (written.reason !== 'conflict') {\n // Too few took it: keep who did, so a later attempt adds to them.\n const kept = await deps.store.update(current.orderId, current.version, {\n inboxRelays: [...inbox],\n acknowledgedRelays: acknowledged,\n });\n if (kept.ok) {\n return { ok: false, reason: 'not_acknowledged', record: kept.record };\n }\n if (kept.reason !== 'conflict') {\n return { ok: false, reason: 'not_acknowledged', record: current };\n }\n }\n const stored = await deps.store.get(current.orderId);\n if (stored === undefined) {\n return { ok: false, reason: 'not_acknowledged', record: current };\n }\n // Another tab ordered it: report what is stored, not this stale copy.\n if (stored.state !== 'created') {\n return { ok: true, record: stored };\n }\n current = stored;\n }\n return { ok: false, reason: 'not_acknowledged', record: current };\n } finally {\n client.close();\n }\n}\n\n/**\n * The buyer's receipt (kind 17) once a payment went out: the medium, the derived\n * reference and the transaction, sealed by the buyer key, recorded (for byte-for-\n * byte republishing) and sent to the order's inbox relays.\n */\nexport async function sendReceipt(\n record: OrderRecord,\n tx: string,\n createdAt: number,\n deps: OrderDeps,\n): Promise<StoreWrite> {\n const buyerKey = hexToBytes(record.buyerSecretKey);\n const rumor = buildOrderMessage(\n {\n type: 'receipt',\n storePubkey: record.storePubkey,\n orderId: record.orderId,\n payment: { medium: record.medium, reference: record.reference, tx },\n },\n createdAt,\n );\n const wrapped = wrapOrderMessage(rumor, buyerKey, record.storePubkey);\n const written = await deps.store.update(record.orderId, record.version, {\n receiptWrap: wrapped.recipientWrap,\n });\n if (written.ok) {\n const client = deps.clientFor(buyerKey);\n try {\n await client.publish(record.inboxRelays, wrapped.recipientWrap);\n } finally {\n client.close();\n }\n }\n return written;\n}\n\n/**\n * On resume: read the store's inbox list again, and republish the SAME order and\n * receipt wraps byte for byte to the union of its current inbox and the relays\n * that took the order before (capped); a record not yet acknowledged may become\n * so here. Returns the relays to listen on for the store's status.\n */\nexport async function resumeOrder(\n record: OrderRecord,\n deps: OrderDeps,\n now: number,\n): Promise<{ record: OrderRecord; relays: string[] }> {\n const fresh = await readStoreInbox(\n deps.readClient,\n { acknowledged: record.acknowledgedRelays },\n record.storePubkey,\n now,\n );\n const relays = storeRelays({\n inbox: fresh?.relays ?? record.inboxRelays,\n acknowledged: record.acknowledgedRelays,\n });\n if (record.state === 'created') {\n // No valid store inbox list: nowhere the store is known to read, so no order.\n if (fresh === undefined) {\n return { record, relays };\n }\n const placed = await acknowledge(record, relays, fresh.relays, deps);\n return { record: placed.record ?? record, relays };\n }\n const client = deps.clientFor(hexToBytes(record.buyerSecretKey));\n try {\n for (const wrap of [record.orderWrap, record.receiptWrap]) {\n if (wrap !== undefined) {\n await client.publish(relays, wrap);\n }\n }\n } finally {\n client.close();\n }\n // Receipts sent from now on go where the store reads today.\n // Written only when it changed: every write bumps the version another tab's\n // payment writes are checked against.\n const sameInbox =\n fresh !== undefined &&\n fresh.relays.length === record.inboxRelays.length &&\n fresh.relays.every((relay, index) => record.inboxRelays[index] === relay);\n if (fresh !== undefined && !sameInbox && !isTerminal(record)) {\n const moved = await deps.store.update(record.orderId, record.version, {\n inboxRelays: fresh.relays,\n });\n if (moved.ok) {\n return { record: moved.record, relays };\n }\n }\n return { record, relays };\n}\n\n/**\n * A store status for this record, or `undefined`: sealed by the store key, for\n * this order id, naming this record's buyer key. Anything else - another\n * sender, another order, another buyer - is not this order's answer.\n */\nexport function statusFor(record: OrderRecord, wrap: NostrEvent): OrderStatusMessage | undefined {\n const unwrapped = unwrapOrderMessage(wrap, hexToBytes(record.buyerSecretKey));\n if (\n unwrapped === undefined ||\n unwrapped.senderPubkey !== record.storePubkey ||\n unwrapped.message.type !== 'status' ||\n unwrapped.message.orderId !== record.orderId ||\n unwrapped.message.buyerPubkey !== record.buyerPubkey\n ) {\n return undefined;\n }\n return unwrapped.message;\n}\n\n/** The delivery as a link, only when it is `https:`; anything else is shown as text. */\nexport function deliveryLink(value: string): string | undefined {\n try {\n const url = new URL(value);\n return url.protocol === 'https:' ? url.href : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** The state a store status settles: delivered, or cancelled with a refund. */\nfunction settledState(message: OrderStatusMessage): 'completed' | 'refunded' | undefined {\n if (message.status === 'completed') {\n return 'completed';\n }\n if (message.status === 'cancelled' && message.refund !== undefined) {\n return 'refunded';\n }\n return undefined;\n}\n\n/** TOFU: the owner, and every payout of the offer that delivered. */\nasync function rememberDelivery(store: OrderStore, record: OrderRecord): Promise<void> {\n await store.rememberDelivery(\n record.storePubkey,\n record.offer.ownerPubkey,\n record.offer.payouts.map((target) => ({ caip19: target.caip19.id, address: target.address })),\n );\n}\n\n/**\n * A settling status heard while the order was not yet acknowledged was kept\n * alone; once the record is ordered it settles now (the same wrap is not handed\n * on again this session). Left as it is on a concurrent change: the next\n * subscription hears the status again.\n */\nasync function settleHeldStatus(store: OrderStore, record: OrderRecord): Promise<OrderRecord> {\n const held = record.status;\n let settles: 'completed' | 'refunded' | undefined;\n if (held?.status === 'completed') {\n settles = 'completed';\n } else if (held?.status === 'cancelled' && held.refunded === true) {\n settles = 'refunded';\n }\n if (settles === undefined) {\n return record;\n }\n const settled = await store.update(record.orderId, record.version, { state: settles });\n if (!settled.ok) {\n return record;\n }\n if (settles === 'completed') {\n await rememberDelivery(store, settled.record);\n }\n return settled.record;\n}\n\n/**\n * Record a store status: the status itself (it only moves forward), and the\n * state it settles - `completed` on delivery, `refunded` on a cancellation with\n * a refund. The write retries on a concurrent change; a status the record can no\n * longer take is left out.\n */\nexport async function applyStatus(\n store: OrderStore,\n orderId: string,\n message: OrderStatusMessage,\n at: number,\n): Promise<OrderRecord | undefined> {\n const status: OrderStatus = {\n status: message.status,\n at,\n ...(message.delivery === undefined ? {} : { delivery: message.delivery.value }),\n ...(message.refund === undefined ? {} : { refunded: true }),\n };\n for (let attempt = 0; attempt < STORE_WRITE_ATTEMPTS; attempt += 1) {\n const current = await store.get(orderId);\n if (current === undefined) {\n return undefined;\n }\n const settles = settledState(message);\n const heardBefore =\n current.status?.status === status.status &&\n current.status.delivery === status.delivery &&\n current.status.refunded === status.refunded;\n // Heard again (a re-read, another relay): nothing new, no write - unless the\n // record could not settle when it was first heard and may now.\n if (heardBefore && (settles === undefined || current.state === settles)) {\n return current;\n }\n const withState = await store.update(orderId, current.version, {\n status,\n ...(settles === undefined ? {} : { state: settles }),\n });\n if (withState.ok) {\n if (settles === 'completed') {\n await rememberDelivery(store, withState.record);\n }\n return withState.record;\n }\n if (withState.reason === 'conflict') {\n continue;\n }\n // The state cannot move (e.g. not yet ordered): keep the status alone.\n if (heardBefore) {\n return current;\n }\n const alone = await store.update(orderId, current.version, { status });\n if (alone.ok) {\n return alone.record;\n }\n if (alone.reason !== 'conflict') {\n return undefined;\n }\n }\n return undefined;\n}\n\n/**\n * Listen for the store's status on `relays`: gift wraps to the buyer key from\n * the order's date back two days and the skew (NIP-59 back-dates wraps), each\n * checked by `statusFor` before it is handed on. It listens with its own client\n * that answers AUTH with the buyer key (inbox relays often ask for it before\n * serving gift wraps), closed with the subscription.\n */\nexport function listenForStatus(\n record: OrderRecord,\n relays: readonly string[],\n deps: Pick<OrderDeps, 'clientFor'>,\n onStatus: (message: OrderStatusMessage) => void,\n): { close(): void } {\n const client = deps.clientFor(hexToBytes(record.buyerSecretKey));\n const subscription = client.subscribe(\n relays,\n {\n kinds: [KIND_GIFT_WRAP],\n '#p': [record.buyerPubkey],\n since: record.createdAt - WRAP_BACKDATE_SECS - MAX_FUTURE_SKEW_SECS,\n },\n (wrap) => {\n const status = statusFor(record, wrap);\n if (status !== undefined) {\n onStatus(status);\n }\n },\n );\n return {\n close() {\n subscription.close();\n client.close();\n },\n };\n}\n","import { ORDER_ACK_TARGET } from './constants';\nimport { isGenuineEvent } from './events';\nimport {\n type OrderRecord,\n type OrderState,\n type OrderStatus,\n type PaymentMarker,\n holdsPayExclusion,\n isTerminal,\n} from './order-record';\nimport { relayHost } from './relays';\n\n/** Per store, what earlier purchases pinned (TOFU). */\nexport interface StorePinsRecord {\n storePubkey: string;\n pinnedOwnerPubkey: string;\n /** The union of every payout of every verified offer that delivered from this store. */\n knownPayouts: { caip19: string; address: string }[];\n}\n\nexport type StoreWrite =\n | { ok: true; record: OrderRecord }\n | {\n ok: false;\n /**\n * `missing`: no such record. `conflict`: the record (its version or its\n * marker's attempt) is not the one the caller judged. `exclusion`: another\n * record for this product holds a live payment. `not_ready`: the record's\n * state does not allow this write.\n */\n reason: 'missing' | 'conflict' | 'exclusion' | 'not_ready';\n /** For `exclusion`: the order holding it. */\n holder?: string;\n };\n\n/**\n * Fields a plain update may change. What the order and its payment were made of\n * (payout, amount, reference, offer, ...) is fixed when the record is added; the\n * marker and the version have their own paths.\n */\nexport type RecordPatch = Partial<\n Pick<\n OrderRecord,\n | 'state'\n | 'paymentRequest'\n | 'orderWrap'\n | 'receiptWrap'\n | 'inboxRelays'\n | 'acknowledgedRelays'\n | 'paidTx'\n | 'status'\n >\n>;\n\n/** The keys of `RecordPatch`, enforced at runtime too: a spread record carries more. */\nconst PATCH_KEYS = [\n 'state',\n 'paymentRequest',\n 'orderWrap',\n 'receiptWrap',\n 'inboxRelays',\n 'acknowledgedRelays',\n 'paidTx',\n 'status',\n] as const satisfies readonly (keyof RecordPatch)[];\n\n/** The statuses that may follow a stored one: a store's answer only moves forward. */\nconst STATUS_SUCCESSORS: Record<OrderStatus['status'], readonly OrderStatus['status'][]> = {\n pending: ['pending', 'confirmed', 'completed', 'cancelled'],\n confirmed: ['confirmed', 'completed', 'cancelled'],\n cancelled: ['cancelled', 'completed'],\n completed: ['completed'],\n};\n\n/** The states a found payment (`paidTx`) may be recorded with. */\nconst PAID_STATES: readonly OrderState[] = ['paid', 'completed', 'refunded'];\n\n/**\n * The states a plain update may move a record to. Only forward: an ended order\n * is never reopened (a new order starts instead), a terminal record never\n * changes, `paying` is entered only by `setMarker` and left for `ordered` or\n * `ended-unpaid` only by `clearMarker`.\n */\nconst NEXT_STATES: Record<OrderState, readonly OrderState[]> = {\n created: ['ordered'],\n ordered: ['paid', 'completed', 'refunded', 'ended-unpaid'],\n paying: ['paid', 'completed', 'refunded', 'blocked'],\n paid: ['completed', 'refunded'],\n 'ended-unpaid': ['paid', 'completed', 'refunded', 'blocked'],\n blocked: ['paid', 'completed', 'refunded'],\n completed: [],\n refunded: [],\n};\n\n/** Why a plain patch may not apply to `current`, or `undefined` when it may. */\nfunction patchRefusal(current: OrderRecord, patch: RecordPatch): 'not_ready' | undefined {\n if (isTerminal(current)) {\n return 'not_ready';\n }\n if (\n patch.state !== undefined &&\n patch.state !== current.state &&\n !NEXT_STATES[current.state].includes(patch.state)\n ) {\n return 'not_ready';\n }\n // Written once, before the first marker: resume and every verdict use this request.\n const nextState = patch.state ?? current.state;\n if (\n patch.paymentRequest !== undefined &&\n (current.paymentRequest !== undefined || nextState !== 'ordered')\n ) {\n return 'not_ready';\n }\n // Only a Tempo payment can sit with a transfer-policy guard.\n if (\n patch.state === 'blocked' &&\n current.state !== 'blocked' &&\n !current.payout.caip19.startsWith('eip155:')\n ) {\n return 'not_ready';\n }\n // The transaction that paid is written once, together with the state it\n // means: a record whose payment was found is never left open to pay again, and\n // a second payment found later is reconciled by hand, never erasing the first.\n if (\n patch.paidTx !== undefined &&\n (current.paidTx !== undefined || !PAID_STATES.includes(nextState))\n ) {\n return 'not_ready';\n }\n // The receipt is republished byte for byte; only a Solana retry (still paying,\n // nothing found yet) sends a new one, for its own transaction.\n if (\n patch.receiptWrap !== undefined &&\n current.receiptWrap !== undefined &&\n current.state !== 'paying'\n ) {\n return 'not_ready';\n }\n // A store's answer never goes back: relays return old status wraps in any\n // order, and a stale `pending` must not reopen a cancelled order for paying.\n // Once `completed` is seen it is kept; after `cancelled` only a delivery or a\n // repeated cancellation (a refund) may follow.\n if (patch.status !== undefined && current.status !== undefined) {\n const allowed = STATUS_SUCCESSORS[current.status.status];\n if (!allowed.includes(patch.status.status)) {\n return 'not_ready';\n }\n // A refund, once seen, is kept: a stale cancellation without one never erases it.\n if (current.status.refunded === true && patch.status.refunded !== true) {\n return 'not_ready';\n }\n }\n // Acknowledged means the store's inbox holds the signed order - two of its\n // relays said OK (one when it lists one): the wallet may open only after that.\n // Counted per relay SERVER (host and port): two URLs of one relay are one.\n if (patch.state === 'ordered' && current.state === 'created') {\n const inbox = patch.inboxRelays ?? current.inboxRelays;\n const inboxHosts = new Set(inbox.map(relayHost));\n const acknowledgedHosts = new Set(\n (patch.acknowledgedRelays ?? current.acknowledgedRelays)\n .filter((relay) => inbox.includes(relay))\n .map(relayHost),\n );\n const wrap = patch.orderWrap ?? current.orderWrap;\n if (\n wrap === undefined ||\n !isGenuineEvent(wrap) ||\n inboxHosts.size === 0 ||\n acknowledgedHosts.size < Math.min(ORDER_ACK_TARGET, inboxHosts.size)\n ) {\n return 'not_ready';\n }\n }\n // Republished byte for byte on resume: the same rumor, never a new one.\n if (patch.orderWrap !== undefined && current.orderWrap !== undefined) {\n return 'not_ready';\n }\n return undefined;\n}\n\n/**\n * Whether the store has closed the order - cancelled or delivered it. No wallet\n * request, first or retry, is ever made for such an order.\n */\nfunction storeClosed(record: Pick<OrderRecord, 'status'>): boolean {\n return record.status?.status === 'cancelled' || record.status?.status === 'completed';\n}\n\n/** The rail a record pays on, from its payout: the marker must be of the same rail. */\nfunction railOf(record: Pick<OrderRecord, 'payout'>): PaymentMarker['rail'] {\n return record.payout.caip19.startsWith('eip155:') ? 'tempo' : 'solana';\n}\n\n/** What a marker proves was requested: a signed transaction, a sent hash or an approved bundle. */\nfunction markerEvidence(marker: PaymentMarker): string[] {\n return marker.rail === 'solana'\n ? [marker.signature ?? '', marker.signedTransaction ?? '']\n : [marker.txHash ?? '', marker.bundleId ?? ''];\n}\n\nfunction holdsEvidence(marker: PaymentMarker): boolean {\n return markerEvidence(marker).some((value) => value !== '');\n}\n\n/**\n * Whether `next` keeps everything `current` proves: evidence is only ever added\n * (a retry replaces an expired Solana attempt; its old signature is checked\n * before the retry is allowed).\n */\nfunction keepsEvidence(current: PaymentMarker, next: PaymentMarker): boolean {\n const before = markerEvidence(current);\n const after = markerEvidence(next);\n return before.every((value, index) => value === '' || value === after[index]);\n}\n\n/**\n * Where order records live. Every money rule is judged by the core (below) on\n * what `transactProduct` hands it; a backend only makes that read-judge-write\n * atomic and durable: the checkout's IndexedDB (one readwrite transaction with\n * strict durability), the MCP's locked, fsynced file, or memory in tests.\n *\n * `fn` is synchronous: the rule runs between the read and the write of ONE\n * transaction (an `await` inside would let IndexedDB commit part-way). A\n * backend resolves only once the writes are committed; a write that did not\n * commit did not happen, and nothing is decided on it.\n */\nexport interface OrderBackend {\n read(orderId: string): Promise<OrderRecord | undefined>;\n /** Every record for a product (any order; the store sorts). */\n forProduct(productAddress: string): Promise<OrderRecord[]>;\n /** Read the product's records, run `fn`, commit its writes (whole records, by `orderId`). */\n transactProduct<T>(\n productAddress: string,\n fn: (records: readonly OrderRecord[]) => { write?: readonly OrderRecord[]; result: T },\n ): Promise<T>;\n readPins(storePubkey: string): Promise<StorePinsRecord | undefined>;\n /** Read one store's pins, run `fn`, commit its write. */\n transactPins<T>(\n storePubkey: string,\n fn: (pins: StorePinsRecord | undefined) => { write?: StorePinsRecord; result: T },\n ): Promise<T>;\n}\n\n/** A rule's verdict: what the caller is told, and the record to write when it is `ok`. */\ninterface Judged {\n result: StoreWrite;\n write?: readonly OrderRecord[];\n}\n\nfunction refused(reason: Extract<StoreWrite, { ok: false }>['reason'], holder?: string): Judged {\n return { result: holder === undefined ? { ok: false, reason } : { ok: false, reason, holder } };\n}\n\nfunction accepted(record: OrderRecord): Judged {\n return { result: { ok: true, record }, write: [record] };\n}\n\n/**\n * Another record of the same product that holds the pay exclusion, judged in the\n * same transaction as the write: every new wallet request (a first attempt or a\n * retry) is atomic with this check.\n */\nfunction exclusionHolder(\n records: readonly OrderRecord[],\n current: OrderRecord,\n): OrderRecord | undefined {\n return records.find(\n (sibling) => sibling.orderId !== current.orderId && holdsPayExclusion(sibling),\n );\n}\n\n/** The judged record, or a refusal when it is gone or is not the version judged. */\nfunction judgedRecord(\n records: readonly OrderRecord[],\n orderId: string,\n expectedVersion: number,\n): OrderRecord | Judged {\n const current = records.find((record) => record.orderId === orderId);\n if (current === undefined) {\n return refused('missing');\n }\n if (current.version !== expectedVersion) {\n return refused('conflict');\n }\n return current;\n}\n\nfunction isJudged(value: OrderRecord | Judged): value is Judged {\n return 'result' in value;\n}\n\n/** A new order: `created`, version 1, no marker, an id not yet used. */\nexport function judgeAdd(records: readonly OrderRecord[], record: OrderRecord): Judged {\n if (record.state !== 'created' || record.version !== 1 || record.marker !== undefined) {\n throw new Error('A new order record starts as created, at version 1, with no marker');\n }\n if (records.some((existing) => existing.orderId === record.orderId)) {\n throw new Error('An order record with this id already exists');\n }\n return { result: { ok: true, record }, write: [record] };\n}\n\n/** Plain fields of the record the caller judged at `expectedVersion`. */\nexport function judgeUpdate(\n records: readonly OrderRecord[],\n orderId: string,\n expectedVersion: number,\n patch: RecordPatch,\n): Judged {\n const current = judgedRecord(records, orderId, expectedVersion);\n if (isJudged(current)) {\n return current;\n }\n // Only the patchable keys, and only those set: a key set to `undefined` would\n // wipe the field on spread, and any other key is not a plain update's to change.\n const defined: RecordPatch = {};\n for (const key of PATCH_KEYS) {\n if (patch[key] !== undefined) {\n Object.assign(defined, { [key]: patch[key] });\n }\n }\n const refusal = patchRefusal(current, defined);\n if (refusal !== undefined) {\n return refused(refusal);\n }\n return accepted({ ...current, ...defined, version: current.version + 1 });\n}\n\n/**\n * Test-and-set the payment marker immediately before the wallet call. Refused\n * unless the record is still the one judged, acknowledged (`ordered`), holds\n * its composed request and no marker - and no OTHER record for the product\n * holds a live payment (two tabs cannot both pay).\n */\nexport function judgeSetMarker(\n records: readonly OrderRecord[],\n orderId: string,\n expectedVersion: number,\n marker: PaymentMarker,\n): Judged {\n const current = judgedRecord(records, orderId, expectedVersion);\n if (isJudged(current)) {\n return current;\n }\n if (\n current.state !== 'ordered' ||\n current.marker !== undefined ||\n current.paymentRequest === undefined ||\n storeClosed(current) ||\n marker.rail !== railOf(current)\n ) {\n return refused('not_ready');\n }\n const holder = exclusionHolder(records, current);\n if (holder !== undefined) {\n return refused('exclusion', holder.orderId);\n }\n return accepted({ ...current, marker, state: 'paying', version: current.version + 1 });\n}\n\n/**\n * Change the marker of the attempt `attemptId` - record its signature or hash,\n * or replace it with a retry's marker (same record, order and reference). Both\n * the attempt and the record version must be the ones the caller judged: a\n * signature recorded in between is never overrun.\n */\nexport function judgeUpdateMarker(\n records: readonly OrderRecord[],\n orderId: string,\n expectedVersion: number,\n attemptId: string,\n next: PaymentMarker,\n): Judged {\n const current = records.find((record) => record.orderId === orderId);\n if (current === undefined) {\n return refused('missing');\n }\n if (\n current.version !== expectedVersion ||\n current.marker?.attemptId !== attemptId ||\n current.marker.rail !== next.rail\n ) {\n return refused('conflict');\n }\n if (current.state !== 'paying') {\n return refused('not_ready');\n }\n const retry = next.attemptId !== attemptId;\n // Tempo has no in-widget retry (an old prompt would pay too); within one\n // attempt, what the marker proves is never dropped or changed.\n // Within one attempt its pay window is fixed too: the expiry wait (Solana) and\n // the reconciliation floor (Tempo) are measured against what was stored.\n const windowMoved =\n current.marker.rail === 'solana' && next.rail === 'solana'\n ? next.blockhash !== current.marker.blockhash ||\n next.lastValidBlockHeight !== current.marker.lastValidBlockHeight ||\n next.slot !== current.marker.slot\n : current.marker.rail === 'tempo' &&\n next.rail === 'tempo' &&\n next.floorBlock !== current.marker.floorBlock;\n if (\n (retry && next.rail === 'tempo') ||\n (!retry && !keepsEvidence(current.marker, next)) ||\n (!retry && windowMoved)\n ) {\n return refused('not_ready');\n }\n // A retry is a new wallet request: never for an order the store cancelled,\n // and the product must still be free of any other order holding the\n // exclusion (one paid late meanwhile, say).\n if (retry && storeClosed(current)) {\n return refused('not_ready');\n }\n if (retry) {\n const holder = exclusionHolder(records, current);\n if (holder !== undefined) {\n return refused('exclusion', holder.orderId);\n }\n }\n return accepted({ ...current, marker: next, version: current.version + 1 });\n}\n\n/**\n * End the attempt `attemptId`, judged at `expectedVersion`: nothing was\n * requested (`ordered`, the marker is removed), or the attempt provably ended\n * (`ended-unpaid`, the marker is KEPT - it no longer excludes, but its floor,\n * signature or hash is what later reconciliation starts from).\n */\nexport function judgeClearMarker(\n records: readonly OrderRecord[],\n orderId: string,\n expectedVersion: number,\n attemptId: string,\n nextState: Extract<OrderState, 'ordered' | 'ended-unpaid'>,\n): Judged {\n const current = records.find((record) => record.orderId === orderId);\n if (current === undefined) {\n return refused('missing');\n }\n if (current.version !== expectedVersion || current.marker?.attemptId !== attemptId) {\n return refused('conflict');\n }\n if (current.state !== 'paying') {\n return refused('not_ready');\n }\n // An approved Tempo bundle may still land under a new hash: it never ends\n // unpaid on a deadline, it stays live until it is found.\n if (\n nextState === 'ended-unpaid' &&\n current.marker?.rail === 'tempo' &&\n current.marker.bundleId !== undefined\n ) {\n return refused('not_ready');\n }\n // \"Nothing was requested\" is false once the marker proves a request.\n if (nextState === 'ordered' && current.marker !== undefined && holdsEvidence(current.marker)) {\n return refused('not_ready');\n }\n if (nextState === 'ordered') {\n const { marker: _removed, ...rest } = current;\n return accepted({ ...rest, state: nextState, version: current.version + 1 });\n }\n return accepted({ ...current, state: nextState, version: current.version + 1 });\n}\n\n/**\n * After a delivery: pin the store's owner, and add every payout of the offer\n * that delivered to the known ones (pinning only the paid one would flag every\n * other rail the store lists as changed next time). A delivery under a\n * different owner than the pinned one never replaces the pin.\n */\nexport function mergePins(\n current: StorePinsRecord | undefined,\n storePubkey: string,\n ownerPubkey: string,\n payouts: readonly { caip19: string; address: string }[],\n): { write?: StorePinsRecord; result: StorePinsRecord } {\n if (current !== undefined && current.pinnedOwnerPubkey !== ownerPubkey) {\n return { result: current };\n }\n const known = [...(current?.knownPayouts ?? [])];\n for (const payout of payouts) {\n if (\n !known.some((entry) => entry.caip19 === payout.caip19 && entry.address === payout.address)\n ) {\n known.push({ caip19: payout.caip19, address: payout.address });\n }\n }\n const record: StorePinsRecord = {\n storePubkey,\n pinnedOwnerPubkey: ownerPubkey,\n knownPayouts: known,\n };\n return { write: record, result: record };\n}\n\n/**\n * The order records, over any `OrderBackend`. Every write that decides\n * something about money is judged inside the backend's transaction and\n * re-checks what the caller judged (the record version, the marker's attempt\n * id), so a stale tab, a second process or a late wallet answer can never\n * overrun a newer write.\n */\nexport class OrderStore {\n constructor(private readonly backend: OrderBackend) {}\n\n /** Add a new order: `created`, version 1, no marker. Anything else is refused. */\n async add(record: OrderRecord): Promise<void> {\n await this.backend.transactProduct(record.productAddress, (records) =>\n judgeAdd(records, record),\n );\n }\n\n get(orderId: string): Promise<OrderRecord | undefined> {\n return this.backend.read(orderId);\n }\n\n /** Every record for a product, oldest first. */\n async forProduct(productAddress: string): Promise<OrderRecord[]> {\n const records = await this.backend.forProduct(productAddress);\n return [...records].sort((left, right) => left.createdAt - right.createdAt);\n }\n\n /** Run a rule on the product of `orderId` (it never changes), in one transaction. */\n private async judge(\n orderId: string,\n rule: (records: readonly OrderRecord[]) => Judged,\n ): Promise<StoreWrite> {\n const known = await this.backend.read(orderId);\n if (known === undefined) {\n return { ok: false, reason: 'missing' };\n }\n return this.backend.transactProduct(known.productAddress, rule);\n }\n\n /** Change plain fields of the record the caller judged at `expectedVersion`. */\n update(orderId: string, expectedVersion: number, patch: RecordPatch): Promise<StoreWrite> {\n return this.judge(orderId, (records) => judgeUpdate(records, orderId, expectedVersion, patch));\n }\n\n /** See `judgeSetMarker`. */\n setMarker(orderId: string, expectedVersion: number, marker: PaymentMarker): Promise<StoreWrite> {\n return this.judge(orderId, (records) =>\n judgeSetMarker(records, orderId, expectedVersion, marker),\n );\n }\n\n /** See `judgeUpdateMarker`. */\n updateMarker(\n orderId: string,\n expectedVersion: number,\n attemptId: string,\n next: PaymentMarker,\n ): Promise<StoreWrite> {\n return this.judge(orderId, (records) =>\n judgeUpdateMarker(records, orderId, expectedVersion, attemptId, next),\n );\n }\n\n /** See `judgeClearMarker`. */\n clearMarker(\n orderId: string,\n expectedVersion: number,\n attemptId: string,\n nextState: Extract<OrderState, 'ordered' | 'ended-unpaid'>,\n ): Promise<StoreWrite> {\n return this.judge(orderId, (records) =>\n judgeClearMarker(records, orderId, expectedVersion, attemptId, nextState),\n );\n }\n\n pins(storePubkey: string): Promise<StorePinsRecord | undefined> {\n return this.backend.readPins(storePubkey);\n }\n\n /** See `mergePins`. */\n rememberDelivery(\n storePubkey: string,\n ownerPubkey: string,\n payouts: readonly { caip19: string; address: string }[],\n ): Promise<StorePinsRecord> {\n return this.backend.transactPins(storePubkey, (current) =>\n mergePins(current, storePubkey, ownerPubkey, payouts),\n );\n }\n}\n\n/**\n * An in-memory backend: for tests, and for a caller that keeps orders only for\n * the life of the process. Transactions on it are trivially atomic (one thread).\n */\nexport class MemoryOrderBackend implements OrderBackend {\n private readonly orders = new Map<string, OrderRecord>();\n private readonly stores = new Map<string, StorePinsRecord>();\n\n async read(orderId: string): Promise<OrderRecord | undefined> {\n return structuredClone(this.orders.get(orderId));\n }\n\n private snapshot(productAddress: string): OrderRecord[] {\n return [...this.orders.values()]\n .filter((record) => record.productAddress === productAddress)\n .map((record) => structuredClone(record));\n }\n\n async forProduct(productAddress: string): Promise<OrderRecord[]> {\n return this.snapshot(productAddress);\n }\n\n // Read, rule and write run with no await between them: no other call can interleave.\n async transactProduct<T>(\n productAddress: string,\n fn: (records: readonly OrderRecord[]) => { write?: readonly OrderRecord[]; result: T },\n ): Promise<T> {\n const { write, result } = fn(this.snapshot(productAddress));\n for (const record of write ?? []) {\n this.orders.set(record.orderId, structuredClone(record));\n }\n return result;\n }\n\n async readPins(storePubkey: string): Promise<StorePinsRecord | undefined> {\n return structuredClone(this.stores.get(storePubkey));\n }\n\n async transactPins<T>(\n storePubkey: string,\n fn: (pins: StorePinsRecord | undefined) => { write?: StorePinsRecord; result: T },\n ): Promise<T> {\n const { write, result } = fn(structuredClone(this.stores.get(storePubkey)));\n if (write !== undefined) {\n this.stores.set(storePubkey, structuredClone(write));\n }\n return result;\n }\n}\n","import {\n type Asset,\n type DirectInstruction,\n type Network,\n type PaymentRequestData,\n boundTransferAmount,\n buildPaymentInstructions,\n composeSolanaPaymentRequest,\n directInstructionsFromCompiledMessage,\n estimatePriorityFeeMicroLamports,\n estimateSolFeeLamports,\n getProtocolProgramId,\n parsePaymentRequest,\n verifyDirectSolanaPayment,\n} from '@elisym/pay-core';\nimport { TOKEN_PROGRAM_ADDRESS, findAssociatedTokenPda } from '@solana-program/token';\nimport {\n type Base64EncodedWireTransaction,\n type Signature,\n type Rpc,\n type SolanaRpcApi,\n address,\n appendTransactionMessageInstructions,\n compileTransaction,\n createNoopSigner,\n createTransactionMessage,\n getBase58Decoder,\n getBase64Decoder,\n getCompiledTransactionMessageDecoder,\n getPublicKeyFromAddress,\n getTransactionDecoder,\n getTransactionEncoder,\n isAddress,\n pipe,\n setTransactionMessageComputeUnitLimit,\n setTransactionMessageComputeUnitPrice,\n setTransactionMessageFeePayer,\n setTransactionMessageLifetimeUsingBlockhash,\n verifySignature,\n} from '@solana/kit';\nimport { isOfferPayout, parseCaip19 } from '../index';\nimport {\n MERCHANT_CATCH_UP_SECS,\n PAYMENT_SCAN_MARGIN_SECS,\n PAY_CUTOFF_SECS,\n SOLANA_COMPUTE_UNIT_LIMIT,\n STORE_WRITE_ATTEMPTS,\n} from './constants';\nimport { nowSecs } from './events';\nimport { type LoadedOffer, isSnapshotStale } from './offer';\nimport { type OrderDeps, sendReceipt } from './order-flow';\nimport { type OrderRecord, type PaymentMarker, isTerminal } from './order-record';\nimport type { OrderStore, StoreWrite } from './order-store';\n\ntype ReadyOffer = Extract<LoadedOffer, { ok: true }>;\ntype SolanaMarker = Extract<PaymentMarker, { rail: 'solana' }>;\n\nconst SYSTEM_PROGRAM = '11111111111111111111111111111111';\nconst COMPUTE_BUDGET_PROGRAM = 'ComputeBudget111111111111111111111111111111';\nconst SET_COMPUTE_UNIT_LIMIT = 2;\nconst SET_COMPUTE_UNIT_PRICE = 3;\nconst BASE_FEE_LAMPORTS = 5000n;\n/** One page of `getSignaturesForAddress` (the RPC's maximum) and at most this many pages. */\nconst SIGNATURE_PAGE_LIMIT = 1000;\nconst MAX_SIGNATURE_PAGES = 10;\n/**\n * Blocks past the last valid height before \"none\" is acted on: an RPC's address\n * index and transaction store are written after the bank, and a transaction that\n * landed in the last blocks of the lifetime must have time to show there.\n */\nconst EXPIRY_SETTLE_BLOCKS = 32n;\n/** System `AdvanceNonceAccount`: a durable-nonce transaction, which never expires. */\nconst ADVANCE_NONCE_DISCRIMINATOR = 4;\n/** Signatures under one reference the widget checks at most; past it the answer is \"unsure\". */\nconst MAX_REFERENCE_CANDIDATES = 100;\n/** Verdicts that say nothing final about a signature: ask again later. */\nconst UNSURE_VERDICTS = ['rpc_error', 'unreadable', 'not_found', 'bad_request'] as const;\n\n/**\n * A wallet account offering `solana:signTransaction`. The wallet signs the wire\n * transaction the widget built and returns it; the widget sends it itself.\n */\nexport interface SolanaWallet {\n address: string;\n signTransaction(transaction: Uint8Array): Promise<Uint8Array>;\n}\n\n/**\n * What one payment attempt may spend, as the caller's spend limits count it:\n * the coin's amount (for a token), and the SOL that leaves the payer's wallet\n * (the fee, the payee's token-account rent when missing, `increment_stats`'\n * rent on a new asset, and the amount itself for native SOL). The payer's own\n * rent floor is only kept, never spent, so it is not counted.\n */\nexport interface PaymentCosts {\n asset: Asset;\n /** Subunits of `asset` when it is a token; 0 for native SOL (counted in `lamports`). */\n tokenAmount: bigint;\n lamports: bigint;\n /**\n * The network fee inside `lamports`: the one part an attempt that never paid\n * may still have spent (a transaction that landed and failed).\n */\n feeLamports: bigint;\n}\n\nexport interface SolanaPayDeps extends OrderDeps {\n /** The widget's own Solana RPC. */\n rpc: Rpc<SolanaRpcApi>;\n /** The device clock (seconds); the receipt's date and the marker's `setAt`. */\n now?: () => number;\n newAttemptId?: () => string;\n /**\n * Whether `rpc` can prove an attempt over: a full-history endpoint whose\n * \"no payment\" can be trusted. Without it (`false`) the watch never answers\n * `over`, so nothing is retried or ended on an answer that could be wrong.\n * The widget always has one (true, the default).\n */\n canProveOver?: boolean;\n /**\n * Called once an attempt's costs are known and before its marker is written;\n * a throw refuses the payment with `spend_limit` before anything is recorded.\n */\n reserve?: (costs: PaymentCosts, attemptId: string) => void;\n /** Called when the attempt `attemptId` was refused after `reserve`, before any broadcast. */\n release?: (attemptId: string) => void;\n}\n\nexport interface PayInput {\n /** A FRESH verified offer (at most two minutes old): the payout and price are checked against it. */\n fresh: ReadyOffer;\n /** Chain time read just before (seconds). */\n chainTime: number;\n}\n\nexport type SolanaPayRefusal =\n /** The record cannot take a payment now (state, no request, the store closed it). */\n | 'not_payable'\n /** The offer snapshot is older than two minutes: verify again. */\n | 'stale_offer'\n /** The store no longer offers this payout at this price: end this order and start a new one. */\n | 'offer_changed'\n /** Too close to the end of the merchant's catch-up: a new order instead. */\n | 'too_late'\n /** The payer is the payout address itself (a transfer to oneself pays nothing). */\n | 'self_payment'\n | 'insufficient_token'\n | 'insufficient_sol'\n /** A chain read failed; nothing was requested. */\n | 'rpc_error'\n /** Another order for this product holds a live payment. */\n | 'exclusion'\n /** The record changed meanwhile; read it again. */\n | 'conflict'\n /** The wallet did not sign. The attempt stays live until its blockhash expires. */\n | 'wallet_failed'\n /** The wallet returned a transaction the widget does not send (below). Same wait. */\n | 'wallet_unsupported'\n /** A retry before the last attempt provably ended. */\n | 'still_waiting'\n | 'already_paid'\n /** The caller's spend limit refused the attempt's costs (`reserve` threw). Nothing was recorded. */\n | 'spend_limit';\n\nexport type SolanaPayResult =\n | { ok: true; record: OrderRecord; signature: string }\n | {\n ok: false;\n reason: SolanaPayRefusal;\n record?: OrderRecord;\n /** For `exclusion`: the order holding it. */\n holder?: string;\n /** For `insufficient_*`: what the payment needs and what the payer has, in subunits / lamports. */\n needed?: bigint;\n available?: bigint;\n /** For `wallet_unsupported`: what was wrong with the returned transaction. */\n detail?: SignedRefusal;\n };\n\n/** The request stored on the record, as the schema reads it. */\nexport function storedSolanaRequest(record: OrderRecord): PaymentRequestData | undefined {\n if (record.paymentRequest === undefined) {\n return undefined;\n }\n const parsed = parsePaymentRequest(record.paymentRequest);\n return parsed.ok ? parsed.data : undefined;\n}\n\nfunction solanaAssetOf(record: OrderRecord): { asset: Asset; network: Network } | undefined {\n const caip19 = parseCaip19(record.payout.caip19);\n if (caip19 === undefined || caip19.chain.family !== 'solana') {\n return undefined;\n }\n return { asset: caip19.asset, network: caip19.chain.network };\n}\n\n/**\n * Compose the order's payment request once, right after the order was\n * acknowledged, from the order's own snapshot; resume and every verdict use this\n * stored request, never a recomposed one.\n */\nexport async function composeOrderPayment(\n record: OrderRecord,\n store: OrderStore,\n): Promise<StoreWrite> {\n if (record.paymentRequest !== undefined) {\n return { ok: true, record };\n }\n const coin = solanaAssetOf(record);\n if (coin === undefined) {\n return { ok: false, reason: 'not_ready' };\n }\n let request: PaymentRequestData;\n try {\n request = composeSolanaPaymentRequest({\n recipient: record.payout.address,\n amount: BigInt(record.amount),\n asset: coin.asset,\n network: coin.network,\n reference: record.reference,\n createdAt: record.createdAt,\n });\n } catch {\n return { ok: false, reason: 'not_ready' };\n }\n const written = await store.update(record.orderId, record.version, {\n paymentRequest: JSON.stringify(request),\n });\n if (!written.ok && written.reason === 'conflict') {\n const current = await store.get(record.orderId);\n if (current?.paymentRequest !== undefined) {\n return { ok: true, record: current };\n }\n }\n return written;\n}\n\n/** What the payer holds and what the payment needs besides the fee itself. */\ninterface Funds {\n /** The payer's SOL, read before the marker. */\n lamports: bigint;\n /**\n * Everything but the transaction fee the payer's SOL must cover: the payee's\n * token-account rent when missing, `increment_stats`' rent on a new asset, the\n * payer's own rent floor, and the amount itself for native SOL.\n */\n otherLamports: bigint;\n /** The compute-unit price the widget asks (micro-lamports), for the payment's own accounts. */\n priceMicroLamports: bigint;\n /** What the attempt spends, for the caller's spend limits. */\n costs: PaymentCosts;\n}\n\ntype Checked =\n | { ok: true; request: PaymentRequestData; asset: Asset; network: Network; funds: Funds }\n | Extract<SolanaPayResult, { ok: false }>;\n\n/** The stored request pays what the record says: the payout, the reference, the coin. */\nfunction requestMatches(\n request: PaymentRequestData,\n record: OrderRecord,\n coin: { asset: Asset; network: Network },\n): boolean {\n return (\n request.recipient === record.payout.address &&\n request.reference === record.reference &&\n BigInt(request.amount) === BigInt(record.amount) &&\n (request.network ?? 'devnet') === coin.network &&\n request.asset?.mint === coin.asset.mint &&\n (request.fee_amount ?? 0) === 0 &&\n request.fee_address === undefined\n );\n}\n\n/**\n * Every check that runs BEFORE the marker: nothing was requested if one fails.\n * The fresh offer must still hold this payout at exactly the stored amount (a\n * higher price cannot be accepted, a lower one would overpay).\n */\nexport async function checkBeforePaying(\n record: OrderRecord,\n payer: string,\n input: PayInput,\n deps: Pick<SolanaPayDeps, 'rpc' | 'now'>,\n): Promise<Checked> {\n const request = storedSolanaRequest(record);\n const coin = solanaAssetOf(record);\n if (\n request === undefined ||\n coin === undefined ||\n !isAddress(payer) ||\n !requestMatches(request, record, coin)\n ) {\n return { ok: false, reason: 'not_payable', record };\n }\n if (isSnapshotStale(input.fresh.snapshotAt, (deps.now ?? nowSecs)())) {\n return { ok: false, reason: 'stale_offer', record };\n }\n const match = input.fresh.payouts.find(\n (payout) =>\n payout.target.caip19.id === record.payout.caip19 &&\n payout.target.address === record.payout.address,\n );\n if (\n input.fresh.productAddress !== record.productAddress ||\n !isOfferPayout(input.fresh.offer, record.payout.caip19, record.payout.address) ||\n match === undefined ||\n match.amount !== BigInt(record.amount)\n ) {\n return { ok: false, reason: 'offer_changed', record };\n }\n if (input.chainTime > record.createdAt + MERCHANT_CATCH_UP_SECS - PAY_CUTOFF_SECS) {\n return { ok: false, reason: 'too_late', record };\n }\n if (payer === record.payout.address) {\n return { ok: false, reason: 'self_payment', record };\n }\n const funds = await checkFunds(deps.rpc, request, payer, coin);\n if (!funds.ok) {\n return { ...funds, record };\n }\n return { ok: true, request, asset: coin.asset, network: coin.network, funds: funds.funds };\n}\n\n/** The payer's and the payee's accounts of the asset: what the payment write-locks. */\nasync function assetAccounts(\n payer: string,\n recipient: string,\n asset: Asset,\n): Promise<{ payer: string; payee: string }> {\n if (asset.mint === undefined) {\n return { payer, payee: recipient };\n }\n const tokenProgram = address(asset.tokenProgram ?? TOKEN_PROGRAM_ADDRESS);\n const mint = address(asset.mint);\n const [payerAccount] = await findAssociatedTokenPda({\n owner: address(payer),\n mint,\n tokenProgram,\n });\n const [payeeAccount] = await findAssociatedTokenPda({\n owner: address(recipient),\n mint,\n tokenProgram,\n });\n return { payer: payerAccount, payee: payeeAccount };\n}\n\n/** The payer's balance of the asset's token, 0 when it holds no token account. */\nasync function tokenBalance(rpc: Rpc<SolanaRpcApi>, account: string): Promise<bigint> {\n const info = await rpc\n .getAccountInfo(address(account), { commitment: 'confirmed', encoding: 'base64' })\n .send();\n if (info.value === null) {\n return 0n;\n }\n const balance = await rpc\n .getTokenAccountBalance(address(account), { commitment: 'confirmed' })\n .send();\n return BigInt(balance.value.amount);\n}\n\n/**\n * Whether the payer can pay: the asset for the amount, and SOL for the fees, for\n * creating the payee's token account when it is missing, and for its own rent\n * floor. Refused before the wallet opens - the widget says what is short. The\n * compute-unit price is read for the payment's own accounts (a price over no\n * accounts is the chain-wide floor, which a busy block leaves behind).\n */\nasync function checkFunds(\n rpc: Rpc<SolanaRpcApi>,\n request: PaymentRequestData,\n payer: string,\n coin: { asset: Asset; network: Network },\n): Promise<{ ok: true; funds: Funds } | Extract<SolanaPayResult, { ok: false }>> {\n try {\n const amount = BigInt(request.amount);\n const accounts = await assetAccounts(payer, request.recipient, coin.asset);\n const priceMicroLamports = await estimatePriorityFeeMicroLamports(rpc, {\n network: coin.network,\n accounts: [address(accounts.payer), address(accounts.payee)],\n });\n const fees = await estimateSolFeeLamports(rpc, request, payer, coin.network, {\n computeUnitLimit: SOLANA_COMPUTE_UNIT_LIMIT,\n priorityFeeMicroLamports: priceMicroLamports,\n });\n const rentFloor = await rpc.getMinimumBalanceForRentExemption(0n).send();\n const lamports = (await rpc.getBalance(address(payer), { commitment: 'confirmed' }).send())\n .value;\n const otherLamports =\n fees.rentLamports +\n fees.assetStatsRentLamports +\n rentFloor +\n (coin.asset.mint === undefined ? amount : 0n);\n const feeLamports = fees.baseFeeLamports + fees.priorityFeeLamports;\n if (coin.asset.mint !== undefined) {\n const tokens = await tokenBalance(rpc, accounts.payer);\n if (tokens < amount) {\n return { ok: false, reason: 'insufficient_token', needed: amount, available: tokens };\n }\n }\n if (lamports < otherLamports + feeLamports) {\n return {\n ok: false,\n reason: 'insufficient_sol',\n needed: otherLamports + feeLamports,\n available: lamports,\n };\n }\n const costs: PaymentCosts = {\n asset: coin.asset,\n tokenAmount: coin.asset.mint === undefined ? 0n : amount,\n lamports:\n fees.rentLamports +\n fees.assetStatsRentLamports +\n feeLamports +\n (coin.asset.mint === undefined ? amount : 0n),\n feeLamports,\n };\n return { ok: true, funds: { lamports, otherLamports, priceMicroLamports, costs } };\n } catch {\n return { ok: false, reason: 'rpc_error' };\n }\n}\n\ninterface Unsigned {\n bytes: Uint8Array;\n blockhash: string;\n lastValidBlockHeight: bigint;\n /** The slot the blockhash was read at. */\n slot: bigint;\n}\n\n/**\n * The payment transaction, unsigned: pay-core's instructions (the bound transfer\n * and `increment_stats`), the widget's own blockhash, a compute limit and price.\n * The blockhash and its last valid height are the attempt's lifetime.\n */\nasync function unsignedPayment(\n rpc: Rpc<SolanaRpcApi>,\n checked: Extract<Checked, { ok: true }>,\n payer: string,\n): Promise<Unsigned> {\n const payerAddress = address(payer);\n const instructions = await buildPaymentInstructions(\n checked.request,\n createNoopSigner(payerAddress),\n { programId: getProtocolProgramId(checked.network) },\n );\n const { context, value: latest } = await rpc\n .getLatestBlockhash({ commitment: 'confirmed' })\n .send();\n const message = pipe(\n createTransactionMessage({ version: 0 }),\n (draft) => setTransactionMessageFeePayer(payerAddress, draft),\n (draft) => setTransactionMessageLifetimeUsingBlockhash(latest, draft),\n (draft) => setTransactionMessageComputeUnitLimit(SOLANA_COMPUTE_UNIT_LIMIT, draft),\n (draft) => setTransactionMessageComputeUnitPrice(checked.funds.priceMicroLamports, draft),\n (draft) =>\n appendTransactionMessageInstructions(\n // pay-core types its instructions loosely; the same cast its own builder uses.\n instructions as Parameters<typeof appendTransactionMessageInstructions>[0],\n draft,\n ),\n );\n return {\n bytes: new Uint8Array(getTransactionEncoder().encode(compileTransaction(message))),\n blockhash: latest.blockhash,\n lastValidBlockHeight: latest.lastValidBlockHeight,\n slot: BigInt(context.slot),\n };\n}\n\nexport type SignedRefusal =\n /** Not a transaction the widget can read. */\n | 'unreadable'\n /** Another blockhash, or a durable nonce (no expiry at all). */\n | 'lifetime_changed'\n /** Another fee payer than the wallet account. */\n | 'wrong_payer'\n /** A signature is missing or does not verify. */\n | 'unsigned'\n /** The bound transfer is gone or pays another amount. */\n | 'not_bound'\n /** A compute-budget setting twice: the runtime refuses the whole transaction. */\n | 'duplicate_compute_budget';\n\n/**\n * The fee the transaction pays, from its own compute-budget instructions: the\n * signatures' base fee plus limit × price. Without a limit the runtime grants\n * 200 000 units per other instruction (at most 1.4 M). `undefined` when a\n * setting appears twice.\n */\nfunction transactionFee(instructions: readonly DirectInstruction[], signatures: number) {\n let limit: bigint | undefined;\n let price = 0n;\n let limits = 0;\n let prices = 0;\n let others = 0;\n for (const instruction of instructions) {\n if (instruction.program !== COMPUTE_BUDGET_PROGRAM) {\n others += 1;\n continue;\n }\n const view = new DataView(\n instruction.data.buffer,\n instruction.data.byteOffset,\n instruction.data.byteLength,\n );\n if (instruction.data[0] === SET_COMPUTE_UNIT_LIMIT && instruction.data.length === 5) {\n limits += 1;\n limit = BigInt(view.getUint32(1, true));\n } else if (instruction.data[0] === SET_COMPUTE_UNIT_PRICE && instruction.data.length === 9) {\n prices += 1;\n price = view.getBigUint64(1, true);\n }\n }\n if (limits > 1 || prices > 1) {\n return undefined;\n }\n const units = limit ?? BigInt(Math.min(others * 200_000, 1_400_000));\n return BASE_FEE_LAMPORTS * BigInt(signatures) + (price * units + 999_999n) / 1_000_000n;\n}\n\n/**\n * What the widget sends of a transaction the wallet returned: only one whose\n * lifetime is exactly the attempt's blockhash (no durable nonce), paid by the\n * wallet account, fully signed, with each compute-budget setting at most once,\n * and whose bound transfer still pays exactly the stored amount - the same\n * binding the merchant and \"found\" judge. It also returns the fee the\n * transaction pays: a wallet may raise the price the widget set.\n */\nexport async function checkSignedTransaction(\n bytes: Uint8Array,\n expected: { payer: string; blockhash: string; request: PaymentRequestData; asset: Asset },\n): Promise<\n | { ok: true; signature: string; wire: string; feeLamports: bigint }\n | { ok: false; reason: SignedRefusal }\n> {\n let transaction: ReturnType<ReturnType<typeof getTransactionDecoder>['decode']>;\n let message: ReturnType<ReturnType<typeof getCompiledTransactionMessageDecoder>['decode']>;\n let instructions: DirectInstruction[];\n try {\n transaction = getTransactionDecoder().decode(bytes);\n message = getCompiledTransactionMessageDecoder().decode(transaction.messageBytes);\n instructions = directInstructionsFromCompiledMessage(message);\n } catch {\n return { ok: false, reason: 'unreadable' };\n }\n const first = instructions[0];\n const durableNonce =\n first !== undefined &&\n first.program === SYSTEM_PROGRAM &&\n first.data.length >= 4 &&\n new DataView(first.data.buffer, first.data.byteOffset, 4).getUint32(0, true) ===\n ADVANCE_NONCE_DISCRIMINATOR;\n if (message.lifetimeToken !== expected.blockhash || durableNonce) {\n return { ok: false, reason: 'lifetime_changed' };\n }\n if (String(message.staticAccounts[0]) !== expected.payer) {\n return { ok: false, reason: 'wrong_payer' };\n }\n const signatures = Object.entries(transaction.signatures);\n if (signatures.length === 0) {\n return { ok: false, reason: 'unsigned' };\n }\n for (const [signer, signature] of signatures) {\n let valid = false;\n try {\n valid =\n signature !== null &&\n (await verifySignature(\n await getPublicKeyFromAddress(address(signer)),\n signature,\n transaction.messageBytes,\n ));\n } catch {\n // An address that is no key (a PDA added as a signer) cannot have signed.\n valid = false;\n }\n if (!valid) {\n return { ok: false, reason: 'unsigned' };\n }\n }\n const payerSignature = transaction.signatures[address(expected.payer)] ?? null;\n const feeLamports = transactionFee(instructions, signatures.length);\n if (feeLamports === undefined) {\n return { ok: false, reason: 'duplicate_compute_budget' };\n }\n const bound = await boundTransferAmount(instructions, {\n reference: expected.request.reference,\n recipient: expected.request.recipient,\n asset: expected.asset,\n });\n if (payerSignature === null || bound !== BigInt(expected.request.amount)) {\n return { ok: false, reason: payerSignature === null ? 'unsigned' : 'not_bound' };\n }\n return {\n ok: true,\n signature: getBase58Decoder().decode(payerSignature),\n wire: getBase64Decoder().decode(bytes),\n feeLamports,\n };\n}\n\n/** Send the signed bytes; a failure here is judged by the chain later, never by this call. */\nasync function broadcast(rpc: Rpc<SolanaRpcApi>, wire: string): Promise<void> {\n try {\n await rpc\n .sendTransaction(wire as Base64EncodedWireTransaction, {\n encoding: 'base64',\n skipPreflight: true,\n })\n .send();\n } catch {\n // Rebroadcast while waiting; the reference pass decides.\n }\n}\n\n/**\n * Ask the wallet to sign the attempt `marker` (already set), check what it\n * returned, record the signature and the bytes BEFORE the first broadcast, send,\n * and send the receipt. Any failure leaves the marker: Wallet Standard has no\n * proving rejection, so the attempt stays live until its blockhash expires.\n */\nasync function signAndSend(\n record: OrderRecord,\n marker: SolanaMarker,\n unsigned: Unsigned,\n wallet: SolanaWallet,\n checked: Extract<Checked, { ok: true }>,\n deps: SolanaPayDeps,\n): Promise<SolanaPayResult> {\n let signedBytes: Uint8Array;\n try {\n signedBytes = await wallet.signTransaction(unsigned.bytes);\n } catch {\n return { ok: false, reason: 'wallet_failed', record };\n }\n const signed = await checkSignedTransaction(signedBytes, {\n payer: wallet.address,\n blockhash: unsigned.blockhash,\n request: checked.request,\n asset: checked.asset,\n });\n if (!signed.ok) {\n return { ok: false, reason: 'wallet_unsupported', record, detail: signed.reason };\n }\n // A wallet may raise the price the widget set: a payer who cannot cover the fee\n // it signed would send a transaction that never lands.\n const needed = checked.funds.otherLamports + signed.feeLamports;\n if (checked.funds.lamports < needed) {\n deps.release?.(marker.attemptId);\n return {\n ok: false,\n reason: 'insufficient_sol',\n record,\n needed,\n available: checked.funds.lamports,\n };\n }\n // The wallet may take long: the attempt id, not the version the caller saw, is\n // what must still hold. A failed write means no broadcast.\n let current: OrderRecord | undefined = record;\n for (let attempt = 0; attempt < STORE_WRITE_ATTEMPTS && current !== undefined; attempt += 1) {\n if (current.marker?.attemptId !== marker.attemptId) {\n deps.release?.(marker.attemptId);\n return { ok: false, reason: 'conflict', record: current };\n }\n const written = await deps.store.updateMarker(\n current.orderId,\n current.version,\n marker.attemptId,\n { ...marker, signature: signed.signature, signedTransaction: signed.wire },\n );\n if (written.ok) {\n await broadcast(deps.rpc, signed.wire);\n const receipt = await sendReceipt(\n written.record,\n signed.signature,\n (deps.now ?? nowSecs)(),\n deps,\n );\n return {\n ok: true,\n record: receipt.ok ? receipt.record : written.record,\n signature: signed.signature,\n };\n }\n if (written.reason !== 'conflict') {\n deps.release?.(marker.attemptId);\n return { ok: false, reason: 'conflict', record: current };\n }\n current = await deps.store.get(record.orderId);\n }\n deps.release?.(marker.attemptId);\n return { ok: false, reason: 'conflict', ...(current === undefined ? {} : { record: current }) };\n}\n\nfunction storeRefusal(\n written: Extract<StoreWrite, { ok: false }>,\n record: OrderRecord,\n): SolanaPayResult {\n if (written.reason === 'exclusion') {\n return {\n ok: false,\n reason: 'exclusion',\n record,\n ...(written.holder === undefined ? {} : { holder: written.holder }),\n };\n }\n return { ok: false, reason: written.reason === 'conflict' ? 'conflict' : 'not_payable', record };\n}\n\n/**\n * Run the write that records a new attempt; a throw gives the attempt's\n * reservation back (nothing was signed or sent on it) and is rethrown.\n */\nasync function withReleaseOnThrow<T>(\n attemptId: string,\n deps: SolanaPayDeps,\n write: () => Promise<T>,\n): Promise<T> {\n try {\n return await write();\n } catch (error) {\n deps.release?.(attemptId);\n throw error;\n }\n}\n\n/** Ask the caller's spend limits for the attempt's costs; `false` when refused. */\nfunction reserveCosts(costs: PaymentCosts, attemptId: string, deps: SolanaPayDeps): boolean {\n if (deps.reserve === undefined) {\n return true;\n }\n try {\n deps.reserve(costs, attemptId);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction newMarker(unsigned: Unsigned, deps: SolanaPayDeps): SolanaMarker {\n return {\n rail: 'solana',\n attemptId: (deps.newAttemptId ?? (() => crypto.randomUUID()))(),\n setAt: (deps.now ?? nowSecs)(),\n blockhash: unsigned.blockhash,\n lastValidBlockHeight: unsigned.lastValidBlockHeight.toString(),\n slot: unsigned.slot.toString(),\n };\n}\n\n/**\n * The first payment of an acknowledged order: checks, the transaction, then the\n * marker (test-and-set with the product's other orders) and only then the wallet.\n */\nexport async function payWithSolana(\n record: OrderRecord,\n wallet: SolanaWallet,\n input: PayInput,\n deps: SolanaPayDeps,\n): Promise<SolanaPayResult> {\n if (record.state !== 'ordered' || record.marker !== undefined) {\n return { ok: false, reason: 'not_payable', record };\n }\n const checked = await checkBeforePaying(record, wallet.address, input, deps);\n if (!checked.ok) {\n return checked;\n }\n let unsigned: Unsigned;\n try {\n unsigned = await unsignedPayment(deps.rpc, checked, wallet.address);\n } catch {\n return { ok: false, reason: 'rpc_error', record };\n }\n const marker = newMarker(unsigned, deps);\n if (!reserveCosts(checked.funds.costs, marker.attemptId, deps)) {\n return { ok: false, reason: 'spend_limit', record };\n }\n const marked = await withReleaseOnThrow(marker.attemptId, deps, () =>\n deps.store.setMarker(record.orderId, record.version, marker),\n );\n if (!marked.ok) {\n deps.release?.(marker.attemptId);\n return storeRefusal(marked, record);\n }\n return signAndSend(marked.record, marker, unsigned, wallet, checked, deps);\n}\n\nexport type SolanaWatch =\n /** The payment was found and recorded. */\n | { state: 'paid'; record: OrderRecord }\n /** The attempt may still land, or the chain could not be read in full: keep watching. */\n | { state: 'waiting'; record: OrderRecord }\n /** The attempt's blockhash expired at `finalized` and a full pass found no payment. */\n | { state: 'over'; record: OrderRecord }\n /**\n * The store delivered or refunded (a terminal record): its answer stands and\n * nothing is left to watch. Says nothing about which transaction paid.\n */\n | { state: 'closed'; record: OrderRecord };\n\ntype Search = { found: string } | 'none' | 'unsure';\n\n/**\n * Every signature under the reference, newest first, paged until one is older\n * than `notBefore` - pay-core's walk, with `minContextSlot`: a load-balanced RPC\n * may answer from a node behind the one that reported the blockhash expired, and\n * such a node must refuse (unsure) rather than list without the payment.\n */\nasync function listReference(\n rpc: Rpc<SolanaRpcApi>,\n reference: string,\n notBefore: number,\n minContextSlot: bigint | undefined,\n): Promise<{ signatures: { signature: string; failed: boolean }[]; complete: boolean }> {\n const signatures: { signature: string; failed: boolean }[] = [];\n let before: Signature | undefined;\n for (let page = 0; page < MAX_SIGNATURE_PAGES; page += 1) {\n const rows = await rpc\n .getSignaturesForAddress(address(reference), {\n limit: SIGNATURE_PAGE_LIMIT,\n commitment: 'confirmed',\n ...(minContextSlot === undefined ? {} : { minContextSlot }),\n ...(before === undefined ? {} : { before }),\n })\n .send();\n let reachedFloor = false;\n for (const row of rows) {\n signatures.push({ signature: row.signature, failed: row.err !== null });\n if (row.blockTime !== null && Number(row.blockTime) < notBefore) {\n reachedFloor = true;\n }\n }\n const last = rows[rows.length - 1];\n if (reachedFloor || rows.length < SIGNATURE_PAGE_LIMIT || last === undefined) {\n return { signatures, complete: true };\n }\n before = last.signature;\n }\n return { signatures, complete: false };\n}\n\n/**\n * Look for a payment of this order: the attempt's own signature, then every\n * signature under the reference. A failed transaction is not a payment;\n * anything unreadable makes the answer \"unsure\", never \"none\". The caller acts\n * on \"none\" only with `minContextSlot` (the finalized slot that proved the\n * blockhash expired): the listing is then complete up to that slot, so a\n * signature it does not hold, which the node does not serve either, never landed.\n */\nasync function searchPayment(\n record: OrderRecord,\n request: PaymentRequestData,\n rpc: Rpc<SolanaRpcApi>,\n minContextSlot: bigint | undefined,\n): Promise<Search> {\n const own = record.marker?.rail === 'solana' ? record.marker.signature : undefined;\n const candidates: string[] = own === undefined ? [] : [own];\n const listed = new Set<string>();\n let unsure = false;\n try {\n const listing = await listReference(\n rpc,\n request.reference,\n record.createdAt - PAYMENT_SCAN_MARGIN_SECS,\n minContextSlot,\n );\n unsure = !listing.complete;\n for (const entry of listing.signatures) {\n listed.add(entry.signature);\n if (!entry.failed && !candidates.includes(entry.signature)) {\n candidates.push(entry.signature);\n }\n }\n } catch {\n unsure = true;\n }\n if (candidates.length > MAX_REFERENCE_CANDIDATES) {\n unsure = true;\n }\n for (const signature of candidates.slice(0, MAX_REFERENCE_CANDIDATES)) {\n let verdict: Awaited<ReturnType<typeof verifyDirectSolanaPayment>>;\n try {\n verdict = await verifyDirectSolanaPayment(rpc, request, signature);\n } catch {\n // A signature the node listed that cannot even be read: never proof of \"none\".\n unsure = true;\n continue;\n }\n if (verdict.verified) {\n return { found: signature };\n }\n if (!(UNSURE_VERDICTS as readonly string[]).includes(verdict.reason)) {\n continue;\n }\n // Not served and not listed: it has not landed - for the attempt's own\n // signature only once its status is unknown too, from the bank's recent\n // statuses and from history (an address index may lag the slot the node is at).\n // Only \"none\" after expiry is acted on, and that listing reads at least as far\n // as the expiry slot.\n if (\n verdict.reason === 'not_found' &&\n !listed.has(signature) &&\n (signature !== own ||\n minContextSlot === undefined ||\n !(await statusKnown(rpc, signature, minContextSlot)))\n ) {\n continue;\n }\n unsure = true;\n }\n return unsure ? 'unsure' : 'none';\n}\n\n/**\n * Whether the signature's status is known, with history: known when found, and\n * also when the answering node is behind `minContextSlot` (a load-balanced RPC\n * may send this read elsewhere) or the read fails - neither proves anything.\n */\nasync function statusKnown(\n rpc: Rpc<SolanaRpcApi>,\n signature: string,\n minContextSlot: bigint,\n): Promise<boolean> {\n try {\n const statuses = await rpc\n .getSignatureStatuses([signature as Signature], { searchTransactionHistory: true })\n .send();\n const status = statuses.value[0];\n return (\n BigInt(statuses.context.slot) < minContextSlot || (status !== null && status !== undefined)\n );\n } catch {\n return true;\n }\n}\n\n/**\n * Record the payment found, with a receipt naming it unless one already went\n * out for it: the attempt's own receipt may have been lost (the tab closed\n * after the broadcast), and a payment that is not the attempt's own (another\n * device) needs its own - while the record still takes one.\n */\nasync function recordPaid(\n record: OrderRecord,\n signature: string,\n deps: SolanaPayDeps,\n): Promise<OrderRecord> {\n let current: OrderRecord | undefined = record;\n const own = record.marker?.rail === 'solana' ? record.marker.signature : undefined;\n if (current.receiptWrap === undefined || (current.state === 'paying' && own !== signature)) {\n const receipt = await sendReceipt(current, signature, (deps.now ?? nowSecs)(), deps);\n if (receipt.ok) {\n current = receipt.record;\n }\n }\n for (let attempt = 0; attempt < STORE_WRITE_ATTEMPTS && current !== undefined; attempt += 1) {\n if (current.paidTx !== undefined) {\n return current;\n }\n const written = await deps.store.update(current.orderId, current.version, {\n state: 'paid',\n paidTx: signature,\n });\n if (written.ok) {\n return written.record;\n }\n if (written.reason !== 'conflict') {\n return current;\n }\n current = await deps.store.get(record.orderId);\n }\n return current ?? record;\n}\n\n/**\n * Whether the RPC's history reaches back to the attempt's slot (unknown counts as\n * no). `getFirstAvailableBlock` covers a node's long-term storage too, where\n * `minimumLedgerSlot` would name only its local ledger.\n */\nasync function ledgerReaches(rpc: Rpc<SolanaRpcApi>, slot: string | undefined): Promise<boolean> {\n if (slot === undefined) {\n return false;\n }\n try {\n return BigInt(await rpc.getFirstAvailableBlock().send()) <= BigInt(slot);\n } catch {\n return false;\n }\n}\n\n/**\n * One reconciliation step for a record with a Solana attempt: found -> paid;\n * otherwise the signed bytes are sent again while the blockhash can land, and\n * once it expired at `finalized` - read BEFORE the pass, together with its slot\n * (the pass reads at least that far), so a pass that finds nothing proves it -\n * a complete pass that finds nothing ends the attempt.\n */\nexport async function watchSolanaPayment(\n record: OrderRecord,\n deps: SolanaPayDeps,\n): Promise<SolanaWatch> {\n // Delivered or refunded: the store has answered, nothing is left to watch (the\n // delivery can arrive before the widget itself found the payment).\n if (isTerminal(record)) {\n return { state: 'closed', record };\n }\n if (record.paidTx !== undefined) {\n // A receipt lost before the payment was recorded is sent now.\n if (record.receiptWrap === undefined) {\n const receipt = await sendReceipt(record, record.paidTx, (deps.now ?? nowSecs)(), deps);\n return { state: 'paid', record: receipt.ok ? receipt.record : record };\n }\n return { state: 'paid', record };\n }\n const marker = record.marker;\n const request = storedSolanaRequest(record);\n if (marker?.rail !== 'solana' || request === undefined) {\n return { state: 'waiting', record };\n }\n let expired = false;\n // The finalized slot that proved the expiry, once the index had time to catch up.\n let settledAt: bigint | undefined;\n try {\n const epoch = await deps.rpc.getEpochInfo({ commitment: 'finalized' }).send();\n const lastValid = BigInt(marker.lastValidBlockHeight);\n expired = BigInt(epoch.blockHeight) > lastValid;\n if (BigInt(epoch.blockHeight) > lastValid + EXPIRY_SETTLE_BLOCKS) {\n settledAt = BigInt(epoch.absoluteSlot);\n }\n } catch {\n expired = false;\n }\n // An RPC whose ledger starts above the attempt cannot show it: never \"none\" from it.\n if (settledAt !== undefined && !(await ledgerReaches(deps.rpc, marker.slot))) {\n settledAt = undefined;\n }\n const search = await searchPayment(record, request, deps.rpc, settledAt);\n if (search !== 'none' && search !== 'unsure') {\n return { state: 'paid', record: await recordPaid(record, search.found, deps) };\n }\n if (!expired) {\n if (marker.signedTransaction !== undefined) {\n await broadcast(deps.rpc, marker.signedTransaction);\n }\n return { state: 'waiting', record };\n }\n // Only a caller whose RPC can prove it (full history) ever acts on \"none\".\n return search === 'none' && settledAt !== undefined && deps.canProveOver !== false\n ? { state: 'over', record }\n : { state: 'waiting', record };\n}\n\n/**\n * A new attempt for the same order, reference and request, once the last one\n * provably ended: the pass runs here, and the marker is replaced only at the\n * version it judged (a payment found meanwhile is never overrun).\n */\nexport async function retryWithSolana(\n record: OrderRecord,\n wallet: SolanaWallet,\n input: PayInput,\n deps: SolanaPayDeps,\n): Promise<SolanaPayResult> {\n if (record.state !== 'paying' || record.marker?.rail !== 'solana') {\n return { ok: false, reason: 'not_payable', record };\n }\n const watch = await watchSolanaPayment(record, deps);\n if (watch.state !== 'over') {\n const reasons = {\n paid: 'already_paid',\n waiting: 'still_waiting',\n closed: 'not_payable',\n } as const;\n return { ok: false, reason: reasons[watch.state], record: watch.record };\n }\n const judged = watch.record;\n const previous = judged.marker;\n if (previous === undefined) {\n return { ok: false, reason: 'not_payable', record: judged };\n }\n const checked = await checkBeforePaying(judged, wallet.address, input, deps);\n if (!checked.ok) {\n return checked;\n }\n let unsigned: Unsigned;\n try {\n unsigned = await unsignedPayment(deps.rpc, checked, wallet.address);\n } catch {\n return { ok: false, reason: 'rpc_error', record: judged };\n }\n const marker = newMarker(unsigned, deps);\n if (!reserveCosts(checked.funds.costs, marker.attemptId, deps)) {\n return { ok: false, reason: 'spend_limit', record: judged };\n }\n const replaced = await withReleaseOnThrow(marker.attemptId, deps, () =>\n deps.store.updateMarker(judged.orderId, judged.version, previous.attemptId, marker),\n );\n if (!replaced.ok) {\n deps.release?.(marker.attemptId);\n return storeRefusal(replaced, judged);\n }\n return signAndSend(replaced.record, marker, unsigned, wallet, checked, deps);\n}\n\n/**\n * End an order that will not be paid (the offer changed, the buyer starts over):\n * at once when nothing was requested; with an attempt, only once it provably\n * ended. `ended-unpaid` keeps the marker for later reconciliation.\n */\nexport async function endSolanaOrder(\n record: OrderRecord,\n deps: SolanaPayDeps,\n): Promise<{ ended: boolean; record: OrderRecord }> {\n if (record.state === 'ordered' && record.marker === undefined) {\n const written = await deps.store.update(record.orderId, record.version, {\n state: 'ended-unpaid',\n });\n return written.ok ? { ended: true, record: written.record } : { ended: false, record };\n }\n if (record.state !== 'paying' || record.marker === undefined) {\n return { ended: false, record };\n }\n const watch = await watchSolanaPayment(record, deps);\n if (watch.state !== 'over' || watch.record.marker === undefined) {\n return { ended: false, record: watch.record };\n }\n const written = await deps.store.clearMarker(\n watch.record.orderId,\n watch.record.version,\n watch.record.marker.attemptId,\n 'ended-unpaid',\n );\n return written.ok\n ? { ended: true, record: written.record }\n : { ended: false, record: watch.record };\n}\n","import type { PricedPayout } from './offer';\nimport type { OrderRecord } from './order-record';\nimport type { OrderStore } from './order-store';\nimport { type SolanaPayDeps, endSolanaOrder } from './solana-pay';\n\n/**\n * Decisions a purchase makes about the records it holds, shared by the widget's\n * session and the MCP's tools. Each caller sequences them with its own screens\n * or answers; the rules are the same.\n */\n\n/** The store cancelled an order no payment is known for (the attempt, if any, is over). */\nexport function cancelledUnpaid(record: OrderRecord): boolean {\n return (\n record.status?.status === 'cancelled' &&\n record.paidTx === undefined &&\n (record.state === 'created' || record.state === 'ordered')\n );\n}\n\n/** Ended with no payment found (by this caller or another): no longer this product's purchase. */\nexport function gone(record: OrderRecord): boolean {\n return record.state === 'ended-unpaid' && record.paidTx === undefined;\n}\n\n/**\n * Whether `record` can still be paid on `payout`: an order is placed for one\n * payout and price, so an order on other terms, or one the store cancelled\n * while unpaid, must end before a new one is placed.\n */\nexport function onOtherTerms(record: OrderRecord, payout: PricedPayout): boolean {\n return (\n cancelledUnpaid(record) ||\n record.payout.caip19 !== payout.target.caip19.id ||\n record.payout.address !== payout.target.address ||\n record.amount !== payout.amount.toString()\n );\n}\n\nexport type EndDeps = Pick<\n SolanaPayDeps,\n 'store' | 'readClient' | 'clientFor' | 'now' | 'canProveOver'\n> & {\n /** The order's own network's RPC, or `undefined` when the caller has none for it. */\n rpc: SolanaPayDeps['rpc'] | undefined;\n store: OrderStore;\n};\n\n/**\n * End an order that will not be paid, before a new one is placed beside it:\n * - a `created` order was never acknowledged and holds nothing: it counts as\n * ended at once (it is never moved; `created` only becomes `ordered`);\n * - an acknowledged order with no attempt ends through the store alone;\n * - an order with an attempt ends only once the attempt provably ended, which\n * needs the order's own RPC and `canProveOver` (see `endSolanaOrder`).\n * `ended: false` means an attempt may still land: follow it, never place a\n * second order beside it.\n */\nexport async function endOrder(\n record: OrderRecord,\n deps: EndDeps,\n): Promise<{ ended: boolean; record: OrderRecord }> {\n if (record.state === 'created') {\n return { ended: true, record };\n }\n if (deps.rpc !== undefined) {\n return await endSolanaOrder(record, { ...deps, rpc: deps.rpc });\n }\n if (record.state === 'ordered' && record.marker === undefined) {\n const written = await deps.store.update(record.orderId, record.version, {\n state: 'ended-unpaid',\n });\n return written.ok ? { ended: true, record: written.record } : { ended: false, record };\n }\n return { ended: false, record };\n}\n","import type { EventTemplate, Filter, NostrEvent, VerifiedEvent } from 'nostr-tools';\nimport { SimplePool } from 'nostr-tools/pool';\nimport { normalizeURL } from 'nostr-tools/utils';\nimport {\n SUBSCRIBE_RETRY_MAX_MS,\n SUBSCRIBE_RETRY_MS,\n SUBSCRIBE_STABLE_MS,\n RELAY_CONNECT_MAX_WAIT_MS,\n RELAY_PUBLISH_DEADLINE_MS,\n RELAY_QUERY_DEADLINE_MS,\n RELAY_QUERY_MAX_WAIT_MS,\n} from './constants';\nimport { isGenuineEvent } from './events';\n\n/** Signs a NIP-42 AUTH event with the buyer key when a relay asks for one. */\nexport type AuthSigner = (template: EventTemplate) => Promise<VerifiedEvent>;\n\nexport interface PublishResult {\n /** Relays that answered OK. */\n accepted: string[];\n /** Relays that refused, failed or timed out, with their reason. */\n failed: { relay: string; reason: string }[];\n}\n\nexport interface RelayClient {\n /**\n * Every event the relays hold for the filters, each once. Nothing is trusted:\n * the caller checks signatures and authors itself. A relay that fails adds\n * nothing; it does not fail the query.\n */\n query(relays: readonly string[], filters: readonly Filter[]): Promise<NostrEvent[]>;\n publish(relays: readonly string[], event: NostrEvent): Promise<PublishResult>;\n /**\n * Keep listening on each relay for `filter`, each event handed on once. A\n * relay that closes the subscription is opened again after a pause; one that\n * asks for AUTH gets it once, signed by the client's key.\n */\n subscribe(\n relays: readonly string[],\n filter: Filter,\n onEvent: (event: NostrEvent) => void,\n ): { close(): void };\n close(): void;\n}\n\n/** The part of a connected relay the client uses. */\nexport interface RelayLike {\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 /** A relay-level subscription: nostr-tools takes a LIST of filters here. */\n subscribe(\n filters: Filter[],\n params: {\n onevent?: (event: NostrEvent) => void;\n oneose?: () => void;\n onclose?: (reason: string) => void;\n },\n ): { close(reason?: string): void };\n}\n\n/** The part of `SimplePool` the client uses, so tests can stand in for relays. */\nexport interface PoolLike {\n subscribeEose(\n relays: string[],\n filter: Filter,\n params: {\n maxWait?: number;\n onauth?: AuthSigner;\n onevent?: (event: NostrEvent) => void;\n onclose?: (reasons: string[]) => void;\n },\n ): { close(reason?: string): void };\n ensureRelay(url: string, params?: { connectionTimeout?: number }): Promise<RelayLike>;\n destroy(): void;\n}\n\nexport interface RelayClientOptions {\n /** Answers NIP-42 AUTH challenges (the buyer key). Without it a relay that asks is refused. */\n auth?: AuthSigner;\n pool?: PoolLike;\n}\n\n/** `promise`, or a rejection once `ms` passed. */\nfunction withDeadline<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => reject(new Error('timed out')), ms);\n });\n return Promise.race([promise, deadline]).finally(() => clearTimeout(timer));\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * A pool that never answers an AUTH challenge on its own: the buyer key signs\n * only for a relay that refuses a request with auth-required (the query's\n * `onauth`, the publish retry), not for every relay that merely asks on connect.\n * Exported for tests.\n */\nexport function createPool(): SimplePool {\n return new SimplePool();\n}\n\nexport function createRelayClient(options: RelayClientOptions = {}): RelayClient {\n const pool: PoolLike = options.pool ?? createPool();\n\n /**\n * One filter at ONE relay to the end of its stored events; a relay that closes\n * with auth-required is retried after AUTH. One subscription per relay: relays\n * sharing a subscription share its seen-id set, so one relay's forged copy of\n * an event id would hide the genuine event from every other relay.\n */\n function queryRelay(relay: string, filter: Filter): Promise<NostrEvent[]> {\n return new Promise((resolve) => {\n const events: NostrEvent[] = [];\n let subscription: { close(reason?: string): void } | undefined;\n // An AUTH signer that fails leaves the library's retry pending forever:\n // answer with what arrived by the deadline instead.\n const deadline = setTimeout(() => {\n subscription?.close('deadline');\n resolve(events);\n }, RELAY_QUERY_DEADLINE_MS);\n try {\n subscription = pool.subscribeEose([relay], filter, {\n maxWait: RELAY_QUERY_MAX_WAIT_MS,\n ...(options.auth === undefined ? {} : { onauth: options.auth }),\n onevent: (event) => events.push(event),\n onclose: () => {\n clearTimeout(deadline);\n resolve(events);\n },\n });\n } catch (error) {\n clearTimeout(deadline);\n throw error;\n }\n });\n }\n\n /**\n * Publish to one relay: accepted only on its OK. A relay that cannot be reached\n * is a failure (the pool's own publish resolves a connection failure as if it\n * were an answer), and an auth-required refusal is retried once after AUTH.\n */\n async function publishOne(url: string, event: NostrEvent): Promise<string> {\n const relay = await pool.ensureRelay(url, { connectionTimeout: RELAY_CONNECT_MAX_WAIT_MS });\n try {\n return await relay.publish(event);\n } catch (error) {\n if (options.auth !== undefined && errorText(error).startsWith('auth-required')) {\n await relay.auth(options.auth);\n return relay.publish(event);\n }\n throw error;\n }\n }\n\n /** `publishOne` with an overall deadline: a relay that never settles counts as failed. */\n function publishWithDeadline(url: string, event: NostrEvent): Promise<string> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => reject(new Error('timed out')), RELAY_PUBLISH_DEADLINE_MS);\n });\n return Promise.race([publishOne(url, event), deadline]).finally(() => clearTimeout(timer));\n }\n\n /**\n * One relay's long-lived subscription. It is opened by hand (not through the\n * pool) so an AUTH re-subscription is ours to close, and re-opened after any\n * close with a growing pause until the caller closes it.\n */\n // Every live subscription's closer: closing the client closes them first, or a\n // subscription the pool drops would reconnect on a pool that no longer exists.\n const liveClosers = new Set<() => void>();\n\n function listenOn(url: string, filter: Filter, onEvent: (event: NostrEvent) => void) {\n let closed = false;\n let attempt = 0;\n // AUTH is answered once per CONNECTION: after a drop the pool builds a new,\n // unauthenticated one, which may ask again.\n let authenticatedOn: RelayLike | undefined;\n let current: { close(reason?: string): void } | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const again = () => {\n if (closed) {\n return;\n }\n const pause =\n SUBSCRIBE_RETRY_MS[Math.min(attempt, SUBSCRIBE_RETRY_MS.length - 1)] ??\n SUBSCRIBE_RETRY_MAX_MS;\n attempt += 1;\n timer = setTimeout(() => void open(), pause);\n };\n const open = async () => {\n if (closed) {\n return;\n }\n let relay: RelayLike;\n try {\n relay = await pool.ensureRelay(url, { connectionTimeout: RELAY_CONNECT_MAX_WAIT_MS });\n } catch {\n again();\n return;\n }\n if (closed) {\n return;\n }\n let liveSince: number | undefined;\n const subscription = relay.subscribe([filter], {\n onevent: onEvent,\n // nostr-tools also fires this on its own EOSE timeout, even after a CLOSED:\n // only a subscription still open counts.\n oneose: () => {\n if (current === subscription) {\n liveSince = Date.now();\n }\n },\n onclose: (reason) => {\n if (current === subscription) {\n current = undefined;\n // Only a subscription that stayed up a while starts the pauses over.\n if (liveSince !== undefined && Date.now() - liveSince >= SUBSCRIBE_STABLE_MS) {\n attempt = 0;\n }\n }\n if (closed) {\n return;\n }\n if (\n options.auth !== undefined &&\n authenticatedOn !== relay &&\n reason.startsWith('auth-required')\n ) {\n authenticatedOn = relay;\n // A signer that throws leaves nostr-tools' AUTH pending forever: bound it.\n withDeadline(relay.auth(options.auth), RELAY_PUBLISH_DEADLINE_MS).then(\n () => void open(),\n () => again(),\n );\n return;\n }\n again();\n },\n });\n current = subscription;\n };\n void open();\n return () => {\n closed = true;\n clearTimeout(timer);\n current?.close('closed by caller');\n };\n }\n\n return {\n subscribe(relays, filter, onEvent) {\n const seen = new Set<string>();\n // The id does not cover the signature: a relay could send a same-id copy with\n // a bad one first and hide the genuine copy from another relay. Only a\n // verified event takes its id (nostr-tools verifies too; this does not rely on it).\n const handOn = (event: NostrEvent) => {\n if (!seen.has(event.id) && isGenuineEvent(event)) {\n seen.add(event.id);\n onEvent(event);\n }\n };\n const closers = relays.map((relay) => listenOn(relay, filter, handOn));\n const closeAll = () => {\n for (const close of closers) {\n close();\n }\n liveClosers.delete(closeAll);\n };\n liveClosers.add(closeAll);\n return { close: closeAll };\n },\n async query(relays, filters) {\n if (relays.length === 0) {\n return [];\n }\n const seen = new Map<string, NostrEvent>();\n // One subscription per relay and filter: the pool takes a single filter, not a list.\n const batches = await Promise.allSettled(\n filters.flatMap((filter) => relays.map((relay) => queryRelay(relay, filter))),\n );\n for (const batch of batches) {\n if (batch.status !== 'fulfilled') {\n continue;\n }\n for (const event of batch.value) {\n // As in `subscribe`: only a verified copy takes its id.\n if (!seen.has(event.id) && isGenuineEvent(event)) {\n seen.set(event.id, event);\n }\n }\n }\n return [...seen.values()];\n },\n async publish(relays, event) {\n // Deduplicated as the pool keys its connections: two spellings of one relay\n // share one connection, and would count as two acknowledgements.\n const byConnection = new Map<string, string>();\n const unusable: string[] = [];\n for (const relay of relays) {\n let connection: string;\n try {\n connection = normalizeURL(relay);\n } catch {\n unusable.push(relay);\n continue;\n }\n if (!byConnection.has(connection)) {\n byConnection.set(connection, relay);\n }\n }\n const targets = [...byConnection.values()];\n const results = await Promise.allSettled(\n targets.map((relay) => publishWithDeadline(relay, event)),\n );\n const outcome: PublishResult = {\n accepted: [],\n failed: unusable.map((relay) => ({ relay, reason: 'not a relay URL' })),\n };\n results.forEach((result, index) => {\n const relay = targets[index];\n if (relay === undefined) {\n return;\n }\n if (result.status === 'fulfilled') {\n outcome.accepted.push(relay);\n } else {\n outcome.failed.push({ relay, reason: errorText(result.reason) });\n }\n });\n return outcome;\n },\n close() {\n for (const close of [...liveClosers]) {\n close();\n }\n // nostr-tools closes only OPEN sockets: one still connecting now opens\n // later and stays idle until the page goes (nothing subscribes on it).\n pool.destroy();\n },\n };\n}\n"]}
|