Executing Swaps
After you create and inspect a quote with swapper.swap(...), the usual next step is swap.execute(...).
execute() is the high-level execution path used by the SDK. It is state-aware, so it resumes from the current swap state, performs the next on-chain or off-chain action, and then waits for automatic settlement when the protocol supports it. Generally the execute() function follows this syntax:
import {isRefundableSwap, isClaimableSwap} from "@atomiqlabs/sdk";
const result = await swap.execute(/* source signer or wallet */, /* optional callbacks */, /* optional options */);
if (result === false) {
// In case of Smart chain → BTC/Lightning swaps:
// - the swap has failed and the user can refund with swap.refund(...)
if(isRefundableSwap(swap)) await swap.refund(/* source chain signer or wallet - always a smart chain signer */);
// In case of BTC/Lightning → Smart chain swaps:
// - the swap wasn't settled automatically, call swap.claim(...) to settle the swap manually with the destination chain signer.
if(isClaimableSwap(swap)) await swap.claim(/* destination chain signer or wallet - always a smart chain signer */);
}
The high-level flow is shared across swap types, but the execute(...) signature is not identical everywhere, in general the swaps:
- take a signer/wallet on the source chain
- return a
booleanindicating whether the execution was successful or not (in this case the user should eitherrefund()on the source chain orclaim()on the destination chain manually).
If you need low-level control instead of execute() or want to get raw transactions and PSBTs that you sign and send manually, see the respective swap pages.
Swap Types
An overview of execute() function arguments for various swap types
Swaps from Bitcoin on-chain (L1) and Lightning (L2) to Solana use legacy swap protocols and are described below in the Legacy Swaps section.
- Smart chain → BTC/Lightning
- BTC → Smart chain
- Lightning → Smart chain
Swap classes: ToBTCSwap and ToBTCLNSwap
Same flow is shared for both, Smart chain → BTC & Smart chain → Lightning swaps.
Typical usage of the execute() function:
// Returns whether the swap was successfully executed by the LP, if not the user can refund
const swapSuccess = await swap.execute(srcSigner, callbacks?, options?);
// Refund on failure, this returns the funds back to the signer's wallet
if (!swapSuccess) await swap.refund(srcSigner);
Type of the signer is dependent on the source network:
- For Solana → BTC swaps: SolanaSigner, or native
@coral-xyz/anchorWallet - For Starknet → BTC swaps: StarknetSigner, StarknetBrowserSigner, or native
starknetAccount - For EVM → BTC swaps: EVMSigner, or native
ethersSigner
Callbacks
| Name | Type | Description |
|---|---|---|
onSourceTransactionSent | (sourceTxId: string) => void | Fired when the source smart-chain commit transaction is sent. |
onSourceTransactionConfirmed | (sourceTxId: string) => void | Fired when the source smart-chain transaction is confirmed. |
onSwapSettled | (destinationTxId: string) => void | Fired when the BTC or Lightning payment is sent. |
Options
| Name | Type | Description |
|---|---|---|
abortSignal | AbortSignal | Cancels execution or waiting. |
paymentCheckIntervalSeconds | number | Polling interval used while waiting for the LP to process the payment. |
maxWaitTillSwapProcessedSeconds | number | Maximum time to wait for the LP to process the swap. Defaults to 120. If the LP doesn't process the swap an Error is thrown, you can then get the swap expiration time with swap.getExpiry() after which you can refund unilaterally. |
For more details about the swap, swap states, going through swap steps manually or getting the transactions to sign and send outside the SDK refer to the respective Smart Chain → Bitcoin swap.
Swap classes: SpvFromBTCSwap
Typical usage of the execute() function:
// Returns whether the swap was successfully executed automatically, if not the user can claim manually
const automaticallySettled = await swap.execute(bitcoinWallet, callbacks?, options?);
// Claim on failure, this settles the funds to the destination chain signer
if (!automaticallySettled) await swap.claim(destinationSmartChainSigner);
Type of the source wallet can be:
- A class extending the abstract IBitcoinWallet, e.g. the built-in SingleAddressBitcoinWallet
- A simple object implementing MinimalBitcoinWalletInterfaceWithSigner type:
const bitcoinWallet: MinimalBitcoinWalletInterfaceWithSigner = {
address: "bc1p..", // Wallet address
publicKey: "03030cbd...", // Wallet public key
signPsbt: (psbtToSign: {psbt: Transaction, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
... // Sign the inputs specified by `signInputs` of the provided PSBT here.
return signedPsbt; // Can be in base64 or hex serialized format, or `@scure/bitcoin-js` Transaction object.
}
}
Callbacks
| Name | Type | Description |
|---|---|---|
onSourceTransactionSent | (sourceTxId: string) => void | Fired when the BTC swap transaction is sent. |
onSourceTransactionConfirmationStatus | (sourceTxId?: string, confirmations?: number, targetConfirations?: number, etaMs?: number) => void | Progress callback while waiting for the BTC transaction to confirm. |
onSourceTransactionConfirmed | (sourceTxId: string) => void | Fired once the BTC transaction is confirmed. |
onSwapSettled | (destinationTxId: string) => void | Fired when the destination-chain settlement succeeds automatically or is fronted. |
Options
| Name | Type | Description |
|---|---|---|
feeRate | number | Bitcoin fee rate to use when the SDK sends the BTC transaction. |
abortSignal | AbortSignal | Cancels execution or waiting. |
btcTxCheckIntervalSeconds | number | Polling interval while waiting for the BTC transaction to confirm. |
maxWaitTillAutomaticSettlementSeconds | number | Maximum time to wait for automatic destination settlement. Defaults to 60. |
For more details about the swap, swap states, going through swap steps manually or getting the raw PSBT to sign outside the SDK refer to the respective Bitcoin → Smart Chain swap.
Swap classes: FromBTCLNAutoSwap
Typical usage of the execute() function:
// Returns whether the swap was successfully executed automatically, if not the user can claim manually
const automaticallySettled = await swap.execute(lightningWalletOrLnurlWithdraw?, callbacks?, options?);
// Claim on failure, this settles the funds to the destination chain signer
if (!automaticallySettled) await swap.claim(destinationSmartChainSigner);
Type of the lightning network source can be:
- A simple object implementing MinimalLightningNetworkWalletInterface:
const lightningWallet: MinimalLightningNetworkWalletInterface = {
payInvoice: (bolt11PaymentRequest: string) => {
... // Pay the provided bolt11 payment request
return bolt11PaymentHash; //Return the hexadecimal payment hash
}
} - LNURL-withdraw as
stringor LNURLWithdraw object from SwapperUtils.parseAddress() - Pass
nullorundefinedif the invoice will be paid externally:const bolt11PaymentInvoice = swap.getAddress(); // Returns the lightning network invoice to be displayed and paid by the user
const lightningPaymentDeeplink = swap.getHyperlink(); // Or get a `lightning:` deeplink that can be displayed as QR code
// Display the invoice and/or deeplink in a QR code to the user
// Call execute without a wallet for it to wait till an external payment arrives
const automaticallySettled = await swap.execute(null, callbacks?, options?);
Callbacks
| Name | Type | Description |
|---|---|---|
onSourceTransactionReceived | (sourceTxId: string) => void | Fired when the Lightning payment is received by the LP. |
onSwapSettled | (destinationTxId: string) => void | Fired when the destination-chain settlement succeeds automatically. |
Options
| Name | Type | Description |
|---|---|---|
abortSignal | AbortSignal | Cancels execution or waiting. |
lightningTxCheckIntervalSeconds | number | Polling interval while waiting for the Lightning payment to arrive. |
maxWaitTillAutomaticSettlementSeconds | number | Maximum time to wait for automatic destination settlement. Defaults to 60. |
secret | string | Secret/pre-image to broadcast to watchtowers. Usually only needed when the swap was recovered or the pre-image was generated outside the SDK. |
For more details about the swap, swap states, going through swap steps manually or getting the transactions to sign and send outside the SDK refer to the respective Lightning → Smart Chain swap.
Legacy Swaps
These swaps use the legacy protocol in the Bitcoin/Lightning → Solana direction, and require a destination Solana wallet to sign and send transactions.
- BTC → Solana
- Lightning → Solana
Swap classes: FromBTCSwap
Typical usage of the execute() function:
// Returns whether the swap was successfully executed automatically, if not the user can claim manually
const automaticallySettled = await swap.execute(dstSigner, bitcoinWallet?, callbacks?, options?);
// Claim on failure, this settles the funds to the destination chain signer
if (!automaticallySettled) await swap.claim(dstSigner);
Type of the destination dstSigner signer: SolanaSigner, or native @coral-xyz/anchor Wallet
Type of the source bitcoin wallet can be:
- A class extending the abstract IBitcoinWallet, e.g. the built-in SingleAddressBitcoinWallet
- A simple object implementing MinimalBitcoinWalletInterfaceWithSigner type:
const bitcoinWallet: MinimalBitcoinWalletInterfaceWithSigner = {
address: "bc1p..", // Wallet address
publicKey: "03030cbd...", // Wallet public key
signPsbt: (psbtToSign: {psbt: Transaction, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
... // Sign the inputs specified by `signInputs` of the provided PSBT here.
return signedPsbt; // Can be in base64 or hex serialized format, or `@scure/bitcoin-js` Transaction object.
}
}
Callbacks
| Name | Type | Description |
|---|---|---|
onDestinationCommitSent | (destinationCommitTxId: string) => void | Fired when the destination-chain commit/open-address transaction is sent. |
onSourceTransactionSent | (sourceTxId: string) => void | Fired when the BTC funding transaction is sent. |
onSourceTransactionConfirmationStatus | (sourceTxId?: string, confirmations?: number, targetConfirations?: number, etaMs?: number) => void | Progress callback while waiting for the BTC transaction to confirm. |
onSourceTransactionConfirmed | (sourceTxId: string) => void | Fired once the BTC transaction is confirmed. |
onSwapSettled | (destinationTxId: string) => void | Fired when the destination-chain settlement is completed automatically. |
Options
| Name | Type | Description |
|---|---|---|
feeRate | number | Bitcoin fee rate to use when the SDK sends the BTC transaction. |
abortSignal | AbortSignal | Cancels execution or waiting. |
btcTxCheckIntervalSeconds | number | Polling interval while waiting for the BTC transaction to confirm. |
maxWaitTillAutomaticSettlementSeconds | number | Maximum time to wait for automatic destination settlement. Defaults to 60. |
For more details about the swap, swap states, going through swap steps manually or getting the transactions to sign and send outside the SDK refer to the respective Bitcoin → Smart Chain swap.
Swap classes: FromBTCLNSwap
Typical usage of the execute() function:
// Executes the full legacy flow, always returns `true`, so there is not edge-case to cover
await swap.execute(dstSigner, lightningWalletOrLnurlWithdraw?, callbacks?, options?);
Type of the destination dstSigner signer: SolanaSigner, or native @coral-xyz/anchor Wallet
Type of the lightning network source can be:
- A simple object implementing MinimalLightningNetworkWalletInterface:
const lightningWallet: MinimalLightningNetworkWalletInterface = {
payInvoice: (bolt11PaymentRequest: string) => {
... // Pay the provided bolt11 payment request
return bolt11PaymentHash; //Return the hexadecimal payment hash
}
} - LNURL-withdraw as
stringor LNURLWithdraw object from SwapperUtils.parseAddress() - Pass
nullorundefinedif the invoice will be paid externally:const bolt11PaymentInvoice = swap.getAddress(); // Returns the lightning network invoice to be displayed and paid by the user
const lightningPaymentDeeplink = swap.getHyperlink(); // Or get a `lightning:` deeplink that can be displayed as QR code
// Display the invoice and/or deeplink in a QR code to the user
// Call execute without a wallet for it to wait till an external payment arrives
const automaticallySettled = await swap.execute(null, callbacks?, options?);
Callbacks
| Name | Type | Description |
|---|---|---|
onSourceTransactionReceived | (sourceTxId: string) => void | Fired when the Lightning payment is received by the LP. |
onDestinationCommitSent | (destinationCommitTxId: string) => void | Fired when the destination-chain commit transaction is sent. |
onDestinationClaimSent | (destinationClaimTxId: string) => void | Fired when the destination-chain claim transaction is sent. |
onSwapSettled | (destinationTxId: string) => void | Fired when the destination-chain funds are claimed and the swap is settled. |
Options
| Name | Type | Description |
|---|---|---|
abortSignal | AbortSignal | Cancels execution or waiting. |
lightningTxCheckIntervalSeconds | number | Polling interval while waiting for the Lightning payment to arrive. |
delayBetweenCommitAndClaimSeconds | number | Optional delay inserted between sending commit and claim transaction on the destination network. |
secret | string | Override the swap secret/pre-image. Usually only needed when the swap was recovered or the pre-image was generated outside the SDK. |
For more details about the swap, swap states, going through swap steps manually or getting the transactions to sign and send outside the SDK refer to the respective Lightning → Smart Chain swap.
Summary of Failure Modes and Fallbacks
When execute() returns false and does not fully finish the swap automatically:
| Swap family | Failure Mode | Manual fallback |
|---|---|---|
| Smart chain → BTC L1 / Lightning | LP didn't process the swap | swap.refund(sourceSigner) |
| BTC L1 → Starknet / EVM | Swap wasn't settled automatically | swap.claim(destinationSigner) |
| Lightning → Starknet / EVM | Swap wasn't settled automatically | swap.claim(destinationSigner) |
Legacy Swaps
| Swap family | Failure Mode | Manual fallback |
|---|---|---|
| BTC L1 → Solana (legacy) | Swap wasn't settled automatically | swap.claim(destinationSigner) |
| Lightning → Solana (legacy) | None | - |
Next Steps
Detailed Swap Type Descriptions
Explain each swap type in-depth, go through manually processing the swap & explain various swap states.
Utilities
SDK-exposed utilities allow you to parse addresses (including LNURL links), fetch token balances, list supported tokens and swap types.
Swap Management
Retrieve & query past swaps, handle refundable and claimable swaps.