Files
breez-sdk-docs/src/guide/send_onchain.md
2023-10-04 23:42:37 +03:00

10 KiB

Sending an on-chain transaction (swap-out)

You can send funds from the Breez SDK wallet to an on-chain address as follows.

First, fetch the current reverse swap fees:

Rust
let current_fees = sdk.fetch_reverse_swap_fees(
    ReverseSwapFeesRequest {
        send_amount_sat: Some(50000),
    })
    .await?;

info!("Total estimated fees for reverse swap: {}", current_fees.total_estimated_fees);
Swift
let sendAmountSat:UInt64? = 50000
try {
  let currentFees = try sdk.fetchReverseSwapFees(
      req: ReverseSwapFeesRequest(sendAmountSat: sendAmountSat))
  print("Total estimated fees for reverse swap: \(currentFees.totalEstimatedFees)")
} catch {
    // handle error
}
Android
try {
    val fees = sdk.fetchReverseSwapFees(ReverseSwapFeesRequest(50000))
    Log.v("Breez", "Total estimated fees for reverse swap: ${fees.totalEstimatedFees}")
} catch (e: Exception) {
    // handle error
}
React Native
try {
    const currentFees = await fetchReverseSwapFees({sendAmountSat: 50000})

    console.log(`Total estimated fees for reverse swap: ${currentFees.totalEstimatedFees}`);
} catch (error) {
    console.log(error)
}
Dart
try {
    ReverseSwapPairInfo currentFees = await fetchReverseSwapFees(
        req: ReverseSwapFeesRequest(
            sendAmountSat: 50000,
        ),
    );

    print("Total estimated fees for reverse swap: ${currentFees.totalEstimatedFees}");
} catch (error) {
    // handle error
}
Python
try: 
    current_fees = sdk_services.fetch_reverse_swap_fees(
        breez_sdk.ReverseSwapFeesRequest(send_amount_sat=50000))
    print("Total estimated fees for reverseswap:", current_fees.total_estimated_fees)
except Exception as error:
    # Handle error
Go
sendAmountSat := uint64(50000)
reverseSwapFeesRequest := breez_sdk.ReverseSwapFeesRequest{
    SendAmountSat: &sendAmountSat,
}
if currentFees, err := sdk.FetchReverseSwapFees(reverseSwapFeesRequest); err == nil {
    log.Printf("Total estimated fees for reverse swap: %v", currentFees.TotalEstimatedFees)
}
C#
try
{
    var currentFees = sdk.FetchReverseSwapFees(
        new ReverseSwapFeesRequest(50000));
    Console.WriteLine($"Total estimated fees for reverse swap: {currentFees.totalEstimatedFees}");
}
catch (Exception)
{
    // Handle error
}

The reverse swap will involve two on-chain transactions, for which the mining fees can only be estimated. They will happen automatically once the process is started, but the last two values above are these estimates to help you get a picture of the total costs.

Fetching the fees also tells you what is the range of amounts you can send:

Rust
info!("Minimum amount, in sats: {}", current_fees.min);
info!("Maximum amount, in sats: {}", current_fees.max);
Swift
println("Minimum amount, in sats: \(current_fees.min)")
println("Maximum amount, in sats: \(current_fees.max)")
Android
Log.v("Breez", "Minimum amount, in sats: ${fees.min}")
Log.v("Breez", "Maximum amount, in sats: ${fees.max}")
React Native
console.log(`Minimum amount, in sats: ${currentFees.min}`);
console.log(`Maximum amount, in sats: ${currentFees.max}`);
Dart
print("Minimum amount, in sats: ${currentFees.min}");
print("Maximum amount, in sats: ${currentFees.max}");
Python
print("Minimum amount, in sats: ", current_fees.min)
print("Maximum amount, in sats: ", current_fees.max)
Go
log.Printf("Minimum amount, in sats: %v", currentFees.Min)
log.Printf("Maximum amount, in sats: %v", currentFees.Max)
C#
Console.WriteLine($"Minimum amount, in sats: {currentFees.min}");
Console.WriteLine($"Maximum amount, in sats: {currentFees.max}");

Once you checked the fees are acceptable, you can start the reverse swap:

Rust
let destination_address = String::from("bc1..");
let amount_sat = current_fees.min;
let satPerVbyte = <fee rate>;

sdk.send_onchain(amount_sat, destination_address, current_fees.fees_hash, satPerVbyte).await?;
Swift
let destinationAddress = "bc1.."
let amountSat = currentFees.min
let satPerVbyte = <fee rate>
try {
  try sdk.sendOnchain(
    amountSat: amountSat,
    onchainRecipientAddress: destinationAddress, 
    pairHash: currentFees.feesHash,
    satPerVbyte: satPerVbyte)
} catch {
    // handle error
}
Android
val address = "bc1.."
val amountSat = 123L.toULong()
val satPerVbyte = 1L.toULong()
try {
    sdk.sendOnchain(amountSat, address, fees.feesHash, satPerVbyte)
} catch (e: Exception) {
    // handle error
}
React Native
const destinationAddress = "bc1..";
const amountSat = currentFees.min;
const satPerVbyte = <fee rate>
try {
    const reverseSwapInfo = await sendOnchain(amountSat, destinationAddress, currentFees.feesHash, satPerVbyte)
} catch (error) {
    console.log(error)
}
Dart
String destinationAddress = "bc1..";
int amountSat = <amount>;
int satPerVbyte = <fee rate>
ReverseSwapPairInfo currentFees = <current reverse swap fees>
try {
    ReverseSwapInfo reverseSwapInfo = await sendOnchain(
        amountSat: amountSat,
        onchainRecipientAddress: destinationAddress,
        pairHash: currentFees.feesHash,
        satPerVbyte: satPerVbyte,
    );
} catch (error) {
    // handle error
}
Python
destination_address = "bc1.."
amount_sat = current_fees.min
fee_hash = current_fees.fee_hash
sat_per_vbyte = <fee rate>

try:
  sdk_services.send_onchain(
    amount_sat=amount_msats,
    onchain_recipient_address="...",
    pair_hash=current_fees.fee_hash,
    sat_per_vbyte=sat_per_vbyte)
except Exception as error:
  # Handle erorr
Go
destinationAddress := "bc1.."
sendAmountSat := uint64(50000)
satPerVbyte := uint64(5)
if currentFees, err := sdk.FetchReverseSwapFees(breez_sdk.ReverseSwapFeesRequest{SendAmountSat: &sendAmountSat}); err == nil {
    if reverseSwapInfo, err := sdk.SendOnchain(sendAmountSat, destinationAddress, currentFees.FeesHash, satPerVbyte); err == nil {
        log.Printf("%#v", reverseSwapInfo)
    }
}
C#
var destinationAddress = "bc1..";
var amountSat = currentFees.min;
var satPerVbyte = <fee rate>;
try 
{
    var reverseSwapInfo = sdk.SendOnchain(
        amountSat, destinationAddress, currentFees.feesHash, satPerVbyte);
} 
catch (Exception) 
{
    // Handle error
}

Starting the reverse swap will trigger a HODL invoice payment, which will only be settled if the entire swap completes. This means you will see an outgoing pending payment in your list of payments, which locks those funds until the invoice is either settled or cancelled. This will happen automatically at the end of the reverse swap.

You can check its status with:

Rust
for rs in sdk.in_progress_reverse_swaps().await? {
    info!("Reverse swap {} in progress, status is {}", rs.id, rs.status);
}
Swift
for rs in sdk.inProgressReverseSwaps() {
  println("Reverse swap \(rs.id) in progress, status is \(rs.status)")
}
Android
for (rs in sdk.inProgressReverseSwaps()) {
    Log.v("Breez", "Reverse swap ${rs.id} in progress, status is ${rs.status}")
}
React Native
try {
    const swaps = await inProgressReverseSwaps()
    for (const swap in swaps) {
        println(`Reverse swap ${swap.id} in progress, status is ${swap.status}`);
    }
} catch (error) {
    console.log(error)
}
Dart
try {
    List<ReverseSwapInfo> swaps = await inProgressReverseSwaps();
    for (swap in swaps) {
        print(`Reverse swap ${swap.id} in progress, status is ${swap.status}`);
    }
} catch (error) {
    // handle error
}
Python
try: 
  reverse_swaps = sdk_services.in_progress_reverse_swaps()
  for rs in reverse_swaps:
    print("Reverse swap ",rs.id , " in progress, status is ", rs.status)
except Exception as error:
  # Handle erorr
Go
if swaps, err := sdk.InProgressReverseSwaps(); err == nil {
    for _, swap := range swaps {
        log.Printf("Reverse swap %v in progress, status is %v", swap.Id, swap.Status)
    }
}
C#
try 
{
    var swaps = sdk.InProgressReverseSwaps();
    foreach (var swap in swaps) {
        Console.WriteLine($"Reverse swap {swap.id} in progress, status is {swap.status}`");
    }
} 
catch (Exception) 
{
    // Handle error
}   

If the reverse swap is successful, you'll get the on-chain payment on your destination address and the HODL invoice will change from pending to settled.

If however something goes wrong at any point in the process, the initial HODL payment will be cancelled and the funds in your Breez SDK wallet will be unlocked.