use std::future::Future;
use std::sync::Arc;
use lwk_wollet::bitcoin::bip32::KeySource;
use lwk_wollet::bitcoin::PublicKey;
use lwk_wollet::elements::pset::PartiallySignedTransaction;
use lwk_wollet::elements::{AssetId, OutPoint, Script, Transaction, TxOut, TxOutSecrets, Txid};
use lwk_wollet::secp256k1::schnorr::Signature;
use lwk_wollet::secp256k1::{Message, XOnlyPublicKey};
use lwk_wollet::{BlindingPublicKey, ExternalUtxo};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WalletOutputTemplate {
pub script_pubkey: Script,
pub blinding_pubkey: Option<BlindingPublicKey>,
}
#[derive(Debug, Clone)]
pub struct WalletRequestSession {
pub session_id: String,
pub network: lwk_common::Network,
pub spendable_utxos: Arc<[ExternalUtxo]>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WalletOutputRequest {
Receive {
index: u32,
},
Change {
index: u32,
asset_id: AssetId,
},
}
pub struct WalletRuntimeDeps<SessionFactory, WalletProvider> {
pub session_factory: SessionFactory,
pub wallet_provider: WalletProvider,
}
impl<SessionFactory, WalletProvider> WalletRuntimeDeps<SessionFactory, WalletProvider> {
pub fn new(session_factory: SessionFactory, wallet_provider: WalletProvider) -> Self {
Self {
session_factory,
wallet_provider,
}
}
}
pub trait KeyStoreMeta {
type Error: std::error::Error + Send + Sync + 'static;
fn get_raw_signing_x_only_pubkey(&self) -> Result<XOnlyPublicKey, Self::Error>;
fn sign_pst(&self, pst: &mut PartiallySignedTransaction) -> Result<(), Self::Error>;
fn sign_schnorr(
&self,
message: Message,
xonly_public_key: XOnlyPublicKey,
) -> Result<Signature, Self::Error>;
}
pub trait WalletSessionFactory {
type Error: std::error::Error + Send + Sync + 'static;
fn open_wallet_request_session(
&self,
) -> impl Future<Output = Result<WalletRequestSession, Self::Error>> + Send + '_;
}
pub trait WalletProviderMeta {
type Error: std::error::Error + Send + Sync + 'static;
fn get_bip32_derivation_pair(
&self,
out_point: &OutPoint,
) -> Result<Option<(PublicKey, KeySource)>, Self::Error>;
fn unblind(&self, tx_out: &TxOut) -> Result<TxOutSecrets, Self::Error>;
fn get_tx_out(
&self,
outpoint: OutPoint,
) -> impl Future<Output = Result<TxOut, Self::Error>> + Send + '_;
fn get_wallet_output_template(
&self,
session: &WalletRequestSession,
request: &WalletOutputRequest,
) -> Result<WalletOutputTemplate, Self::Error>;
fn broadcast_transaction(
&self,
tx: &Transaction,
) -> impl Future<Output = Result<Txid, Self::Error>> + Send + '_;
}
impl<T> KeyStoreMeta for Arc<T>
where
T: KeyStoreMeta + ?Sized,
{
type Error = T::Error;
fn get_raw_signing_x_only_pubkey(&self) -> Result<XOnlyPublicKey, Self::Error> {
self.as_ref().get_raw_signing_x_only_pubkey()
}
fn sign_pst(&self, pst: &mut PartiallySignedTransaction) -> Result<(), Self::Error> {
self.as_ref().sign_pst(pst)
}
fn sign_schnorr(
&self,
message: Message,
xonly_public_key: XOnlyPublicKey,
) -> Result<Signature, Self::Error> {
self.as_ref().sign_schnorr(message, xonly_public_key)
}
}
impl<T> WalletSessionFactory for Arc<T>
where
T: WalletSessionFactory + ?Sized,
{
type Error = T::Error;
fn open_wallet_request_session(
&self,
) -> impl Future<Output = Result<WalletRequestSession, Self::Error>> + Send + '_ {
self.as_ref().open_wallet_request_session()
}
}
impl<T> WalletProviderMeta for Arc<T>
where
T: WalletProviderMeta + ?Sized,
{
type Error = T::Error;
fn get_bip32_derivation_pair(
&self,
out_point: &OutPoint,
) -> Result<Option<(PublicKey, KeySource)>, Self::Error> {
self.as_ref().get_bip32_derivation_pair(out_point)
}
fn unblind(&self, tx_out: &TxOut) -> Result<TxOutSecrets, Self::Error> {
self.as_ref().unblind(tx_out)
}
fn get_tx_out(
&self,
outpoint: OutPoint,
) -> impl Future<Output = Result<TxOut, Self::Error>> + Send + '_ {
self.as_ref().get_tx_out(outpoint)
}
fn get_wallet_output_template(
&self,
session: &WalletRequestSession,
request: &WalletOutputRequest,
) -> Result<WalletOutputTemplate, Self::Error> {
self.as_ref().get_wallet_output_template(session, request)
}
fn broadcast_transaction(
&self,
tx: &Transaction,
) -> impl Future<Output = Result<Txid, Self::Error>> + Send + '_ {
self.as_ref().broadcast_transaction(tx)
}
}