Skip to content

Drop a kept inscription launch whose commit can never confirm - #53

Merged
droplister merged 1 commit into
mainfrom
fix/pending-reveal-dead
Sep 30, 2026
Merged

droplister merged 1 commit into
mainfrom
fix/pending-reveal-dead

Conversation

@droplister

Copy link
Copy Markdown
Member

Follow-up to #50. A saved reveal record blocks new inscription launches from its address until the launch is finished. Say the commit never reached the network, for example because the page died before it was broadcast. If the coin it spends is then used by another transaction, "Finish launching" re-broadcast the commit, the node refused it (missingorspent), and the record stayed. The address was blocked for good.

Change (apps/web/src/lib/inscribe-launch.ts). This applies only when the commit's /tx/:txid/status is unknown, meaning it is neither confirmed nor in the mempool. resumeInscribeLaunch now reads /tx/:prev/outspend/:vout for each commit input. It uses the same esplora base (BITCOIN_API_BASE) the file already uses. If an input was spent by a different transaction and that spend is confirmed, the commit can never confirm. In that case the function:

  • clears the record;
  • signs and broadcasts nothing;
  • returns { outcome: "abandoned", commitTxid, spentBy }.

A successful resume now returns { outcome: "launched", commitTxid, revealTxid }.

Not cleared. In each of these cases the record stays and the old path runs (re-broadcast, then an error if it fails):

  • the conflicting spend is only in the mempool, since it can be evicted or replaced;
  • the input is unspent;
  • the only spend reported is the commit itself;
  • the outspend read returns HTTP errors;
  • the request fails.

Page (create/page.tsx). On abandoned, a one-time neutral notice replaces the amber banner. It is shown for that address only and is not persisted, since the record is already gone: "The inscription commit for {asset} never made it on-chain, and a coin it spends has since been spent by another confirmed transaction, so it never will. None of its BTC is waiting on a reveal, and you can start a new launch."

Localization. Translated into es, fr, ja, ko, pt, ru, uk, zh, zh-tw and zh-hk. Each entry is added to <locale>.status.json under machine, as #50 did.

Tests (tests/inscribe-launch-recovery.test.ts).

  • The abandoned path: exact result, no signature, no broadcast, record cleared.
  • Five keep-the-record cases: unconfirmed conflict, unspent input, only the commit spending it, HTTP 503, fetch failure. Each ends in a refused re-broadcast with the record still there.
  • The existing tests are updated for the outcome field.

Gates run locally: npm run check (111 files, 1432 tests, typecheck, lint, numeric, i18n with every locale at 1295/1295) and next build. No api code changed.

A kept reveal blocks new inscription launches from its address until it
is finished. When its commit is neither confirmed nor in the mempool and
one of the commit's inputs has since been spent by another confirmed
transaction, the commit can never confirm and no BTC waits behind it:
resuming used to re-broadcast it, fail, and keep the record forever.

resumeInscribeLaunch now asks the Bitcoin API for each input's outspend
first. A confirmed spend by another transaction clears the record,
broadcasts and signs nothing, and returns an "abandoned" outcome; the
create page shows a one-time notice instead of an error. A mempool-only
conflict, an unspent input, or an unreadable status keeps the record and
the old path. The notice is machine-translated in every locale and
listed as such in each status file.
@droplister
droplister merged commit 0b0ff2a into main Sep 30, 2026
@droplister
droplister deleted the fix/pending-reveal-dead branch September 30, 2026 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant