Skip to main content

Persistence and recovery

The store​

The driver keeps one record per swap, through a store you implement:

#[async_trait]
pub trait SwapStore: MaybeSend + MaybeSync {
async fn save(&self, record: &SwapRecord) -> Result<(), StoreError>;
async fn load(&self, swap_id: &Uuid) -> Result<Option<SwapRecord>, StoreError>;
async fn list(&self) -> Result<Vec<Uuid>, StoreError>;
}

Back it with anything durable: a table of JSON blobs keyed by swap_id is enough. Keep each record in its JSON form, version included, since a later SDK upgrades records only in that form. list returns ids, not records, so a record that fails to load stops only its own swap. Give each store one driver; in a browser, tabs over one store take turns on each swap.

A record holds the swap's terms, its status, and what the chain cannot report. It holds no keys, so encrypting it is your choice, not a requirement.

A restart is the same driver over the same store, and run again. Every swap resumes where the chain says it stands.

Losing the store​

The server keeps the signed request that created each swap, so a lost record can be rebuilt:

let swap = driver.restore(swap_id).await?;
let report = driver.restore_all().await?;
CallEffect
restoreRebuilds one swap after checking the request against this wallet and running the creation checks again. The swap is Restoring until its first pass.
restore_allRestores every swap the server lists for this wallet that the store lacks, and reports the ones restored and the ones that failed a check.

A server can leave a swap out of its listing, but cannot alter one. Treat restore as the fallback for a lost device, and the store as the plan.

What the mnemonic recovers​

Derived from the mnemonicUse
user_idthe identity the server knows the wallet by
Per swap, from its swap_idthe refund and claim keys, the Liquid blinding keys, the SwapOut preimage

A swap key revealed by the protocol exposes no other key, and a mnemonic that also backs an ordinary BIP32 wallet shares no key with it.

KeptRecovers
The mnemonicevery swap the server still lists
The mnemonic and the storeevery swap, also with the server gone

To recover a wallet:

  1. Build the wallet from the mnemonic, and the driver over the store, loaded from a backup if there is one.
  2. Call restore_all, then run.

Records across releases​

An SDK drives a record only when both its version and its key derivation match:

Written byversionKeys derived fromDriven by SDK 1.3.0 and later
SDK 1.2.01the seed, as BIP84 account keysno
SDK 1.3.0 and later1the seed tagged anyswap/user-wallet/v2yes

A 1.2.0 record still loads, but the driver watches an address nothing was paid to. Finish such swaps with the SDK that made them.

Within one version, a field a later SDK added reads as None until a pass fills it, as fee on a swap finished before 1.4.0; step makes that pass. A record of another version fails with RecordVersion, and an older SDK may not read a record a newer one wrote.