Skip to main content

Quickstart

One SwapOut on Bitcoin, from setup to Completed. The switch in the navbar picks the language of every snippet on the site.

1. Build the driver​

use anyswap_sdk::{
client::HttpClient,
context::SwapContext,
driver::{ChainConfig, Driver, MemoryStore, TargetAmount},
esplora::BitcoinEsplora,
types::{Chain, SwapNetwork},
wallet::Wallet,
};

const NETWORK: SwapNetwork = SwapNetwork::Mainnet;

let (wallet, mnemonic) = Wallet::generate(NETWORK)?;
let client = HttpClient::new("https://anyswap.example.com", Some(&wallet))?;

let driver = Driver::new(SwapContext::new(wallet), client.clone(), MemoryStore::default())
.with_chain(
Chain::Bitcoin,
BitcoinEsplora::new("https://esplora.example.com/api")?,
ChainConfig::bitcoin(),
)?
.with_signals(client.signals());
ObjectHolds
Walletevery key, derived from the mnemonic; the mnemonic restores every swap
HttpClientthe server API, signing each request as the wallet
SwapContextthe wallet, plus the Liquid parameters when you swap there
BitcoinEsplorachain reads and broadcasts; a chain without one cannot be swapped on
MemoryStorethe swap records, forgotten on exit; a real app passes a durable store
Signalsthe server's WebSocket, which wakes the driver when a swap moves; without it the driver polls

2. Quote​

let quote = driver
.quote(None, Some(Chain::Bitcoin), TargetAmount::Receive(50_000))
.await?;
println!("pay {}, receive {}", quote.send_amount, quote.receive_amount);

The quote is the price the user accepts: send_amount is receive_amount plus the fees, and it holds until expires_at.

3. Create the swap​

let swap = driver.swap_out(quote, Some(claim_address)).await?;
println!("pay {}", swap.claim_invoice().await?);

The user pays the invoice. It is a hold invoice: the payment stays pending until the funds are locked on chain for the user.

4. Run and watch​

let mut updates = driver.subscribe();
tokio::spawn(driver.run());
while let Some(swap) = updates.next().await {
match swap.error() {
Some(error) => eprintln!("{} error: {error}", swap.swap_id()),
None => println!("{} {:?}", swap.swap_id(), swap.status().await?),
}
}

The swap moves through Funding, Confirming and Claiming to Completed. Swaps has every status and what it means.

Runnable examples​

RustTypeScriptShows
swaps.rsswaps.tsany number of swaps, both ways, on both chains, in the background
advance.rsadvance.tsone swap driven by hand over a file store, resumable after a restart