feat(checkout): surface the pool fee, complete the invoice lifecycle
The pool charges a flat 6 STRK per operation and documents it nowhere. The widget now reads it from get_fee_amount(), adds it to the total before the payer signs, and warns when it exceeds the invoice. Teaching MockWallet to charge it broke ten tests that had been passing mainnet-impossible flows. Payment correctness: - Hosted page takes its amount from the merchant's watcher, not its own query string: an edited ?amount= used to produce a real "Paid" screen for a thousandth of the price. New unauthenticated GET /public/invoices/:id?to= serves invoice terms to whoever holds the link, and nobody else. - Arcade INSERT COIN no longer tears down a checkout mid-payment: the money left, the credit never arrived, and the replacement invoice carried a new id so the duplicate guard never saw it either. - Partial payments become underpaid (with shortfall) instead of expired, so their address is never released for reuse. Late ones become paid_late inside a 24h grace window instead of being dropped. Overpayment is reported. - expiresAt in the past is refused at creation. Merchant operations: - Webhook queue persisted on the invoice row: a restart resumes deliveries rather than losing them. POST /invoices/:id/redeliver re-queues one. - Idempotency-Key on POST /invoices, so a timed-out retry returns the invoice it already created instead of "already exists". - GET /invoices.csv, with formula-injection-safe cells. Widget and demos: - Confirmation block before signing: merchant receives, pool fee, total, destination, network. Honesty panel moved above the button and opened. - Explorer links come from the wallet, so mock hashes are not linked and sepolia does not link to mainnet Voyager. - Wallet-missing message no longer tells you to update something you have not installed. Focus rings, 44px targets, reduced motion, touch controls, and keyboard capture that no longer steals Space from buttons. - Landing page linking all three apps. Packaging and tests: - strk20-pay is publish-ready with a README, a React binding, and a full manifest. Publishing is the owner's to run. - First automated tests for the widget, on a 120-line DOM double: 95 passing. - server/dev-static.mjs sends no-store, because a cached module made three verification passes report the old code's behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
B
bongbongcrypto committed
a069dc4fdf10eb2fb0df88aadded604ef617d521
Parent: bd2af8a