mirror of
https://github.com/aljazceru/breez-sdk-liquid.git
synced 2025-12-23 17:04:25 +01:00
list-refundables: show refundable amount, not swap amount (#516)
* list-refundables: show refundable amount, not swap amount * Rename chainswap fn for clarity get_lockup_swap_script_pubkey only applies to Receive Chain Swaps, so it was renamed to get_receive_lockup_swap_script_pubkey. * list_refundables: batch calls to fetch balance from chain service * Simplify conversion from Chain Swap to RefundableSwap * Fix MockBitcoinChainService * Re-generate flutter bindings * Add utility for creating SdkError::Generic with &str or String * Chain Swap getter for swap script pk: throw SdkError instead of anyhow::Error * Update RefundableSwap comment Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com> * Re-generate dart files --------- Co-authored-by: Ross Savage <551697+dangeross@users.noreply.github.com>
This commit is contained in:
@@ -44,10 +44,7 @@ impl log::Log for UniffiBindingLogger {
|
|||||||
|
|
||||||
/// If used, this must be called before `connect`
|
/// If used, this must be called before `connect`
|
||||||
pub fn set_logger(logger: Box<dyn Logger>) -> Result<(), SdkError> {
|
pub fn set_logger(logger: Box<dyn Logger>) -> Result<(), SdkError> {
|
||||||
UniffiBindingLogger::init(logger).map_err(|_| SdkError::Generic {
|
UniffiBindingLogger::init(logger).map_err(|_| SdkError::generic("Logger already created"))
|
||||||
err: "Logger already created".into(),
|
|
||||||
})?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(req: ConnectRequest) -> Result<Arc<BindingLiquidSdk>, SdkError> {
|
pub fn connect(req: ConnectRequest) -> Result<Arc<BindingLiquidSdk>, SdkError> {
|
||||||
|
|||||||
@@ -54,9 +54,7 @@ pub async fn connect(req: ConnectRequest) -> Result<BindingLiquidSdk, SdkError>
|
|||||||
|
|
||||||
/// If used, this must be called before `connect`. It can only be called once.
|
/// If used, this must be called before `connect`. It can only be called once.
|
||||||
pub fn breez_log_stream(s: StreamSink<LogEntry>) -> Result<()> {
|
pub fn breez_log_stream(s: StreamSink<LogEntry>) -> Result<()> {
|
||||||
DartBindingLogger::init(s).map_err(|_| SdkError::Generic {
|
DartBindingLogger::init(s).map_err(|_| SdkError::generic("Log stream already created"))?;
|
||||||
err: "Log stream already created".into(),
|
|
||||||
})?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ pub trait BitcoinChainService: Send + Sync {
|
|||||||
/// Return the confirmed and unconfirmed balances of a script hash
|
/// Return the confirmed and unconfirmed balances of a script hash
|
||||||
fn script_get_balance(&self, script: &Script) -> Result<GetBalanceRes>;
|
fn script_get_balance(&self, script: &Script) -> Result<GetBalanceRes>;
|
||||||
|
|
||||||
|
/// Return the confirmed and unconfirmed balances of a list of script hashes
|
||||||
|
fn scripts_get_balance(&self, scripts: &[&Script]) -> Result<Vec<GetBalanceRes>>;
|
||||||
|
|
||||||
/// Verify that a transaction appears in the address script history
|
/// Verify that a transaction appears in the address script history
|
||||||
async fn verify_tx(
|
async fn verify_tx(
|
||||||
&self,
|
&self,
|
||||||
@@ -207,6 +210,10 @@ impl BitcoinChainService for HybridBitcoinChainService {
|
|||||||
Ok(self.client.script_get_balance(script)?)
|
Ok(self.client.script_get_balance(script)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scripts_get_balance(&self, scripts: &[&Script]) -> Result<Vec<GetBalanceRes>> {
|
||||||
|
Ok(self.client.batch_script_get_balance(scripts)?)
|
||||||
|
}
|
||||||
|
|
||||||
async fn verify_tx(
|
async fn verify_tx(
|
||||||
&self,
|
&self,
|
||||||
address: &Address,
|
address: &Address,
|
||||||
|
|||||||
@@ -142,11 +142,7 @@ impl ChainSwapHandler {
|
|||||||
let is_monitoring_expired = current_height > monitoring_block_height;
|
let is_monitoring_expired = current_height > monitoring_block_height;
|
||||||
|
|
||||||
if (is_swap_expired && !is_monitoring_expired) || swap.state == RefundPending {
|
if (is_swap_expired && !is_monitoring_expired) || swap.state == RefundPending {
|
||||||
let swap_script = swap.get_lockup_swap_script()?.as_bitcoin_script()?;
|
let script_pubkey = swap.get_receive_lockup_swap_script_pubkey(self.config.network)?;
|
||||||
let script_pubkey = swap_script
|
|
||||||
.to_address(self.config.network.as_bitcoin_chain())
|
|
||||||
.map_err(|e| anyhow!("Error getting script address: {e:?}"))?
|
|
||||||
.script_pubkey();
|
|
||||||
let script_balance = self
|
let script_balance = self
|
||||||
.bitcoin_chain_service
|
.bitcoin_chain_service
|
||||||
.lock()
|
.lock()
|
||||||
@@ -743,9 +739,9 @@ impl ChainSwapHandler {
|
|||||||
let swap = self
|
let swap = self
|
||||||
.persister
|
.persister
|
||||||
.fetch_chain_swap_by_lockup_address(lockup_address)?
|
.fetch_chain_swap_by_lockup_address(lockup_address)?
|
||||||
.ok_or(SdkError::Generic {
|
.ok_or(SdkError::generic(format!(
|
||||||
err: format!("Swap {} not found", lockup_address),
|
"Chain Swap with lockup address {lockup_address} not found"
|
||||||
})?;
|
)))?;
|
||||||
|
|
||||||
let refund_tx_id = swap.refund_tx_id.clone();
|
let refund_tx_id = swap.refund_tx_id.clone();
|
||||||
if let Some(refund_tx_id) = &refund_tx_id {
|
if let Some(refund_tx_id) = &refund_tx_id {
|
||||||
|
|||||||
@@ -28,31 +28,34 @@ pub enum SdkError {
|
|||||||
#[error("Service connectivity: {err}")]
|
#[error("Service connectivity: {err}")]
|
||||||
ServiceConnectivity { err: String },
|
ServiceConnectivity { err: String },
|
||||||
}
|
}
|
||||||
|
impl SdkError {
|
||||||
|
pub fn generic<T: AsRef<str>>(err: T) -> Self {
|
||||||
|
Self::Generic {
|
||||||
|
err: err.as_ref().to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<anyhow::Error> for SdkError {
|
impl From<anyhow::Error> for SdkError {
|
||||||
fn from(e: Error) -> Self {
|
fn from(e: Error) -> Self {
|
||||||
SdkError::Generic { err: e.to_string() }
|
SdkError::generic(e.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<boltz_client::error::Error> for SdkError {
|
impl From<boltz_client::error::Error> for SdkError {
|
||||||
fn from(err: boltz_client::error::Error) -> Self {
|
fn from(err: boltz_client::error::Error) -> Self {
|
||||||
match err {
|
match err {
|
||||||
boltz_client::error::Error::HTTP(e) => SdkError::Generic {
|
boltz_client::error::Error::HTTP(e) => {
|
||||||
err: format!("Could not contact servers: {e:?}"),
|
SdkError::generic(format!("Could not contact servers: {e:?}"))
|
||||||
},
|
}
|
||||||
_ => SdkError::Generic {
|
_ => SdkError::generic(format!("{err:?}")),
|
||||||
err: format!("{err:?}"),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<secp256k1::Error> for SdkError {
|
impl From<secp256k1::Error> for SdkError {
|
||||||
fn from(err: secp256k1::Error) -> Self {
|
fn from(err: secp256k1::Error) -> Self {
|
||||||
SdkError::Generic {
|
SdkError::generic(format!("{err:?}"))
|
||||||
err: format!("{err:?}"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::path::PathBuf;
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
|
||||||
use boltz_client::{
|
use boltz_client::{
|
||||||
|
bitcoin::ScriptBuf,
|
||||||
network::Chain,
|
network::Chain,
|
||||||
swaps::boltz::{
|
swaps::boltz::{
|
||||||
CreateChainResponse, CreateReverseResponse, CreateSubmarineResponse, Leaf, Side, SwapTree,
|
CreateChainResponse, CreateReverseResponse, CreateSubmarineResponse, Leaf, Side, SwapTree,
|
||||||
@@ -608,6 +609,27 @@ impl ChainSwap {
|
|||||||
Ok(swap_script)
|
Ok(swap_script)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the lockup script pubkey for Receive Chain Swaps
|
||||||
|
pub(crate) fn get_receive_lockup_swap_script_pubkey(
|
||||||
|
&self,
|
||||||
|
network: LiquidNetwork,
|
||||||
|
) -> SdkResult<ScriptBuf> {
|
||||||
|
let swap_script = self.get_lockup_swap_script()?.as_bitcoin_script()?;
|
||||||
|
let script_pubkey = swap_script
|
||||||
|
.to_address(network.as_bitcoin_chain())
|
||||||
|
.map_err(|e| SdkError::generic(format!("Error getting script address: {e:?}")))?
|
||||||
|
.script_pubkey();
|
||||||
|
Ok(script_pubkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn to_refundable(&self, refundable_amount_sat: u64) -> RefundableSwap {
|
||||||
|
RefundableSwap {
|
||||||
|
swap_address: self.lockup_address.clone(),
|
||||||
|
timestamp: self.created_at,
|
||||||
|
amount_sat: refundable_amount_sat,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn from_boltz_struct_to_json(
|
pub(crate) fn from_boltz_struct_to_json(
|
||||||
create_response: &CreateChainResponse,
|
create_response: &CreateChainResponse,
|
||||||
expected_swap_id: &str,
|
expected_swap_id: &str,
|
||||||
@@ -681,11 +703,11 @@ impl SendSwap {
|
|||||||
&self.get_boltz_create_response()?,
|
&self.get_boltz_create_response()?,
|
||||||
self.get_refund_keypair()?.public_key().into(),
|
self.get_refund_keypair()?.public_key().into(),
|
||||||
)
|
)
|
||||||
.map_err(|e| SdkError::Generic {
|
.map_err(|e| {
|
||||||
err: format!(
|
SdkError::generic(format!(
|
||||||
"Failed to create swap script for Send Swap {}: {e:?}",
|
"Failed to create swap script for Send Swap {}: {e:?}",
|
||||||
self.id
|
self.id
|
||||||
),
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -806,17 +828,9 @@ impl ReceiveSwap {
|
|||||||
pub struct RefundableSwap {
|
pub struct RefundableSwap {
|
||||||
pub swap_address: String,
|
pub swap_address: String,
|
||||||
pub timestamp: u32,
|
pub timestamp: u32,
|
||||||
|
/// Amount that is refundable, from all UTXOs
|
||||||
pub amount_sat: u64,
|
pub amount_sat: u64,
|
||||||
}
|
}
|
||||||
impl From<ChainSwap> for RefundableSwap {
|
|
||||||
fn from(swap: ChainSwap) -> Self {
|
|
||||||
Self {
|
|
||||||
swap_address: swap.lockup_address,
|
|
||||||
timestamp: swap.created_at,
|
|
||||||
amount_sat: swap.payer_amount_sat,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The payment state of an individual payment.
|
/// The payment state of an individual payment.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Hash)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Hash)]
|
||||||
|
|||||||
@@ -246,9 +246,7 @@ impl LiquidSdk {
|
|||||||
let mut is_started = self.is_started.write().await;
|
let mut is_started = self.is_started.write().await;
|
||||||
self.shutdown_sender
|
self.shutdown_sender
|
||||||
.send(())
|
.send(())
|
||||||
.map_err(|e| SdkError::Generic {
|
.map_err(|e| SdkError::generic(format!("Shutdown failed: {e}")))?;
|
||||||
err: format!("Shutdown failed: {e}"),
|
|
||||||
})?;
|
|
||||||
*is_started = false;
|
*is_started = false;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1740,12 +1738,34 @@ impl LiquidSdk {
|
|||||||
/// List all failed chain swaps that need to be refunded.
|
/// List all failed chain swaps that need to be refunded.
|
||||||
/// They can be refunded by calling [LiquidSdk::prepare_refund] then [LiquidSdk::refund].
|
/// They can be refunded by calling [LiquidSdk::prepare_refund] then [LiquidSdk::refund].
|
||||||
pub async fn list_refundables(&self) -> SdkResult<Vec<RefundableSwap>> {
|
pub async fn list_refundables(&self) -> SdkResult<Vec<RefundableSwap>> {
|
||||||
Ok(self
|
let chain_swaps = self.persister.list_refundable_chain_swaps()?;
|
||||||
.persister
|
|
||||||
.list_refundable_chain_swaps()?
|
let mut lockup_script_pubkeys = vec![];
|
||||||
.into_iter()
|
for swap in &chain_swaps {
|
||||||
.map(Into::into)
|
let script_pubkey = swap.get_receive_lockup_swap_script_pubkey(self.config.network)?;
|
||||||
.collect())
|
lockup_script_pubkeys.push(script_pubkey);
|
||||||
|
}
|
||||||
|
let lockup_scripts: Vec<&boltz_client::bitcoin::Script> = lockup_script_pubkeys
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.as_script())
|
||||||
|
.collect();
|
||||||
|
let scripts_balance = self
|
||||||
|
.bitcoin_chain_service
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.scripts_get_balance(&lockup_scripts)?;
|
||||||
|
|
||||||
|
let mut refundables = vec![];
|
||||||
|
for (chain_swap, script_balance) in chain_swaps.into_iter().zip(scripts_balance) {
|
||||||
|
let swap_id = &chain_swap.id;
|
||||||
|
let refundable_confirmed_sat = script_balance.confirmed;
|
||||||
|
info!("Incoming Chain Swap {swap_id} is refundable with {refundable_confirmed_sat} confirmed sats");
|
||||||
|
|
||||||
|
let refundable: RefundableSwap = chain_swap.to_refundable(refundable_confirmed_sat);
|
||||||
|
refundables.push(refundable);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(refundables)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepares to refund a failed chain swap by calculating the refund transaction size and absolute fee.
|
/// Prepares to refund a failed chain swap by calculating the refund transaction size and absolute fee.
|
||||||
@@ -2069,10 +2089,7 @@ impl LiquidSdk {
|
|||||||
.unwrap_or(self.persister.get_default_backup_path());
|
.unwrap_or(self.persister.get_default_backup_path());
|
||||||
ensure_sdk!(
|
ensure_sdk!(
|
||||||
backup_path.exists(),
|
backup_path.exists(),
|
||||||
SdkError::Generic {
|
SdkError::generic("Backup file does not exist").into()
|
||||||
err: "Backup file does not exist".to_string()
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
);
|
);
|
||||||
self.persister.restore_from_backup(backup_path)
|
self.persister.restore_from_backup(backup_path)
|
||||||
}
|
}
|
||||||
@@ -2121,12 +2138,10 @@ impl LiquidSdk {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let preimage_str = preimage
|
let preimage_str =
|
||||||
.clone()
|
preimage.clone().ok_or(LnUrlPayError::Generic {
|
||||||
.ok_or(SdkError::Generic {
|
|
||||||
err: "Payment successful but no preimage found".to_string(),
|
err: "Payment successful but no preimage found".to_string(),
|
||||||
})
|
})?;
|
||||||
.unwrap();
|
|
||||||
let preimage =
|
let preimage =
|
||||||
sha256::Hash::from_str(&preimage_str).map_err(|_| {
|
sha256::Hash::from_str(&preimage_str).map_err(|_| {
|
||||||
LnUrlPayError::Generic {
|
LnUrlPayError::Generic {
|
||||||
|
|||||||
@@ -34,21 +34,17 @@ impl BoltzSwapper {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Direction::Outgoing => {
|
Direction::Outgoing => {
|
||||||
return Err(SdkError::Generic {
|
return Err(SdkError::generic(format!(
|
||||||
err: format!(
|
"Cannot create Bitcoin refund wrapper for outgoing Chain swap {}",
|
||||||
"Cannot create Bitcoin refund wrapper for outgoing Chain swap {}",
|
swap.id
|
||||||
swap.id
|
)));
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(SdkError::Generic {
|
return Err(SdkError::generic(format!(
|
||||||
err: format!(
|
"Cannot create Bitcoin refund wrapper for swap {}",
|
||||||
"Cannot create Bitcoin refund wrapper for swap {}",
|
swap.id()
|
||||||
swap.id()
|
)));
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
Ok(refund_wrapper)
|
Ok(refund_wrapper)
|
||||||
@@ -64,28 +60,21 @@ impl BoltzSwapper {
|
|||||||
) -> Result<Transaction, SdkError> {
|
) -> Result<Transaction, SdkError> {
|
||||||
ensure_sdk!(
|
ensure_sdk!(
|
||||||
swap.direction == Direction::Incoming,
|
swap.direction == Direction::Incoming,
|
||||||
SdkError::Generic {
|
SdkError::generic("Cannot create BTC refund tx for outgoing Chain swaps.")
|
||||||
err: "Cannot create BTC refund tx for outgoing Chain swaps.".to_string()
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let address = Address::from_str(refund_address).map_err(|err| SdkError::Generic {
|
let address = Address::from_str(refund_address)
|
||||||
err: format!("Could not parse address: {err:?}"),
|
.map_err(|err| SdkError::generic(format!("Could not parse address: {err:?}")))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
ensure_sdk!(
|
ensure_sdk!(
|
||||||
address.is_valid_for_network(self.config.network.into()),
|
address.is_valid_for_network(self.config.network.into()),
|
||||||
SdkError::Generic {
|
SdkError::generic("Address network validation failed")
|
||||||
err: "Address network validation failed".to_string()
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let utxo = utxos
|
let utxo = utxos
|
||||||
.first()
|
.first()
|
||||||
.and_then(|utxo| utxo.as_bitcoin().cloned())
|
.and_then(|utxo| utxo.as_bitcoin().cloned())
|
||||||
.ok_or(SdkError::Generic {
|
.ok_or(SdkError::generic("No UTXO found"))?;
|
||||||
err: "No UTXO found".to_string(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let swap_script = swap.get_lockup_swap_script()?.as_bitcoin_script()?;
|
let swap_script = swap.get_lockup_swap_script()?.as_bitcoin_script()?;
|
||||||
let refund_tx = BtcSwapTx {
|
let refund_tx = BtcSwapTx {
|
||||||
|
|||||||
@@ -111,12 +111,10 @@ impl BoltzSwapper {
|
|||||||
let refund_wrapper = match swap {
|
let refund_wrapper = match swap {
|
||||||
Swap::Chain(swap) => match swap.direction {
|
Swap::Chain(swap) => match swap.direction {
|
||||||
Direction::Incoming => {
|
Direction::Incoming => {
|
||||||
return Err(SdkError::Generic {
|
return Err(SdkError::generic(format!(
|
||||||
err: format!(
|
"Cannot create Liquid refund wrapper for incoming Chain swap {}",
|
||||||
"Cannot create Liquid refund wrapper for incoming Chain swap {}",
|
swap.id
|
||||||
swap.id
|
)));
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Direction::Outgoing => {
|
Direction::Outgoing => {
|
||||||
let swap_script = swap.get_lockup_swap_script()?;
|
let swap_script = swap.get_lockup_swap_script()?;
|
||||||
@@ -140,12 +138,10 @@ impl BoltzSwapper {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Swap::Receive(swap) => {
|
Swap::Receive(swap) => {
|
||||||
return Err(SdkError::Generic {
|
return Err(SdkError::generic(format!(
|
||||||
err: format!(
|
"Cannot create Liquid refund wrapper for Receive swap {}",
|
||||||
"Cannot create Liquid refund wrapper for Receive swap {}",
|
swap.id
|
||||||
swap.id
|
)));
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
Ok(refund_wrapper)
|
Ok(refund_wrapper)
|
||||||
@@ -162,9 +158,7 @@ impl BoltzSwapper {
|
|||||||
Swap::Chain(swap) => {
|
Swap::Chain(swap) => {
|
||||||
ensure_sdk!(
|
ensure_sdk!(
|
||||||
swap.direction == Direction::Outgoing,
|
swap.direction == Direction::Outgoing,
|
||||||
SdkError::Generic {
|
SdkError::generic("Cannot create LBTC refund tx for incoming Chain swaps")
|
||||||
err: "Cannot create LBTC refund tx for incoming Chain swaps".to_string()
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
(
|
(
|
||||||
@@ -179,25 +173,23 @@ impl BoltzSwapper {
|
|||||||
Preimage::new(),
|
Preimage::new(),
|
||||||
),
|
),
|
||||||
Swap::Receive(_) => {
|
Swap::Receive(_) => {
|
||||||
return Err(SdkError::Generic {
|
return Err(SdkError::generic(
|
||||||
err: "Cannot create LBTC refund tx for Receive swaps.".to_string(),
|
"Cannot create LBTC refund tx for Receive swaps.",
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let swap_id = swap.id();
|
let swap_id = swap.id();
|
||||||
|
|
||||||
let address = Address::from_str(refund_address).map_err(|err| SdkError::Generic {
|
let address = Address::from_str(refund_address)
|
||||||
err: format!("Could not parse address: {err:?}"),
|
.map_err(|err| SdkError::generic(format!("Could not parse address: {err:?}")))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
let genesis_hash = liquid_genesis_hash(&self.liquid_electrum_config)?;
|
let genesis_hash = liquid_genesis_hash(&self.liquid_electrum_config)?;
|
||||||
|
|
||||||
let (funding_outpoint, funding_tx_out) = *utxos
|
let (funding_outpoint, funding_tx_out) =
|
||||||
.first()
|
*utxos
|
||||||
.and_then(|utxo| utxo.as_liquid())
|
.first()
|
||||||
.ok_or(SdkError::Generic {
|
.and_then(|utxo| utxo.as_liquid())
|
||||||
err: "No refundable UTXOs found".to_string(),
|
.ok_or(SdkError::generic("No refundable UTXOs found"))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
let refund_tx = LBtcSwapTx {
|
let refund_tx = LBtcSwapTx {
|
||||||
kind: SwapTxKind::Refund,
|
kind: SwapTxKind::Refund,
|
||||||
|
|||||||
@@ -297,12 +297,10 @@ impl Swapper for BoltzSwapper {
|
|||||||
),
|
),
|
||||||
Swap::Send(swap) => (swap.get_refund_keypair()?, Preimage::new()),
|
Swap::Send(swap) => (swap.get_refund_keypair()?, Preimage::new()),
|
||||||
Swap::Receive(swap) => {
|
Swap::Receive(swap) => {
|
||||||
return Err(SdkError::Generic {
|
return Err(SdkError::generic(format!(
|
||||||
err: format!(
|
"Failed to retrieve refund keypair and preimage for Receive swap {}: invalid swap type",
|
||||||
"Failed to retrieve refund keypair and preimage for Receive swap {}: invalid swap type",
|
swap.id
|
||||||
swap.id
|
)));
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use boltz_client::{
|
|||||||
Amount,
|
Amount,
|
||||||
};
|
};
|
||||||
use electrum_client::bitcoin::{consensus::deserialize, OutPoint, Script, TxOut};
|
use electrum_client::bitcoin::{consensus::deserialize, OutPoint, Script, TxOut};
|
||||||
|
use electrum_client::GetBalanceRes;
|
||||||
use lwk_wollet::{
|
use lwk_wollet::{
|
||||||
elements::{BlockHash, Txid as ElementsTxid},
|
elements::{BlockHash, Txid as ElementsTxid},
|
||||||
History,
|
History,
|
||||||
@@ -188,6 +189,10 @@ impl BitcoinChainService for MockBitcoinChainService {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scripts_get_balance(&self, _scripts: &[&Script]) -> Result<Vec<GetBalanceRes>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
async fn verify_tx(
|
async fn verify_tx(
|
||||||
&self,
|
&self,
|
||||||
_address: &boltz_client::Address,
|
_address: &boltz_client::Address,
|
||||||
|
|||||||
@@ -1047,6 +1047,8 @@ class RefundResponse {
|
|||||||
class RefundableSwap {
|
class RefundableSwap {
|
||||||
final String swapAddress;
|
final String swapAddress;
|
||||||
final int timestamp;
|
final int timestamp;
|
||||||
|
|
||||||
|
/// Amount that is refundable, from all UTXOs
|
||||||
final BigInt amountSat;
|
final BigInt amountSat;
|
||||||
|
|
||||||
const RefundableSwap({
|
const RefundableSwap({
|
||||||
|
|||||||
Reference in New Issue
Block a user