Skip to main content

rgb/
wallet.rs

1// RGB API library for smart contracts on Bitcoin & Lightning network
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2023 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22#[cfg(feature = "fs")]
23use std::path::PathBuf;
24
25#[cfg(all(feature = "fs", feature = "bp"))]
26use bpwallet::fs::FsTextStore;
27#[cfg(all(feature = "fs", feature = "bp"))]
28use bpwallet::Wallet;
29#[cfg(all(not(target_arch = "wasm32"), feature = "fs"))]
30use nonasync::persistence::PersistenceProvider;
31use psrgbt::{RgbOutExt, RgbPropKeyExt};
32use rgbstd::containers::Transfer;
33use rgbstd::contract::ContractOp;
34#[cfg(feature = "fs")]
35use rgbstd::persistence::fs::FsBinStore;
36use rgbstd::persistence::{
37    IndexProvider, MemIndex, MemStash, MemState, StashProvider, StateProvider, Stock, StockError,
38};
39
40use super::{
41    CompletionError, CompositionError, ContractId, PayError, TransferParams, WalletProvider,
42};
43#[cfg(all(feature = "fs", feature = "bp"))]
44use super::{DescriptorRgb, WalletError};
45use crate::invoice::RgbInvoice;
46use crate::pay::PsbtMeta;
47
48#[derive(Getters)]
49pub struct RgbWallet<
50    W: WalletProvider,
51    S: StashProvider = MemStash,
52    H: StateProvider = MemState,
53    I: IndexProvider = MemIndex,
54> {
55    stock: Stock<S, H, I>,
56    wallet: W,
57}
58
59#[cfg(all(feature = "fs", feature = "bp"))]
60impl<
61        K,
62        D: DescriptorRgb + bpwallet::Descriptor<K>,
63        S: StashProvider,
64        H: StateProvider,
65        I: IndexProvider,
66    > RgbWallet<Wallet<K, D>, S, H, I>
67{
68    #[allow(clippy::result_large_err)]
69    pub fn load(
70        stock_path: PathBuf,
71        wallet_path: PathBuf,
72        autosave: bool,
73    ) -> Result<Self, WalletError>
74    where
75        D: serde::Serialize + for<'de> serde::Deserialize<'de>,
76        FsBinStore: PersistenceProvider<S>,
77        FsBinStore: PersistenceProvider<H>,
78        FsBinStore: PersistenceProvider<I>,
79    {
80        use nonasync::persistence::PersistenceError;
81        let provider = FsBinStore::new(stock_path)
82            .map_err(|e| WalletError::StockPersist(PersistenceError::with(e)))?;
83        let stock = Stock::load(provider, autosave).map_err(WalletError::StockPersist)?;
84        let provider = FsTextStore::new(wallet_path)
85            .map_err(|e| WalletError::WalletPersist(PersistenceError::with(e)))?;
86        let wallet = Wallet::load(provider, autosave).map_err(WalletError::WalletPersist)?;
87        Ok(Self { wallet, stock })
88    }
89}
90
91impl<W: WalletProvider, S: StashProvider, H: StateProvider, I: IndexProvider>
92    RgbWallet<W, S, H, I>
93{
94    pub fn new(stock: Stock<S, H, I>, wallet: W) -> Self { Self { stock, wallet } }
95
96    pub fn stock_mut(&mut self) -> &mut Stock<S, H, I> { &mut self.stock }
97
98    pub fn wallet_mut(&mut self) -> &mut W { &mut self.wallet }
99
100    pub fn history(&self, contract_id: ContractId) -> Result<Vec<ContractOp>, StockError<S, H, I>> {
101        let contract = self.stock.contract_data(contract_id)?;
102        let wallet = &self.wallet;
103        Ok(contract.history(wallet.filter_outpoints(), wallet.filter_witnesses()))
104    }
105
106    #[allow(clippy::result_large_err)]
107    pub fn pay<P: RgbPropKeyExt, O: RgbOutExt<P>>(
108        &mut self,
109        invoice: &RgbInvoice,
110        params: TransferParams,
111    ) -> Result<(W::Psbt, PsbtMeta, Transfer), PayError> {
112        self.wallet
113            .pay::<S, H, I, P, O>(&mut self.stock, invoice, params)
114    }
115
116    #[allow(clippy::result_large_err)]
117    pub fn construct_psbt<P: RgbPropKeyExt, O: RgbOutExt<P>>(
118        &mut self,
119        invoice: &RgbInvoice,
120        params: TransferParams,
121    ) -> Result<(W::Psbt, PsbtMeta), CompositionError> {
122        self.wallet
123            .construct_psbt_rgb::<S, H, I, P, O>(&self.stock, invoice, params)
124    }
125
126    #[allow(clippy::result_large_err)]
127    pub fn transfer(
128        &mut self,
129        invoice: &RgbInvoice,
130        psbt: &mut W::Psbt,
131        beneficiary_vout: Option<u32>,
132    ) -> Result<Transfer, CompletionError> {
133        self.wallet
134            .transfer(&mut self.stock, invoice, psbt, beneficiary_vout)
135    }
136}