From 2b65c582c236b727e6a998e9106ff1735a68c26a Mon Sep 17 00:00:00 2001 From: Joel Ulahanna Date: Tue, 17 Sep 2024 10:02:47 -0500 Subject: [PATCH] cli: holofuel summary (#210) --- crates/core_app_cli/src/actions/mod.rs | 1 + crates/core_app_cli/src/actions/summary.rs | 70 ++++++++++ crates/core_app_cli/src/main.rs | 13 ++ crates/holofuel_cli/src/actions/mod.rs | 1 + crates/holofuel_cli/src/actions/summary.rs | 70 ++++++++++ crates/holofuel_cli/src/main.rs | 14 ++ crates/hpos_connect_hc/src/holofuel_types.rs | 140 +++++++++++++++++++ 7 files changed, 309 insertions(+) create mode 100644 crates/core_app_cli/src/actions/summary.rs create mode 100644 crates/holofuel_cli/src/actions/summary.rs diff --git a/crates/core_app_cli/src/actions/mod.rs b/crates/core_app_cli/src/actions/mod.rs index 0f3adfb1..7dd80ad3 100644 --- a/crates/core_app_cli/src/actions/mod.rs +++ b/crates/core_app_cli/src/actions/mod.rs @@ -9,3 +9,4 @@ pub mod list_all_tx; pub mod pay_invoices; pub mod profile; pub mod set_happ_prefs; +pub mod summary; diff --git a/crates/core_app_cli/src/actions/summary.rs b/crates/core_app_cli/src/actions/summary.rs new file mode 100644 index 00000000..17572c0a --- /dev/null +++ b/crates/core_app_cli/src/actions/summary.rs @@ -0,0 +1,70 @@ +use anyhow::Result; +use holochain_types::dna::AgentPubKey; +use holochain_types::prelude::{FunctionName, ZomeName}; +use hpos_hc_connect::app_connection::CoreAppRoleName; +use hpos_hc_connect::hf_agent::HfAgent; +use hpos_hc_connect::holofuel_types::MigrationCloseStateV1Handler; + +pub async fn get_my_summary() -> Result<()> { + let mut agent = HfAgent::spawn(None).await?; + + let summary: MigrationCloseStateV1Handler = agent + .app + .zome_call_typed( + CoreAppRoleName::Holofuel.into(), + ZomeName::from("transactor"), + FunctionName::from("get_my_summary"), + (), + ) + .await?; + + display(summary); + Ok(()) +} + +pub async fn get_agent_summary(pub_key: AgentPubKey) -> Result<()> { + let mut agent = HfAgent::spawn(None).await?; + + let summary: MigrationCloseStateV1Handler = agent + .app + .zome_call_typed( + CoreAppRoleName::Holofuel.into(), + ZomeName::from("transactor"), + FunctionName::from("get_agent_summary"), + pub_key, + ) + .await?; + display(summary); + Ok(()) +} + +fn display(summary: MigrationCloseStateV1Handler) { + println!("==================="); + println!("Your Summary: "); + println!("multi_sig_authorizer: {:?}", summary.multi_sig_authorizer); + println!("reserve_setting: {:?}", summary.reserve_setting); + println!("reserve_sale_price: {:?}", summary.reserve_sale_price); + println!("tx_parked_links: {:?}", summary.tx_parked_links); + println!("cs_txs: {:?}", summary.cs_txs); + println!( + "incomplete_invoice_txs: {:?}", + summary.incomplete_invoice_txs + ); + println!( + "incomplete_promise_txs: {:?}", + summary.incomplete_promise_txs + ); + println!("Number of cs tx: {:?}", summary.cs_txs.len()); + println!( + "Number of incomplete invoice: {:?}", + summary.incomplete_invoice_txs.len() + ); + println!( + "Number of incomplete promises: {:?}", + summary.incomplete_promise_txs.len() + ); + println!("Number of declined: {:?}", summary.number_of_declined); + println!("opening_balance: {:?}", summary.opening_balance); + println!("closing_balance: {:?}", summary.closing_balance); + println!("==================="); +} diff --git a/crates/core_app_cli/src/main.rs b/crates/core_app_cli/src/main.rs index 24810d38..5e109eb9 100644 --- a/crates/core_app_cli/src/main.rs +++ b/crates/core_app_cli/src/main.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use holochain_types::dna::AgentPubKeyB64; use structopt::StructOpt; #[derive(Debug, StructOpt)] @@ -51,6 +52,12 @@ pub enum Opt { #[structopt(name = "max-time-ms")] max_time_before_invoice_ms: String, }, + /// Get My Summary + #[structopt(name = "gms")] + GetMySummary, + /// Get Summary by providing an agent public key + #[structopt(name = "gas")] + GetAgentSummary { pub_key: String }, } impl Opt { /// Run this command @@ -94,6 +101,12 @@ impl Opt { ) .await? } + Opt::GetMySummary => core_app_cli::summary::get_my_summary().await?, + Opt::GetAgentSummary { pub_key } => { + let pub_key = AgentPubKeyB64::from_b64_str(&pub_key) + .expect("Failed to serialize string into AgentPubKey"); + core_app_cli::summary::get_agent_summary(pub_key.into()).await? + } } Ok(()) } diff --git a/crates/holofuel_cli/src/actions/mod.rs b/crates/holofuel_cli/src/actions/mod.rs index d2c8b680..91e3d20d 100644 --- a/crates/holofuel_cli/src/actions/mod.rs +++ b/crates/holofuel_cli/src/actions/mod.rs @@ -4,3 +4,4 @@ pub mod ledger; pub mod pending; pub mod profile; pub mod reserve; +pub mod summary; diff --git a/crates/holofuel_cli/src/actions/summary.rs b/crates/holofuel_cli/src/actions/summary.rs new file mode 100644 index 00000000..17572c0a --- /dev/null +++ b/crates/holofuel_cli/src/actions/summary.rs @@ -0,0 +1,70 @@ +use anyhow::Result; +use holochain_types::dna::AgentPubKey; +use holochain_types::prelude::{FunctionName, ZomeName}; +use hpos_hc_connect::app_connection::CoreAppRoleName; +use hpos_hc_connect::hf_agent::HfAgent; +use hpos_hc_connect::holofuel_types::MigrationCloseStateV1Handler; + +pub async fn get_my_summary() -> Result<()> { + let mut agent = HfAgent::spawn(None).await?; + + let summary: MigrationCloseStateV1Handler = agent + .app + .zome_call_typed( + CoreAppRoleName::Holofuel.into(), + ZomeName::from("transactor"), + FunctionName::from("get_my_summary"), + (), + ) + .await?; + + display(summary); + Ok(()) +} + +pub async fn get_agent_summary(pub_key: AgentPubKey) -> Result<()> { + let mut agent = HfAgent::spawn(None).await?; + + let summary: MigrationCloseStateV1Handler = agent + .app + .zome_call_typed( + CoreAppRoleName::Holofuel.into(), + ZomeName::from("transactor"), + FunctionName::from("get_agent_summary"), + pub_key, + ) + .await?; + display(summary); + Ok(()) +} + +fn display(summary: MigrationCloseStateV1Handler) { + println!("==================="); + println!("Your Summary: "); + println!("multi_sig_authorizer: {:?}", summary.multi_sig_authorizer); + println!("reserve_setting: {:?}", summary.reserve_setting); + println!("reserve_sale_price: {:?}", summary.reserve_sale_price); + println!("tx_parked_links: {:?}", summary.tx_parked_links); + println!("cs_txs: {:?}", summary.cs_txs); + println!( + "incomplete_invoice_txs: {:?}", + summary.incomplete_invoice_txs + ); + println!( + "incomplete_promise_txs: {:?}", + summary.incomplete_promise_txs + ); + println!("Number of cs tx: {:?}", summary.cs_txs.len()); + println!( + "Number of incomplete invoice: {:?}", + summary.incomplete_invoice_txs.len() + ); + println!( + "Number of incomplete promises: {:?}", + summary.incomplete_promise_txs.len() + ); + println!("Number of declined: {:?}", summary.number_of_declined); + println!("opening_balance: {:?}", summary.opening_balance); + println!("closing_balance: {:?}", summary.closing_balance); + println!("==================="); +} diff --git a/crates/holofuel_cli/src/main.rs b/crates/holofuel_cli/src/main.rs index 73610a48..5c5dd9fc 100644 --- a/crates/holofuel_cli/src/main.rs +++ b/crates/holofuel_cli/src/main.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use holochain_types::dna::AgentPubKeyB64; use structopt::StructOpt; #[derive(Debug, StructOpt)] @@ -24,7 +25,14 @@ pub enum Opt { /// Get this reserve accounts sales price #[structopt(name = "rsp")] ReserveSalePrice, + /// Get My Summary + #[structopt(name = "gms")] + GetMySummary, + /// Get Summary by providing an agent public key + #[structopt(name = "gas")] + GetAgentSummary { pub_key: String }, } + impl Opt { /// Run this command pub async fn run(self) -> Result<()> { @@ -36,6 +44,12 @@ impl Opt { Opt::Profile => hf::actions::profile::get().await?, Opt::ReserveSetting => hf::actions::reserve::get_setting().await?, Opt::ReserveSalePrice => hf::actions::reserve::get_sale_price().await?, + Opt::GetMySummary => hf::actions::summary::get_my_summary().await?, + Opt::GetAgentSummary { pub_key } => { + let pub_key = AgentPubKeyB64::from_b64_str(&pub_key) + .expect("Failed to serialize string into AgentPubKey"); + hf::actions::summary::get_agent_summary(pub_key.into()).await? + } } Ok(()) } diff --git a/crates/hpos_connect_hc/src/holofuel_types.rs b/crates/hpos_connect_hc/src/holofuel_types.rs index 6db828a8..00e20167 100644 --- a/crates/hpos_connect_hc/src/holofuel_types.rs +++ b/crates/hpos_connect_hc/src/holofuel_types.rs @@ -1,8 +1,14 @@ use anyhow::{Context, Result}; +use holochain_types::prelude::ActionHash; +use holochain_types::prelude::AgentPubKey; +use holochain_types::prelude::AnyLinkableHash; +use holochain_types::prelude::EntryHash; +use holochain_types::prelude::Signature; use holochain_types::prelude::{ holochain_serial, ActionHashB64, AgentPubKeyB64, AnyDhtHashB64, CapSecret, EntryHashB64, SerializedBytes, Timestamp, X25519PubKey, }; +use holofuel_types::fuel::Fuel; use serde::Deserialize; use serde::Serialize; use std::time::Duration; @@ -167,6 +173,140 @@ pub struct ReserveSalePrice { pub inputs_used: Vec, } +/// Summary +/// + +#[derive(Serialize, Deserialize, Debug, SerializedBytes)] +pub struct MigrationCloseStateV1Handler { + pub opening_balance: Fuel, + pub closing_balance: Fuel, + pub number_of_declined: usize, + pub multi_sig_authorizer: Option, + pub reserve_setting: Option, + pub reserve_sale_price: Option, + pub cs_txs: Vec, + pub tx_parked_links: Vec, + pub incomplete_invoice_txs: Vec, + pub incomplete_promise_txs: Vec, +} + +pub type CounterSignedTxBundle = (CounterSignedTx, ActionHash, Timestamp); +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, SerializedBytes)] +pub struct TxParkedLink { + pub id: ActionHash, + pub parking_spot_hash: AnyLinkableHash, + pub timestamp: Timestamp, + pub fees: Fuel, +} + +pub type InvoiceBundle = (Invoice, EntryHash, Timestamp); +pub type PromiseBundle = (Promise, EntryHash, Timestamp); + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, SerializedBytes)] +pub struct Promise { + pub timestamp: Timestamp, + pub promise_details: TxDetails, + pub fee: Fuel, + pub expiration_date: Timestamp, + pub invoice_hash: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, SerializedBytes)] +pub struct Invoice { + pub timestamp: Timestamp, + pub invoice_details: TxDetails, + pub expiration_date: Option, + pub promise_hash: Option, +} +#[derive(Serialize, Deserialize, Debug, Clone, SerializedBytes, PartialEq, Eq)] +pub struct TxDetails { + pub spender: AgentPubKey, + pub receiver: AgentPubKey, + pub amount: Fuel, + pub payload: Payload, +} +#[derive(Serialize, Deserialize, Debug, SerializedBytes)] +pub struct MultiSigAuthorizers(Vec); +#[derive(Serialize, Deserialize, SerializedBytes, Debug, Clone, PartialEq, Eq)] +pub struct AuthorizerRules { + condition: MultiSigCondition, // MultiSig expected when conditions are met + m_of_n: i8, // is the M of N of the signers whose signatures are required + signer_keys: Vec, // are a vector of keys used for authorization of the action +} +#[derive(Serialize, Deserialize, SerializedBytes, Debug, Clone, PartialEq, Eq)] +pub struct MultiSigCondition { + above_hf_amt: Fuel, // MultiSig will be expected on values above this amt +} + +// Countersigning tx +#[derive(Serialize, Deserialize, SerializedBytes, Debug, Clone, PartialEq, Eq)] +pub struct CounterSignedTx { + pub tx_body: CounterSignedTxBody, + pub spender_state: FuelState, + pub receiver_state: FuelState, +} +#[derive(Serialize, Deserialize, SerializedBytes, Debug, Clone, PartialEq, Eq)] +pub struct FuelState { + pub new_bal: Fuel, + pub new_promise: Fuel, + pub tx_fees_owed: Fuel, + pub tx_body_signature: Signature, +} +#[derive(Serialize, Deserialize, SerializedBytes, Debug, Clone, PartialEq, Eq)] +pub struct CounterSignedTxBody { + pub tx_amt: Fuel, + pub tx_fee: Fuel, + pub spender_payload: Payload, + pub receiver_payload: Payload, + pub spender_chain_info: ChainInfo, + pub receiver_chain_info: ChainInfo, +} +#[derive(Serialize, Deserialize, Debug, Clone, SerializedBytes, Default, PartialEq, Eq)] +pub struct Payload { + pub note: Option, + pub proof_of_service: Option, + pub url: Option, +} +#[derive(Serialize, Deserialize, SerializedBytes, Debug, Clone, PartialEq, Eq)] +pub struct ChainInfo { + pub agent_address: AgentPubKey, + pub pre_auth: EntryHash, + pub prior_action: ActionHash, + pub tx_seq_num: u32, +} +#[derive(Serialize, Deserialize, Debug, Clone, SerializedBytes, PartialEq, Eq)] +pub enum NoteTypes { + ReserveNote(ReserveNote), + MultiSigPayload(MultiSigNote), + SimpleNote(String), +} +#[derive(Serialize, Deserialize, Debug, Clone, SerializedBytes, PartialEq, Eq)] +pub struct ReserveNote { + pub details: ReserveProof, + pub signature: Signature, + pub extra_note: Option, +} +#[derive(Serialize, Deserialize, Debug, Clone, SerializedBytes, PartialEq, Eq)] +pub struct ReserveProof { + pub ext_amt_transferred: Fuel, // Amount of external currency + pub nonce: String, + pub reserve_sales_price: Fuel, // Number of HF units one external currency unit purchases, at the time of promise or request based off the ReserveSalePrice + pub ext_tx_id: Option, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] +pub struct MultiSigNote { + pub details: MultiSigPayload, + pub list_of_sig: Vec, + pub extra_note: Option, +} +#[derive(serde::Serialize, serde::Deserialize, SerializedBytes, Debug, Clone, PartialEq, Eq)] +pub struct MultiSigPayload { + pub role: String, + pub amt: Fuel, + pub counterparty: String, // using AgentPubKeyB64 has serde deserialization issues + pub auth_date: Timestamp, +} #[cfg(test)] pub mod tests { use crate::holofuel_types::ReserveSettingFile;