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
Currentcall_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:
; 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_addressforBigInt(action.amount_in_base_units)satoshis - Output 2: zero-value
OP_RETURNcarrying 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.
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: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’ssignPsbt method with per-input signing indexes and the sighash for the address type: