Skip to content

Commit

Permalink
wallet: use new history API. Remve interfaces dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Sep 20, 2024
1 parent e3bb8e3 commit 406f80a
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 190 deletions.
28 changes: 3 additions & 25 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ psbt = { version = "0.11.0-beta.8", features = ["client-side-validation"] }
bp-wallet = { version = "0.11.0-beta.8" }
rgb-std = { version = "0.11.0-beta.8" }
rgb-psbt = { version = "0.11.0-beta.8", path = "psbt" }
rgb-interfaces = "0.11.0-beta.8"
indexmap = "2.4.0"
chrono = "0.4.38"
serde_crate = { package = "serde", version = "1", features = ["derive"] }
Expand Down Expand Up @@ -103,3 +102,6 @@ serde = ["serde_crate", "serde_yaml", "bp-std/serde", "descriptors/serde", "rgb-

[package.metadata.docs.rs]
features = ["all"]

[patch.crates-io]
rgb-std = { git = "https://github.com/RGB-WG/rgb-std", branch = "fix/rgb-252" }
1 change: 0 additions & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ bp-std = { workspace = true, features = ["serde"] }
bp-wallet = { workspace = true, features = ["cli"] }
psbt = { workspace = true }
rgb-std = { workspace = true, features = ["serde"] }
rgb-interfaces = { workspace = true }
rgb-runtime = { version = "0.11.0-beta.7", path = "..", features = ["electrum_blocking", "esplora_blocking", "mempool_blocking", "log", "serde", "fs", "cli"] }
log = { workspace = true }
env_logger = "0.11.5"
Expand Down
125 changes: 64 additions & 61 deletions cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,22 @@ use baid64::DisplayBaid64;
use bpstd::{Sats, XpubDerivable};
use bpwallet::cli::{BpCommand, Config, Exec};
use bpwallet::Wallet;
use ifaces::{IfaceStandard, Rgb20, Rgb21, Rgb25};
use psbt::{Psbt, PsbtVer};
use rgb::containers::{
BuilderSeal, ContainerVer, ContentId, ContentSigs, Contract, FileContent, Supplement, Transfer,
UniversalFile,
BuilderSeal, ConsignmentExt, ContainerVer, ContentId, ContentSigs, Contract, FileContent,
Supplement, Transfer, UniversalFile,
};
use rgb::interface::{AmountChange, IfaceId, OutpointFilter};
use rgb::interface::{AssignmentsFilter, ContractOp, IfaceId};
use rgb::invoice::{Beneficiary, Pay2Vout, RgbInvoice, RgbInvoiceBuilder, XChainNet};
use rgb::persistence::StashReadProvider;
use rgb::persistence::{MemContract, StashReadProvider, Stock};
use rgb::schema::SchemaId;
use rgb::validation::Validity;
use rgb::vm::RgbIsa;
use rgb::{
BundleId, ContractId, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OutputSeal, RgbDescr,
RgbKeychain, RgbWallet, StateType, TransferParams, WalletError, WalletProvider, XChain,
XOutpoint, XOutputSeal, XWitnessId,
BundleId, ContractId, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, OutputSeal,
RgbDescr, RgbKeychain, RgbWallet, StateType, TransferParams, WalletError, WalletProvider,
XChain, XOutpoint, XWitnessId,
};
use rgbstd::containers::ConsignmentExt;
use rgbstd::persistence::{MemContract, Stock};
use seals::SecretSeal;
use serde_crate::{Deserialize, Serialize};
use strict_types::encoding::{FieldName, TypeName};
Expand All @@ -74,10 +71,7 @@ pub enum Command {

/// Prints out list of known RGB contracts
#[display("contracts")]
Contracts {
/// Select only contracts using specific interface standard
standard: Option<IfaceStandard>,
},
Contracts,

/// Imports RGB data into the stash: contracts, schema, interfaces, etc
#[display("import")]
Expand Down Expand Up @@ -135,6 +129,10 @@ pub enum Command {
/// interface
#[display("history-fungible")]
HistoryFungible {
/// Print detailed information
#[clap(long)]
details: bool,

Check warning on line 134 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L134

Added line #L134 was not covered by tests

/// Contract identifier
contract_id: ContractId,

Expand Down Expand Up @@ -338,57 +336,58 @@ impl Exec for RgbArgs {
print!("{info}");
}
}
Command::Contracts { standard: None } => {
Command::Contracts => {
let stock = self.rgb_stock()?;
for info in stock.contracts()? {
print!("{info}");
}
}
Command::Contracts {
standard: Some(IfaceStandard::Rgb20),
} => {
let stock = self.rgb_stock()?;
for info in stock.contracts_by::<Rgb20>()? {
print!("{info}");
}
}
Command::Contracts {
standard: Some(IfaceStandard::Rgb21),
} => {
let stock = self.rgb_stock()?;
for info in stock.contracts_by::<Rgb21>()? {
print!("{info}");
}
}
Command::Contracts {
standard: Some(IfaceStandard::Rgb25),
} => {
let stock = self.rgb_stock()?;
for info in stock.contracts_by::<Rgb25>()? {
print!("{info}");
}
}

Command::HistoryFungible { contract_id, iface } => {
Command::HistoryFungible {
contract_id,
iface,
details,

Check warning on line 349 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L347-L349

Added lines #L347 - L349 were not covered by tests
} => {
let wallet = self.rgb_wallet(&config)?;
let iface: TypeName = tn!(iface.clone());
let history = wallet.fungible_history(*contract_id, iface)?;
println!("Amount\tCounterparty\tWitness Id");
for (id, op) in history {
let (cparty, more) = match op.state_change {
AmountChange::Dec(_) => {
(op.beneficiaries.first(), op.beneficiaries.len().saturating_sub(1))
}
AmountChange::Zero => continue,
AmountChange::Inc(_) => {
(op.payers.first(), op.payers.len().saturating_sub(1))
}
};
let more = if more > 0 { format!(" (+{more})") } else { s!("") };
let cparty = cparty
.map(XOutputSeal::to_string)
.unwrap_or_else(|| s!("none"));
println!("{}\t{}{}\t{}", op.state_change, cparty, more, id);
let history = wallet.history(*contract_id, iface)?;
if *details {
println!("Operation\tValue\tState\tSeal\tWitness\tOpIds");
} else {
println!("Operation\tValue\tSeal\tWitness");
}

Check warning on line 358 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L353-L358

Added lines #L353 - L358 were not covered by tests
for ContractOp {
direction,
ty,
opids,
state,
to,
witness,
} in history

Check warning on line 366 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L360-L366

Added lines #L360 - L366 were not covered by tests
{
print!("{direction}\t{state}");
if *details {
print!("\t{ty}");
}
print!(
"\t{}\t{}",
to.first().expect("at least one receiver is always present"),
witness
.map(|info| format!("{} ({})", info.id, info.ord))
.unwrap_or_else(|| s!("~"))
);
if *details {
println!(
"{}",
opids
.iter()
.map(OpId::to_string)
.collect::<Vec<_>>()
.join(", ")
)
} else {
println!();
}

Check warning on line 390 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L368-L390

Added lines #L368 - L390 were not covered by tests
}
}

Expand Down Expand Up @@ -530,11 +529,15 @@ impl Exec for RgbArgs {
WalletAll(&'w RgbWallet<Wallet<XpubDerivable, RgbDescr>>),
NoWallet,
}
impl<'w> OutpointFilter for Filter<'w> {
fn include_outpoint(&self, outpoint: impl Into<XOutpoint>) -> bool {
impl<'w> AssignmentsFilter for Filter<'w> {
fn should_include(
&self,
outpoint: impl Into<XOutpoint>,
id: Option<XWitnessId>,
) -> bool {

Check warning on line 537 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L533-L537

Added lines #L533 - L537 were not covered by tests
match self {
Filter::Wallet(wallet) => {
wallet.wallet().filter().include_outpoint(outpoint)
wallet.wallet().filter().should_include(outpoint, id)

Check warning on line 540 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L540

Added line #L540 was not covered by tests
}
_ => true,
}
Expand All @@ -544,7 +547,7 @@ impl Exec for RgbArgs {
fn comment(&self, outpoint: XOutpoint) -> &'static str {
match self {
Filter::Wallet(wallet) | Filter::WalletAll(wallet)
if wallet.wallet().filter().include_outpoint(outpoint) =>
if wallet.wallet().filter().should_include(outpoint, None) =>

Check warning on line 550 in cli/src/command.rs

View check run for this annotation

Codecov / codecov/patch

cli/src/command.rs#L550

Added line #L550 was not covered by tests
{
""
}
Expand Down
16 changes: 1 addition & 15 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,11 @@ pub enum WalletError {

#[cfg(feature = "cli")]
#[from]
WalletExect(bpwallet::cli::ExecError),
WalletExec(bpwallet::cli::ExecError),

#[from]
Builder(BuilderError),

#[from]
History(HistoryError),

#[from]
Contract(ContractError),

Expand Down Expand Up @@ -118,17 +115,6 @@ impl From<(Stock, WalletError)> for WalletError {
fn from((_, e): (Stock, WalletError)) -> Self { e }
}

#[derive(Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum HistoryError {
/// interface doesn't define default operation
NoDefaultOp,
/// default operation defined by the interface is not a state transition
DefaultOpNotTransition,
/// interface doesn't define default fungible state
NoDefaultAssignment,
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Display, Error, From)]
pub enum PayError {
Expand Down
60 changes: 60 additions & 0 deletions src/filters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// RGB wallet library for smart contracts on Bitcoin & Lightning network
//
// SPDX-License-Identifier: Apache-2.0
//
// Written in 2019-2023 by
// Dr Maxim Orlovsky <[email protected]>
//
// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use bpwallet::Wallet;
use rgbstd::interface::AssignmentsFilter;

use crate::{DescriptorRgb, WalletProvider, XChain, XOutpoint, XWitnessId};

pub struct WalletOutpointsFilter<'a, K, D: DescriptorRgb<K>>(pub &'a Wallet<K, D>);

// We need manual derivation to ensure we can be copied and cloned even if descriptor is not
// copyable/clonable.
impl<'a, K, D: DescriptorRgb<K>> Copy for WalletOutpointsFilter<'a, K, D> {}
impl<'a, K, D: DescriptorRgb<K>> Clone for WalletOutpointsFilter<'a, K, D> {
fn clone(&self) -> Self { *self }

Check warning on line 33 in src/filters.rs

View check run for this annotation

Codecov / codecov/patch

src/filters.rs#L33

Added line #L33 was not covered by tests
}

impl<'a, K, D: DescriptorRgb<K>> AssignmentsFilter for WalletOutpointsFilter<'a, K, D> {
fn should_include(&self, output: impl Into<XOutpoint>, _: Option<XWitnessId>) -> bool {
let output = output.into();
self.0
.outpoints()
.any(|outpoint| XChain::Bitcoin(outpoint) == *output)
}

Check warning on line 42 in src/filters.rs

View check run for this annotation

Codecov / codecov/patch

src/filters.rs#L37-L42

Added lines #L37 - L42 were not covered by tests
}

pub struct WitnessOutpointsFilter<'a, K, D: DescriptorRgb<K>>(pub &'a Wallet<K, D>);

// We need manual derivation to ensure we can be copied and cloned even if descriptor is not
// copyable/clonable.
impl<'a, K, D: DescriptorRgb<K>> Copy for WitnessOutpointsFilter<'a, K, D> {}
impl<'a, K, D: DescriptorRgb<K>> Clone for WitnessOutpointsFilter<'a, K, D> {
fn clone(&self) -> Self { *self }

Check warning on line 51 in src/filters.rs

View check run for this annotation

Codecov / codecov/patch

src/filters.rs#L51

Added line #L51 was not covered by tests
}

impl<'a, K, D: DescriptorRgb<K>> AssignmentsFilter for WitnessOutpointsFilter<'a, K, D> {
fn should_include(&self, _: impl Into<XOutpoint>, witness_id: Option<XWitnessId>) -> bool {
self.0
.history()
.any(|row| witness_id == Some(XChain::Bitcoin(row.txid)))
}

Check warning on line 59 in src/filters.rs

View check run for this annotation

Codecov / codecov/patch

src/filters.rs#L55-L59

Added lines #L55 - L59 were not covered by tests
}
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@ extern crate serde_crate as serde;

mod descriptor;
mod indexers;
mod wrapper;
mod filters;
pub mod pay;
mod errors;
mod wallet;

pub use descriptor::{DescriptorRgb, RgbDescr, RgbKeychain, TapTweakAlreadyAssigned, TapretKey};
pub use errors::{CompletionError, CompositionError, HistoryError, PayError, WalletError};
pub use errors::{CompletionError, CompositionError, PayError, WalletError};
pub use pay::{TransferParams, WalletProvider};
pub use rgbstd::*;
pub mod resolvers {
#[cfg(any(feature = "electrum_blocking", feature = "esplora_blocking"))]
pub use super::indexers::*;
pub use super::indexers::{AnyResolver, RgbResolver};
}
pub use filters::{WalletOutpointsFilter, WitnessOutpointsFilter};
pub use wallet::RgbWallet;
pub use wrapper::WalletWrapper;
Loading

0 comments on commit 406f80a

Please sign in to comment.