Skip to main content
A Bitcoin deposit action provides a payment address, an amount in satoshis, and a memo in call_data. The transaction must contain both the payment output and the memo output so Layerswap can match it to the swap.

Encode the memo

Current call_data contains a decimal sequence number followed by a ; terminator, for example "11177265;". Convert only the numeric part to hexadecimal with BigInt, then preserve the terminator and any appended data verbatim:
Layerswap parses the hexadecimal text before ; for matching. Data after ; is ignored by the matcher, but still counts toward the standard 80-byte OP_RETURN payload limit. Do not call Number(call_data): the terminator produces NaN, and large sequence values can lose precision.

Transaction construction

1

Fetch UTXOs

Retrieve unspent transaction outputs for the sender’s address, from your own Bitcoin node or a provider such as the Mempool.space API.
2

Fetch raw transactions

For each UTXO, fetch the full raw transaction hex. This is needed to populate the witnessUtxo field in the PSBT inputs.
3

Select UTXOs

Select enough UTXOs to cover the deposit amount plus estimated fees.
4

Build the PSBT

Create a PSBT with:
  • Inputs: selected UTXOs with witness data
  • Output 1: payment to action.to_address for BigInt(action.amount_in_base_units) satoshis
  • Output 2: zero-value OP_RETURN carrying the encoded memo
  • Output 3 (if needed): change back to the sender’s address
5

Estimate fees

Fetch the recommended fee rate and calculate the transaction fee from the input/output count. Re-select UTXOs if the initial selection doesn’t cover the fee.
6

Sign and broadcast

Sign the PSBT with the sender’s key or wallet and broadcast the raw transaction.
Populate inputs according to their script type. SegWit inputs use witnessUtxo; legacy inputs require the full previous transaction as nonWitnessUtxo. Fetch UTXOs and recommended fee rates from your own node or a provider such as the Mempool.space API, estimate fees from the final input/output mix, and avoid creating dust change.

Full example

A server-side flow that fetches UTXOs, iteratively selects inputs to cover the fee, embeds the memo, signs with a private key, and broadcasts:
The example populates every input as SegWit (witnessUtxo); add nonWitnessUtxo handling if the sending wallet holds legacy UTXOs.

Signing for different address types

Use the signing rules required by the wallet’s address type: Using SIGHASH_ALL on a Taproot input produces an invalid signature.

Hardware and browser wallets

With a wallet provider (Xverse, Unisat, Leather, and similar) instead of a raw private key, the flow changes at the signing step: pass the unsigned PSBT hex to the wallet’s signPsbt method with per-input signing indexes and the sighash for the address type:
Broadcast the extracted raw transaction, then store the transaction id and track the swap.