From d22510f80f91333ed888a1d6a43647ed525ecdb2 Mon Sep 17 00:00:00 2001 From: BitcoinZavior Date: Sat, 2 Nov 2024 13:40:32 -0400 Subject: [PATCH] feat: expose policy::satisfaction --- bdk-ffi/src/bdk.udl | 15 +++++++ bdk-ffi/src/lib.rs | 2 + bdk-ffi/src/types.rs | 101 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index a66de378..898c2cfd 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -452,6 +452,8 @@ interface Policy { boolean requires_path(); SatisfiableItem item(); + + Satisfaction satisfaction(); }; [Enum] @@ -481,6 +483,19 @@ interface LockTime { Seconds(u32 consensus_time); }; +[Enum] +interface Satisfaction { + Partial(u64 n, u64 m, sequence items, boolean? sorted, record> conditions); + PartialComplete(u64 n, u64 m, sequence items, boolean? sorted, record, sequence> conditions); + Complete(Condition condition); + None(string msg); +}; + +dictionary Condition { + u32? csv; + LockTime? timelock; +}; + interface TxBuilder { constructor(); diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index 2d462611..2a082439 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -51,6 +51,7 @@ use crate::types::Balance; use crate::types::BlockId; use crate::types::CanonicalTx; use crate::types::ChainPosition; +use crate::types::Condition; use crate::types::ConfirmationBlockTime; use crate::types::FullScanRequest; use crate::types::FullScanRequestBuilder; @@ -60,6 +61,7 @@ use crate::types::LocalOutput; use crate::types::LockTime; use crate::types::PkOrF; use crate::types::Policy; +use crate::types::Satisfaction; use crate::types::SatisfiableItem; use crate::types::ScriptAmount; use crate::types::SentAndReceivedValues; diff --git a/bdk-ffi/src/types.rs b/bdk-ffi/src/types.rs index 9a3800dd..654606b4 100644 --- a/bdk-ffi/src/types.rs +++ b/bdk-ffi/src/types.rs @@ -19,13 +19,15 @@ use bdk_wallet::chain::{ }; use bdk_wallet::descriptor::policy::{ - PkOrF as BdkPkOrF, Policy as BdkPolicy, SatisfiableItem as BdkSatisfiableItem, + Condition as BdkCondition, PkOrF as BdkPkOrF, Policy as BdkPolicy, + Satisfaction as BdkSatisfaction, SatisfiableItem as BdkSatisfiableItem, }; use bdk_wallet::AddressInfo as BdkAddressInfo; use bdk_wallet::Balance as BdkBalance; use bdk_wallet::KeychainKind; use bdk_wallet::LocalOutput as BdkLocalOutput; use bdk_wallet::Update as BdkUpdate; +use std::collections::HashMap; use std::sync::{Arc, Mutex}; #[derive(Debug)] @@ -268,9 +270,14 @@ impl Policy { pub fn requires_path(&self) -> bool { self.0.requires_path() } + pub fn item(&self) -> SatisfiableItem { self.0.item.clone().into() } + + pub fn satisfaction(&self) -> Satisfaction { + self.0.satisfaction.clone().into() + } } #[derive(Debug, Clone)] @@ -393,3 +400,95 @@ impl From for LockTime { } } } +#[derive(Debug, Clone)] +pub enum Satisfaction { + Partial { + n: u64, + m: u64, + items: Vec, + sorted: Option, + conditions: HashMap>, + }, + PartialComplete { + n: u64, + m: u64, + items: Vec, + sorted: Option, + conditions: HashMap, Vec>, + }, + Complete { + condition: Condition, + }, + + None { + msg: String, + }, +} +impl From for Satisfaction { + fn from(value: BdkSatisfaction) -> Self { + match value { + BdkSatisfaction::Partial { + n, + m, + items, + sorted, + conditions, + } => Satisfaction::Partial { + n: n as u64, + m: m as u64, + items: items.iter().map(|e| e.to_owned() as u64).collect(), + sorted, + conditions: conditions + .into_iter() + .map(|(index, conditions)| { + ( + index as u32, + conditions.into_iter().map(|e| e.into()).collect(), + ) + }) + .collect(), + }, + BdkSatisfaction::PartialComplete { + n, + m, + items, + sorted, + conditions, + } => Satisfaction::PartialComplete { + n: n as u64, + m: m as u64, + items: items.iter().map(|e| e.to_owned() as u64).collect(), + sorted, + conditions: conditions + .into_iter() + .map(|(index, conditions)| { + ( + index.iter().map(|e| e.to_owned() as u32).collect(), + conditions.into_iter().map(|e| e.into()).collect(), // Convert each `Condition` to `YourType` + ) + }) + .collect(), + }, + BdkSatisfaction::Complete { condition } => Satisfaction::Complete { + condition: condition.into(), + }, + BdkSatisfaction::None => Satisfaction::None { + msg: "Cannot satisfy or contribute to the policy item".to_string(), + }, + } + } +} + +#[derive(Debug, Clone)] +pub struct Condition { + pub csv: Option, + pub timelock: Option, +} +impl From for Condition { + fn from(value: BdkCondition) -> Self { + Condition { + csv: value.csv.map(|e| e.to_consensus_u32()), + timelock: value.timelock.map(|e| e.into()), + } + } +}