Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add onchain_amount_sat field to received swaps #41

Merged
merged 1 commit into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@ use std::borrow::Cow::{self, Owned};
use std::sync::Arc;

use anyhow::Result;
use clap::Parser;
use clap::{arg, Parser};
use rustyline::highlight::Highlighter;
use rustyline::history::DefaultHistory;
use rustyline::Editor;
use rustyline::{hint::HistoryHinter, Completer, Helper, Hinter, Validator};

use breez_sdk_liquid::Wallet;
use breez_sdk_liquid::{ReceivePaymentRequest, Wallet};

#[derive(Parser, Debug, Clone, PartialEq)]
pub(crate) enum Command {
/// Send lbtc and receive btc through a swap
SendPayment { bolt11: String },
/// Receive lbtc and send btc through a swap
ReceivePayment { amount_sat: u64 },
ReceivePayment {
#[arg(short, long)]
onchain_amount_sat: Option<u64>,

#[arg(short, long)]
invoice_amount_sat: Option<u64>,
},
/// List incoming and outgoing payments
ListPayments,
/// Get the balance of the currently loaded wallet
Expand All @@ -40,8 +46,14 @@ pub(crate) async fn handle_command(
command: Command,
) -> Result<String> {
match command {
Command::ReceivePayment { amount_sat } => {
let response = wallet.receive_payment(amount_sat)?;
Command::ReceivePayment {
onchain_amount_sat,
invoice_amount_sat,
} => {
let response = wallet.receive_payment(ReceivePaymentRequest {
invoice_amount_sat,
onchain_amount_sat,
})?;
dbg!(&response);
Ok(format!(
"Please pay the following invoice: {}",
Expand Down
7 changes: 5 additions & 2 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod tests {
use anyhow::Result;
use bip39::{Language, Mnemonic};

use crate::Wallet;
use crate::{ReceivePaymentRequest, Wallet};

const DEFAULT_DATA_DIR: &str = ".data";
const PHRASE_FILE_NAME: &str = "phrase";
Expand Down Expand Up @@ -58,7 +58,10 @@ mod tests {
fn reverse_submarine_swap_success() -> Result<()> {
let breez_wallet = Wallet::init(get_mnemonic()?.to_string())?;

let swap_response = breez_wallet.receive_payment(1000)?;
let swap_response = breez_wallet.receive_payment(ReceivePaymentRequest {
onchain_amount_sat: Some(1000),
invoice_amount_sat: None,
})?;

println!(
"Please pay the following invoice: {}",
Expand Down
18 changes: 17 additions & 1 deletion lib/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ impl ToString for SwapStatus {
}
}

pub struct ReceivePaymentRequest {
pub invoice_amount_sat: Option<u64>,
pub onchain_amount_sat: Option<u64>,
}

pub struct SendPaymentResponse {
pub txid: String,
}
Expand Down Expand Up @@ -104,12 +109,23 @@ pub struct WalletInfo {
pub active_address: String,
}

pub struct OngoingSwap {
#[derive(Debug)]
pub struct OngoingReceiveSwap {
pub id: String,
pub preimage: String,
pub redeem_script: String,
pub blinding_key: String,
pub invoice_amount_sat: u64,
pub onchain_amount_sat: u64,
}

pub struct OngoingSendSwap {
pub id: String,
// pub preimage: String,
// pub redeem_script: String,
// pub blinding_key: String,
// pub invoice_amount_sat: Option<u64>,
// pub onchain_amount_sat: Option<u64>,
}

pub enum PaymentType {
Expand Down
3 changes: 2 additions & 1 deletion lib/src/persist/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ pub(crate) fn current_migrations() -> Vec<&'static str> {
preimage TEXT NOT NULL,
redeem_script TEXT NOT NULL,
blinding_key TEXT NOT NULL,
invoice_amount_sat INTEGER
invoice_amount_sat INTEGER NOT NULL,
onchain_amount_sat INTEGER NOT NULL
) STRICT;",
]
}
19 changes: 11 additions & 8 deletions lib/src/persist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use anyhow::Result;
use rusqlite::{params, Connection, Row};
use rusqlite_migration::{Migrations, M};

use crate::OngoingSwap;
use crate::OngoingReceiveSwap;

use migrations::current_migrations;

Expand Down Expand Up @@ -35,7 +35,7 @@ impl Persister {
Ok(())
}

pub fn insert_ongoing_swaps(&self, swaps: &[OngoingSwap]) -> Result<()> {
pub fn insert_ongoing_swaps(&self, swaps: &[OngoingReceiveSwap]) -> Result<()> {
let con = self.get_connection()?;

let mut stmt = con.prepare(
Expand All @@ -45,9 +45,10 @@ impl Persister {
preimage,
redeem_script,
blinding_key,
invoice_amount_sat
invoice_amount_sat,
onchain_amount_sat
)
VALUES (?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?)
",
)?;

Expand All @@ -58,6 +59,7 @@ impl Persister {
&swap.redeem_script,
&swap.blinding_key,
&swap.invoice_amount_sat,
&swap.onchain_amount_sat,
))?
}

Expand All @@ -73,26 +75,27 @@ impl Persister {
Ok(())
}

pub fn list_ongoing_swaps(&self) -> Result<Vec<OngoingSwap>> {
pub fn list_ongoing_swaps(&self) -> Result<Vec<OngoingReceiveSwap>> {
let con = self.get_connection()?;

let mut stmt = con.prepare("SELECT * FROM ongoing_swaps")?;

let swaps: Vec<OngoingSwap> = stmt
let swaps: Vec<OngoingReceiveSwap> = stmt
.query_map(params![], |row| self.sql_row_to_swap(row))?
.map(|i| i.unwrap())
.collect();

Ok(swaps)
}

fn sql_row_to_swap(&self, row: &Row) -> Result<OngoingSwap, rusqlite::Error> {
Ok(OngoingSwap {
fn sql_row_to_swap(&self, row: &Row) -> Result<OngoingReceiveSwap, rusqlite::Error> {
Ok(OngoingReceiveSwap {
id: row.get(0)?,
preimage: row.get(1)?,
redeem_script: row.get(2)?,
blinding_key: row.get(3)?,
invoice_amount_sat: row.get(4)?,
onchain_amount_sat: row.get(5)?,
})
}
}
65 changes: 43 additions & 22 deletions lib/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use lwk_wollet::{
};

use crate::{
persist::Persister, Network, OngoingSwap, Payment, PaymentType, SendPaymentResponse, SwapError,
SwapLbtcResponse, WalletInfo, WalletOptions,
persist::Persister, Network, OngoingReceiveSwap, Payment, PaymentType, ReceivePaymentRequest,
SendPaymentResponse, SwapError, SwapLbtcResponse, WalletInfo, WalletOptions,
};

// To avoid sendrawtransaction error "min relay fee not met"
Expand Down Expand Up @@ -107,7 +107,7 @@ impl Wallet {
thread::scope(|scope| {
for swap in ongoing_swaps {
scope.spawn(|| {
let OngoingSwap {
let OngoingReceiveSwap {
preimage,
redeem_script,
blinding_key,
Expand Down Expand Up @@ -273,12 +273,18 @@ impl Wallet {
)?;
let txid = rev_swap_tx.broadcast(signed_tx, network_config)?;

debug!("Funds claimed successfully! Txid: {txid}");

Ok(txid)
}

pub fn receive_payment(&self, amount_sat: u64) -> Result<SwapLbtcResponse, SwapError> {
pub fn receive_payment(
&self,
req: ReceivePaymentRequest,
) -> Result<SwapLbtcResponse, SwapError> {
let mut amount_sat = req
.onchain_amount_sat
.or(req.invoice_amount_sat)
.ok_or(SwapError::AmountOutOfRange)?;

let client = self.boltz_client();

let lbtc_pair = client.get_pairs()?.get_lbtc_pair()?;
Expand All @@ -297,12 +303,22 @@ impl Wallet {
let preimage_str = preimage.to_string().ok_or(SwapError::InvalidPreimage)?;
let preimage_hash = preimage.sha256.to_string();

let swap_response = client.create_swap(CreateSwapRequest::new_lbtc_reverse_invoice_amt(
lbtc_pair.hash,
preimage_hash.clone(),
lsk.keypair.public_key().to_string(),
amount_sat,
))?;
let swap_response = if req.onchain_amount_sat.is_some() {
amount_sat += CLAIM_ABSOLUTE_FEES;
client.create_swap(CreateSwapRequest::new_lbtc_reverse_onchain_amt(
lbtc_pair.hash,
preimage_hash.clone(),
lsk.keypair.public_key().to_string(),
amount_sat,
))?
} else {
client.create_swap(CreateSwapRequest::new_lbtc_reverse_invoice_amt(
lbtc_pair.hash,
preimage_hash.clone(),
lsk.keypair.public_key().to_string(),
amount_sat,
))?
};

let swap_id = swap_response.get_id();
let invoice = swap_response.get_invoice()?;
Expand All @@ -311,24 +327,29 @@ impl Wallet {

// Double check that the generated invoice includes our data
// https://docs.boltz.exchange/v/api/dont-trust-verify#lightning-invoice-verification
if invoice.payment_hash().to_string() != preimage_hash
|| invoice
.amount_milli_satoshis()
.ok_or(SwapError::InvalidInvoice)?
/ 1000
!= amount_sat
{
if invoice.payment_hash().to_string() != preimage_hash {
return Err(SwapError::InvalidInvoice);
};

let invoice_amount_sat = invoice
.amount_milli_satoshis()
.ok_or(SwapError::InvalidInvoice)?
/ 1000;

self.swap_persister
.insert_ongoing_swaps(&[OngoingSwap {
.insert_ongoing_swaps(dbg!(&[OngoingReceiveSwap {
id: swap_id.clone(),
preimage: preimage_str,
blinding_key: blinding_str,
redeem_script,
invoice_amount_sat: amount_sat,
}])
invoice_amount_sat,
onchain_amount_sat: req.onchain_amount_sat.unwrap_or(
invoice_amount_sat
- lbtc_pair.fees.reverse_boltz(invoice_amount_sat)?
- lbtc_pair.fees.reverse_lockup()?
- CLAIM_ABSOLUTE_FEES
),
}]))
.map_err(|_| SwapError::PersistError)?;

Ok(SwapLbtcResponse {
Expand Down