How it works
The audit, the plan tree, the simulator, and the executor.
Account closure on Stellar is a sequence of standard transactions, not a custodial service. The demolisher's job is to assemble the right sequence in the right order, simulate it before signing, and recover cleanly when the network state shifts under it. Nothing is mocked. Every step happens on chain.
Read the account
The audit step calls Horizon for the full account state: balances, signers, thresholds, flags, offers, data entries, sponsorship counts, claimable balances, and pool-share trustlines. Soroban RPC is also called for any token balances and active SEP-41 allowances. The result is a single read-only snapshot the rest of the flow works from.
The audit also computes a feasibility verdict. Two cases are hard stops:
AUTH_IMMUTABLEis set. The account cannot ever be merged. The protocol forbids it.- The account is sponsoring entries for others (
num_sponsoring > 0). The owner of the sponsored entries has to revoke the sponsorships first.
Both are surfaced with explicit reasons, not silent failures.
Build the plan
The audit, the discovered DeFi positions, and the discovered allowances feed a pure plan generator. It produces a directed acyclic graph of nodes. Each node has one of 14 kinds:
- Allowance:
RevokeAllowance - Blend:
RepayBlend,WithdrawBlend,ClaimBlendEmissions,BackstopQueue - Aquarius:
WithdrawAquarius,ClaimAquariusRewards - Soroswap:
WithdrawSoroswapLp,ConvertSorobanToXLM - FxDAO:
PayFxDAODebt,RedeemFxDAO - Generic:
TransferAsIs(SEP-41 token transfer) - Classic:
FinalClassicTx(the bundled classical close) - Mediator:
MediatorForward(used only when the destination is an exchange)
Nodes carry their dependencies. Blend withdraw nodes wait for Blend repay nodes to finish. The final classical transaction waits for every soroban node. The mediator forward, when present, waits for the final classical transaction.
The graph is validated at build time: duplicates, missing dependencies, and cycles are rejected. Execution walks it in topological order using Kahn's algorithm so the order is stable and deterministic.
The classical batch
FinalClassicTx is one classical Stellar transaction. The order of operations inside it is fixed:
- Withdraw classical liquidity pool positions
- Cancel open offers
- Claim opted-in claimable balances
- Convert non-XLM credit balances via
PATH_PAYMENT_STRICT_SEND, with a return-to-issuer fallback if no path exists - Remove trustlines (pool-share first, then underlying credit trustlines)
- Delete data entries
- Revoke remaining sponsorships (the count is reduced by any self-sponsored claimable balances already claimed in step 3, so the batcher never emits an
op_revoke_sponsorshipfor an entry that no longer exists) - Clear non-master signers and reset thresholds
ACCOUNT_MERGE
If the batch exceeds 100 operations (the protocol limit), it is split at 100 and the merge always lands in the last transaction.
When the destination is a centralized exchange, a CREATE_ACCOUNT op funding the mediator with 2 XLM is prepended to the first batch and the merge targets the mediator, not the user's destination. See Destinations and the mediator.
Simulate before signing
Before any user confirmation, every plan node is simulated:
- Soroban nodes are simulated through the Soroban RPC
simulateTransactionendpoint. The returnedtransactionDataand resource fee are baked into the envelope. If the simulation reports a footprint restore preamble, it is honored. - The final classical transaction is built locally and the operation count and estimated fee are exposed.
The plan tree in the preview step shows the result of each simulation. If something cannot be simulated (a missing balance, a stale footprint), the node is marked failed in the preview, and the closure is held until the user resolves it or confirms the gap.
Execute
Execution walks the topological order. For each node it:
- Re-reads the account if needed (the final classical transaction is rebuilt fresh from the latest state every time it runs, because soroban exits ahead of it move balances around).
- Hands the unsigned envelope to the connector. For Stellar Wallets Kit, this opens the user's wallet UI. For the secret-key fallback, the keypair signs locally in browser memory.
- Submits the signed envelope. Classical to Horizon. Soroban to the RPC, then polls until the receipt arrives.
- Records the receipt and ticks the row to confirmed in the UI.
Failed nodes go through a typed classifier that maps the failure to one of: retry, retry with a fee bump, retry with a fresh sequence number, retry with re-simulation, surface a user-consent gate (for slippage changes that need explicit approval), or escalate to fatal. The fatal state is terminal; everything else can be retried automatically up to a per-flow limit.
Why this design
The closure is a sequence of standard, auditable Stellar transactions. The plan is exposed to the user before signing. The simulation grounds the plan in the real network state. The classifier closes the loop on transient failures. No part of the flow asks the user to trust a server holding their key.