# 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 `boolean` indicating whether the execution was successful or not (in this case the user should either `refund()` on the source chain or `claim()` on the destination chain manually).

tip

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

info

Swaps from Bitcoin on-chain (L1) and Lightning (L2) to **Solana** use legacy swap protocols and are described below in the [Legacy Swaps](#legacy-swaps) section.

* Smart chain → BTC/Lightning
* BTC → Smart chain
* Lightning → Smart chain

> Swap classes: [ToBTCSwap](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/ToBTCSwap) and [ToBTCLNSwap](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/ToBTCLNSwap)

Same flow is shared for both, Smart chain → BTC & Smart chain → Lightning swaps.

Typical usage of the [execute()](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/IToBTCSwap#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](https://docs.atomiq.exchange/sdk-reference/api/atomiq-chain-solana/src/classes/SolanaSigner), or native `@coral-xyz/anchor` [Wallet](https://solana-foundation.github.io/anchor/ts/classes/Wallet.html)
* For Starknet → BTC swaps: [StarknetSigner](https://docs.atomiq.exchange/sdk-reference/api/atomiq-chain-starknet/src/classes/StarknetSigner), [StarknetBrowserSigner](https://docs.atomiq.exchange/sdk-reference/api/atomiq-chain-starknet/src/classes/StarknetBrowserSigner), or native `starknet` [Account](https://starknetjs.com/docs/API/classes/Account)
* For EVM → BTC swaps: [EVMSigner](https://docs.atomiq.exchange/sdk-reference/api/atomiq-chain-evm/src/classes/EVMSigner), or native `ethers` [Signer](https://docs.ethers.org/v6/api/providers/#Signer)

### 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. |

info

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](https://docs.atomiq.exchange/sdk-guide/swaps/smart-chain-to-btc.md).

> Swap classes: [SpvFromBTCSwap](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/SpvFromBTCSwap)

Typical usage of the [execute()](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/SpvFromBTCSwap#execute) function:

```
// Returns whether the swap was successfully executed automatically (via watchtowers - this should usually happen within a minute), 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](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/interfaces/IBitcoinWallet), e.g. the built-in [SingleAddressBitcoinWallet](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/SingleAddressBitcoinWallet)
* A simple object implementing [MinimalBitcoinWalletInterfaceWithSigner](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/type-aliases/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`. |

info

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](https://docs.atomiq.exchange/sdk-guide/swaps/btc-to-smart-chain.md).

> Swap classes: [FromBTCLNAutoSwap](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/FromBTCLNAutoSwap)

Typical usage of the [execute()](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/FromBTCLNAutoSwap#execute) function:

```
// Returns whether the swap was successfully executed automatically (via watchtowers - this should usually happen within a minute), 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](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/type-aliases/MinimalLightningNetworkWalletInterface):
  <!-- -->
  ```
  const lightningWallet: MinimalLightningNetworkWalletInterface = {

      payInvoice: (bolt11PaymentRequest: string) => {

          ... // Pay the provided bolt11 payment request

          return bolt11PaymentHash; //Return the hexadecimal payment hash

      }

  }
  ```
* LNURL-withdraw as `string` or [LNURLWithdraw](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/type-aliases/LNURLWithdraw) object from [SwapperUtils.parseAddress()](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/SwapperUtils#parseaddress)
* Pass `null` or `undefined` if 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. |

info

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](https://docs.atomiq.exchange/sdk-guide/swaps/lightning-to-smart-chain.md).

### 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](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/FromBTCSwap)

Typical usage of the [execute()](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/FromBTCSwap#execute) function:

```
// Returns whether the swap was successfully executed automatically (via watchtowers - this should usually happen within a minute), 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](https://docs.atomiq.exchange/sdk-reference/api/atomiq-chain-solana/src/classes/SolanaSigner), or native `@coral-xyz/anchor` [Wallet](https://solana-foundation.github.io/anchor/ts/classes/Wallet.html)

Type of the source bitcoin wallet can be:

* A class extending the abstract [IBitcoinWallet](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/interfaces/IBitcoinWallet), e.g. the built-in [SingleAddressBitcoinWallet](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/SingleAddressBitcoinWallet)
* A simple object implementing [MinimalBitcoinWalletInterfaceWithSigner](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/type-aliases/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`. |

info

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](https://docs.atomiq.exchange/sdk-guide/swaps/btc-to-smart-chain.md).

> Swap classes: [FromBTCLNSwap](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/FromBTCLNSwap)

Typical usage of the [execute()](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/FromBTCLNSwap#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](https://docs.atomiq.exchange/sdk-reference/api/atomiq-chain-solana/src/classes/SolanaSigner), or native `@coral-xyz/anchor` [Wallet](https://solana-foundation.github.io/anchor/ts/classes/Wallet.html)

Type of the lightning network source can be:

* A simple object implementing [MinimalLightningNetworkWalletInterface](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/type-aliases/MinimalLightningNetworkWalletInterface):
  <!-- -->
  ```
  const lightningWallet: MinimalLightningNetworkWalletInterface = {

      payInvoice: (bolt11PaymentRequest: string) => {

          ... // Pay the provided bolt11 payment request

          return bolt11PaymentHash; //Return the hexadecimal payment hash

      }

  }
  ```
* LNURL-withdraw as `string` or [LNURLWithdraw](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/type-aliases/LNURLWithdraw) object from [SwapperUtils.parseAddress()](https://docs.atomiq.exchange/sdk-reference/api/atomiq-sdk/src/classes/SwapperUtils#parseaddress)
* Pass `null` or `undefined` if 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. |

info

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](https://docs.atomiq.exchange/sdk-guide/swaps/lightning-to-smart-chain.md).

## 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                              | -                               |

### Timing & Fallback Availability

The `execute()` waits up to `maxWaitTillSwapProcessedSeconds` (default `120`) for the LP to process Smart chain → BTC/Lightning swaps, and up to `maxWaitTillAutomaticSettlementSeconds` (default `60`) for automatic settlement on incoming swaps. Past those limits it hands control back to you and the manual fallback applies.

The manual fallback might then take additional time become available:

| Manual fallback                | When it becomes available        | Typical timing                      |
| ------------------------------ | -------------------------------- | ----------------------------------- |
| Cooperative refund (LP online) | Immediately after the swap fails | Seconds — the LP co-signs           |
| Unilateral refund — Lightning  | Only after the refund timeout    | \~4–5 days                          |
| Unilateral refund — BTC L1     | Only after the refund timeout    | \~12 hours                          |
| Claim / settlement             | Immediately — no waiting period  | Seconds — you broadcast your own tx |

**Refunds:** `swap.refund()` first attempts the cooperative path, which settles in seconds whenever the LP is online. If the LP is unreachable it falls back to a unilateral refund, broadcastable only after the swap's on-chain timeout (\~4–5 days Lightning, \~12 hours BTC L1).

**Claims/settlements:** destination funds are claimable *immediately* — there is no lock-up. In practice watchtowers settle for you, usually in under a minute (which is why `execute()` waits \~60s before returning). You never depend on them: `swap.claim()` can be called at any time if you'd rather not wait or avoid an external dependency.

For the full state machine and step-by-step manual processing, see [Swap Management → Refunds](https://docs.atomiq.exchange/sdk-guide/swap-management/refunds.md) and [→ Claiming](https://docs.atomiq.exchange/sdk-guide/swap-management/claiming.md), or the per-type pages under [Swap Types](https://docs.atomiq.exchange/sdk-guide/swaps.md).

## Next Steps

### Swap Management

Retrieve & query past swaps, handle refundable and claimable swaps. This is an important next step for integration, as it ensures existing refundable/claimable swaps can be handled automatically or user prompted to refund, claim/settle them manually.

**[Swap Management →](https://docs.atomiq.exchange/sdk-guide/swap-management.md)**

***

### Detailed Swap Type Descriptions

Explain each swap type in-depth, go through manually processing the swap & explain various swap states.

**[Swap Types →](https://docs.atomiq.exchange/sdk-guide/swaps.md)**

***

### Utilities

SDK-exposed utilities allow you to parse addresses (including LNURL links), fetch token balances, list supported tokens and swap types.

**[Utilities →](https://docs.atomiq.exchange/sdk-guide/utilities.md)**

***
