diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 57c7a19..8956163 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -176,6 +176,11 @@ interface PsbtParseError { Base64Encoding(string error_message); }; +[Error] +interface InspectError { + RequestAlreadyConsumed(); +}; + [Error] interface SignerError { MissingKey(); @@ -274,9 +279,23 @@ dictionary CanonicalTx { ChainPosition chain_position; }; -interface FullScanRequest {}; +interface FullScanRequest { + [Throws=InspectError] + FullScanRequest inspect_spks_for_all_keychains(FullScanScriptInspector inspector); +}; -interface SyncRequest {}; +interface SyncRequest { + [Throws=InspectError] + SyncRequest inspect_spks(SyncScriptInspector inspector); +}; + +callback interface SyncScriptInspector { + void inspect(Script script, u64 total); +}; + +callback interface FullScanScriptInspector { + void inspect(KeychainKind keychain, u32 index, Script script); +}; // ------------------------------------------------------------------------ // bdk crate - wallet module diff --git a/bdk-ffi/src/error.rs b/bdk-ffi/src/error.rs index 2c91d6a..379f2f8 100644 --- a/bdk-ffi/src/error.rs +++ b/bdk-ffi/src/error.rs @@ -375,6 +375,12 @@ pub enum FeeRateError { ArithmeticOverflow, } +#[derive(Debug, thiserror::Error)] +pub enum InspectError { + #[error("the request has already been consumed")] + RequestAlreadyConsumed, +} + #[derive(Debug, thiserror::Error)] pub enum ParseAmountError { #[error("amount is negative")] @@ -1080,8 +1086,8 @@ mod test { use crate::error::{ AddressError, Bip32Error, Bip39Error, CannotConnectError, CreateTxError, DescriptorError, DescriptorKeyError, ElectrumError, EsploraError, ExtractTxError, FeeRateError, - ParseAmountError, PersistenceError, PsbtParseError, TransactionError, TxidParseError, - WalletCreationError, + InspectError, ParseAmountError, PersistenceError, PsbtParseError, TransactionError, + TxidParseError, WalletCreationError, }; use crate::CalculateFeeError; use crate::OutPoint; @@ -1671,6 +1677,18 @@ mod test { } } + #[test] + fn test_error_inspect() { + let cases = vec![( + InspectError::RequestAlreadyConsumed, + "the request has already been consumed", + )]; + + for (error, expected_message) in cases { + assert_eq!(error.to_string(), expected_message); + } + } + #[test] fn test_error_parse_amount() { let cases = vec![ diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index 4e23353..e0b05dd 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -30,6 +30,7 @@ use crate::error::ElectrumError; use crate::error::EsploraError; use crate::error::ExtractTxError; use crate::error::FeeRateError; +use crate::error::InspectError; use crate::error::ParseAmountError; use crate::error::PersistenceError; use crate::error::PsbtParseError; @@ -47,9 +48,11 @@ use crate::types::Balance; use crate::types::CanonicalTx; use crate::types::ChainPosition; use crate::types::FullScanRequest; +use crate::types::FullScanScriptInspector; use crate::types::LocalOutput; use crate::types::ScriptAmount; use crate::types::SyncRequest; +use crate::types::SyncScriptInspector; use crate::wallet::BumpFeeTxBuilder; use crate::wallet::SentAndReceivedValues; use crate::wallet::TxBuilder; diff --git a/bdk-ffi/src/types.rs b/bdk-ffi/src/types.rs index 2127e4b..778abe7 100644 --- a/bdk-ffi/src/types.rs +++ b/bdk-ffi/src/types.rs @@ -1,5 +1,6 @@ use crate::bitcoin::{Address, OutPoint, Script, Transaction, TxOut}; +use bdk::bitcoin::ScriptBuf as BdkScriptBuf; use bdk::chain::spk_client::FullScanRequest as BdkFullScanRequest; use bdk::chain::spk_client::SyncRequest as BdkSyncRequest; use bdk::chain::tx_graph::CanonicalTx as BdkCanonicalTx; @@ -12,6 +13,7 @@ use bdk::LocalOutput as BdkLocalOutput; use std::sync::{Arc, Mutex}; use crate::bitcoin::Amount; +use crate::error::InspectError; #[derive(Debug, Clone, PartialEq, Eq)] pub enum ChainPosition { @@ -112,6 +114,55 @@ impl From for LocalOutput { } } +// Callback for the FullScanRequest +pub trait FullScanScriptInspector: Sync + Send { + fn inspect(&self, keychain: KeychainKind, index: u32, script: Arc