Skip to content

Commit

Permalink
Merge pull request #97 from mycitadel/payto
Browse files Browse the repository at this point in the history
Initial RGB support
  • Loading branch information
Dr. Maxim Orlovsky authored Jul 22, 2023
2 parents 635b0c1 + 1b362dc commit a7741fc
Show file tree
Hide file tree
Showing 14 changed files with 789 additions and 95 deletions.
12 changes: 6 additions & 6 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mycitadel-desktop"
version = "1.3.0"
version = "2.0.0"
authors = ["Dr Maxim Orlovsky <[email protected]>"]
description = "Bitcoin, Lightning and RGB wallet; part of MyCitadel software suite."
repository = "https://github.com/mycitadel/mycitadel-desktop"
Expand Down Expand Up @@ -68,3 +68,4 @@ serde = ["serde_with", "serde_yaml",

[patch.crates-io]
bpro = { git = "https://github.com/pandora-prime/bpro", branch = "v0.5" }
rgb-std = { git = "https://github.com/RGB-WG/rgb-wallet", branch = "develop" }
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};
103 changes: 96 additions & 7 deletions src/view/wallet/asset_row/view_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +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 {
name: RefCell<String>,
amount: RefCell<String>,
ticker: RefCell<String>,
name: RefCell<String>,
details: RefCell<String>,
issue: RefCell<String>,
amount: RefCell<u64>,
precision: RefCell<u8>,
contract: RefCell<String>,
}

Expand Down Expand Up @@ -53,10 +58,35 @@ impl ObjectImpl for AssetInner {
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",
"Amount",
None,
0,
u64::MAX,
0,
glib::ParamFlags::READWRITE,
),
glib::ParamSpecUChar::new(
"precision",
"Precision",
"Precision",
0,
u8::MAX,
0,
glib::ParamFlags::READWRITE,
),
glib::ParamSpecString::new(
Expand Down Expand Up @@ -87,12 +117,30 @@ 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()
.expect("type conformity checked by `Object::set_property`");
self.amount.replace(amount);
}
"precision" => {
let amount = value
.get()
.expect("type conformity checked by `Object::set_property`");
self.precision.replace(amount);
}
"ticker" => {
let ticker = value
.get()
Expand All @@ -112,7 +160,10 @@ 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(),
"contract" => self.contract.borrow().to_value(),
_ => unimplemented!(),
Expand All @@ -125,30 +176,68 @@ glib::wrapper! {
}

impl AssetInfo {
pub fn btc(testnet: bool, amount: u64) -> AssetInfo {
let (btc, bitcoin) = match testnet {
true => ("tBTC", "Test bitcoin"),
false => ("BTC", "Bitcoin"),
};
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 {
let precision = precision as u32;
let amount = amount as f64 / 10_i32.pow(precision) as f64;
glib::Object::new(&[
("name", &name),
("amount", &format!("{}", amount)),
("details", &details),
("issue", &issue),
("amount", &amount),
("precision", &precision),
("ticker", &ticker),
("contract", &contract_name),
])
}

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") }

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

pub fn precision(&self) -> u8 { self.property::<u8>("precision") }
}

#[derive(Debug, Default)]
Expand Down
11 changes: 11 additions & 0 deletions src/view/wallet/asset_row/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ impl RowWidgets {

asset
.bind_property("amount", &self.amount_lbl, "label")
.transform_to(|binding, value: u64| {
let precision = binding.source().unwrap().property::<u8>("precision");
let pow = 10u64.pow(precision as u32);
let int = value / pow;
let mut fract = (value - int * pow) as f64 / pow as f64;
if fract > 0.0 && fract < 0.01 {
fract = 0.01;
}
let fract = format!("{:.2}", fract);
Some(format!("{int}.{}", fract.trim_start_matches("0.")))
})
.flags(flags)
.build();
}
Expand Down
Loading

0 comments on commit a7741fc

Please sign in to comment.