Skip to content

Commit

Permalink
rgb: show asset allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Jul 22, 2023
1 parent 67d6127 commit 1b362dc
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 28 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

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

28 changes: 28 additions & 0 deletions src/model/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// MyCitadel desktop wallet: bitcoin & RGB wallet based on GTK framework.
//
// Written in 2022 by
// Dr. Maxim Orlovsky <[email protected]>
//
// Copyright (C) 2022 by Pandora Prime SA, Switzerland.
//
// This software is distributed without any warranty. You should have received
// a copy of the AGPL-3.0 License along with this software. If not, see
// <https://www.gnu.org/licenses/agpl-3.0-standalone.html>.

use bpro::{OnchainStatus, OnchainTxid};

pub trait FormatDate {
fn format_date(&self) -> String;
}

impl FormatDate for OnchainTxid {
fn format_date(&self) -> String {
match self.status {
OnchainStatus::Blockchain(height) => self
.date_time()
.map(|dt| dt.format("%F %H:%M").to_string())
.unwrap_or_else(|| format!("{height}")),
OnchainStatus::Mempool => s!("mempool"),
}
}
}
2 changes: 2 additions & 0 deletions src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
// a copy of the AGPL-3.0 License along with this software. If not, see
// <https://www.gnu.org/licenses/agpl-3.0-standalone.html>.

mod format;
mod ui;

pub use format::FormatDate;
pub use ui::{Notification, UI};
65 changes: 63 additions & 2 deletions src/view/wallet/asset_row/view_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ use glib::subclass::prelude::*;
use gtk::prelude::*;
use gtk::subclass::prelude::ListModelImpl;
use gtk::{gio, glib};
use rgbstd::contract::ContractId;
use rgbstd::stl::{DivisibleAssetSpec, Timestamp};

// The actual data structure that stores our values. This is not accessible
// directly from the outside.
#[derive(Default)]
pub struct AssetInner {
ticker: RefCell<String>,
name: RefCell<String>,
details: RefCell<String>,
issue: RefCell<String>,
amount: RefCell<u64>,
precision: RefCell<u8>,
ticker: RefCell<String>,
contract: RefCell<String>,
}

Expand Down Expand Up @@ -53,6 +57,20 @@ impl ObjectImpl for AssetInner {
None, // Default value
glib::ParamFlags::READWRITE,
),
glib::ParamSpecString::new(
"details",
"Details",
"Details",
None, // Default value
glib::ParamFlags::READWRITE,
),
glib::ParamSpecString::new(
"issue",
"Issue",
"Issue",
None, // Default value
glib::ParamFlags::READWRITE,
),
glib::ParamSpecUInt64::new(
"amount",
"Amount",
Expand Down Expand Up @@ -99,6 +117,18 @@ impl ObjectImpl for AssetInner {
.expect("type conformity checked by `Object::set_property`");
self.name.replace(name);
}
"details" => {
let details = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.details.replace(details);
}
"issue" => {
let issue = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.issue.replace(issue);
}
"amount" => {
let amount = value
.get()
Expand Down Expand Up @@ -130,6 +160,8 @@ impl ObjectImpl for AssetInner {
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"name" => self.name.borrow().to_value(),
"details" => self.details.borrow().to_value(),
"issue" => self.issue.borrow().to_value(),
"amount" => self.amount.borrow().to_value(),
"precision" => self.precision.borrow().to_value(),
"ticker" => self.ticker.borrow().to_value(),
Expand All @@ -149,18 +181,43 @@ impl AssetInfo {
true => ("tBTC", "Test bitcoin"),
false => ("BTC", "Bitcoin"),
};
AssetInfo::with(bitcoin, btc, amount, 8, "-")
AssetInfo::with_raw(bitcoin, btc, "", "", amount, 8, "-")
}

pub fn with(
spec: DivisibleAssetSpec,
issue: Timestamp,
amount: u64,
contract_id: ContractId,
) -> AssetInfo {
let issue = issue
.to_local()
.map(|local| local.format("%F %H:%M").to_string())
.unwrap_or_else(|| s!("invalid"));
Self::with_raw(
spec.name(),
spec.ticker(),
spec.details().unwrap_or_default(),
&issue,
amount,
spec.precision as u8,
&contract_id.to_string(),
)
}

fn with_raw(
name: &str,
ticker: &str,
details: &str,
issue: &str,
amount: u64,
precision: u8,
contract_name: &str,
) -> AssetInfo {
glib::Object::new(&[
("name", &name),
("details", &details),
("issue", &issue),
("amount", &amount),
("precision", &precision),
("ticker", &ticker),
Expand All @@ -170,6 +227,10 @@ impl AssetInfo {

pub fn name(&self) -> String { self.property::<String>("name") }

pub fn details(&self) -> String { self.property::<String>("details") }

pub fn issue(&self) -> String { self.property::<String>("issue") }

pub fn ticker(&self) -> String { self.property::<String>("ticker") }

pub fn contract_name(&self) -> String { self.property::<String>("contract") }
Expand Down
14 changes: 6 additions & 8 deletions src/view/wallet/view_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,10 @@ impl ViewModel {
let iface = Rgb20::from(iface);
let spec = iface.spec();
asset_model.append(&AssetInfo::with(
spec.name(),
spec.ticker(),
spec,
iface.created(),
iface.balance(&mut wallet),
spec.precision.into(),
&iface.contract_id().to_string(),
iface.contract_id(),
));
}
}
Expand Down Expand Up @@ -223,11 +222,10 @@ impl ViewModel {
let iface = self.asset_for(id);
let spec = iface.spec();
AssetInfo::with(
spec.name(),
spec.ticker(),
spec,
iface.created(),
iface.balance(&self.wallet),
spec.precision.into(),
&iface.contract_id().to_string(),
iface.contract_id(),
)
}
}
47 changes: 31 additions & 16 deletions src/view/wallet/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use std::collections::BTreeSet;
use std::ffi::OsStr;

use bpro::{
AddressSummary, ElectrumSec, ElectrumServer, HistoryEntry, OnchainStatus, UtxoTxid, WalletState,
AddressSummary, ElectrumSec, ElectrumServer, HistoryEntry, OnchainStatus, OnchainTxid,
UtxoTxid, WalletState,
};
use chrono::{DateTime, NaiveDateTime, Utc};
use electrum_client::HeaderNotification;
Expand All @@ -26,12 +27,13 @@ use gtk::{
SortType, SpinButton, Spinner, Statusbar, TextBuffer, TreeView,
};
use relm::Relm;
use rgb::contract::SealWitness;
use rgbstd::interface::FungibleAllocation;
use wallet::hd::SegmentIndexes;

use super::asset_row::{self, AssetModel};
use super::{payto, ElectrumState, Msg, ViewModel};
use crate::model::UI as UIColorTrait;
use crate::model::{FormatDate, UI as UIColorTrait};
use crate::view::{launch, APP_ICON, APP_ICON_TOOL};
use crate::worker::exchange::{Exchange, Fiat};

Expand Down Expand Up @@ -627,17 +629,39 @@ impl Widgets {
}
Some(_) => {
let info = model.asset_info();
self.update_allocations(&model.asset_allocations(), info.precision());
let allocations = model.asset_allocations();
let rgb = model.wallet().rgb().unwrap();
self.update_allocations(
allocations,
info.precision(),
&info.issue(),
rgb.witness_txes(),
);
}
}
}

pub fn update_allocations(&mut self, allocations: &[FungibleAllocation], precision: u8) {
pub fn update_allocations(
&mut self,
allocations: Vec<FungibleAllocation>,
precision: u8,
issue: &str,
witness_txes: &BTreeSet<OnchainTxid>,
) {
let pow = 10u64.pow(precision as u32);
self.utxo_store.clear();
for allocation in allocations {
let int = allocation.value / pow;
let fract = allocation.value - int * pow;
let date = match allocation.witness {
SealWitness::Genesis => issue.to_string(),
SealWitness::Present(txid) => witness_txes
.iter()
.find(|info| info.txid.as_ref() == txid.as_ref().as_slice())
.map(OnchainTxid::format_date)
.unwrap_or_else(|| s!("unknown")),
SealWitness::Extension => s!("issue"),
};
self.utxo_store.insert_with_values(None, &[
(0, &""),
(1, &allocation.owner.to_string()),
Expand All @@ -647,7 +671,7 @@ impl Widgets {
.trim_end_matches('0')
.trim_end_matches('.'),
),
(3, &""),
(3, &date),
(4, &0u32),
]);
}
Expand All @@ -656,20 +680,11 @@ impl Widgets {
pub fn update_utxos(&mut self, utxos: &BTreeSet<UtxoTxid>) {
self.utxo_store.clear();
for item in utxos {
let btc = format_btc_value(item.value);
let date = match item.onchain.status {
OnchainStatus::Blockchain(height) => item
.onchain
.date_time()
.map(|dt| dt.format("%F %H:%M").to_string())
.unwrap_or_else(|| format!("{height}")),
OnchainStatus::Mempool => s!("mempool"),
};
self.utxo_store.insert_with_values(None, &[
(0, &item.addr_src.address.to_string()),
(1, &format!("{}:{}", item.onchain.txid, item.vout)),
(2, &btc),
(3, &date),
(2, &format_btc_value(item.value)),
(3, &item.onchain.format_date()),
(4, &item.onchain.status.into_u32()),
]);
}
Expand Down

0 comments on commit 1b362dc

Please sign in to comment.