From cb1e37491a6081e87ce138ac2e784c0cb2e00161 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 22 Jul 2022 17:05:51 -0600 Subject: [PATCH] [WIP] cosmrs::tx::Builder --- cosmrs/src/crypto/public_key.rs | 3 +- cosmrs/src/error.rs | 2 +- cosmrs/src/tx.rs | 2 + cosmrs/src/tx/body.rs | 9 ++++- cosmrs/src/tx/builder.rs | 70 +++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 cosmrs/src/tx/builder.rs diff --git a/cosmrs/src/crypto/public_key.rs b/cosmrs/src/crypto/public_key.rs index 716f5e6d..2743a1c0 100644 --- a/cosmrs/src/crypto/public_key.rs +++ b/cosmrs/src/crypto/public_key.rs @@ -1,9 +1,8 @@ //! Public keys -use crate::{prost_ext::MessageExt, proto, AccountId, Error, ErrorReport, Result}; +use crate::{prost_ext::MessageExt, proto, AccountId, Error, ErrorReport, Result, Any}; use eyre::WrapErr; use prost::Message; -use prost_types::Any; use serde::{Deserialize, Serialize}; use std::str::FromStr; use subtle_encoding::base64; diff --git a/cosmrs/src/error.rs b/cosmrs/src/error.rs index c455c25c..0958625b 100644 --- a/cosmrs/src/error.rs +++ b/cosmrs/src/error.rs @@ -46,7 +46,7 @@ pub enum Error { /// Expected type URL. expected: &'static str, - /// Actual type URL found in the [`prost_types::Any`] message. + /// Actual type URL found in the [`crate::Any`] message. found: String, }, diff --git a/cosmrs/src/tx.rs b/cosmrs/src/tx.rs index 8124d2b3..eb375417 100644 --- a/cosmrs/src/tx.rs +++ b/cosmrs/src/tx.rs @@ -106,6 +106,7 @@ pub mod mode_info; mod auth_info; mod body; +mod builder; mod fee; mod msg; mod raw; @@ -115,6 +116,7 @@ mod signer_info; pub use self::{ auth_info::AuthInfo, body::Body, + builder::Builder, fee::Fee, mode_info::ModeInfo, msg::{Msg, MsgProto}, diff --git a/cosmrs/src/tx/body.rs b/cosmrs/src/tx/body.rs index 1dd1149e..102aa065 100644 --- a/cosmrs/src/tx/body.rs +++ b/cosmrs/src/tx/body.rs @@ -1,7 +1,6 @@ //! Transaction bodies. -use crate::{prost_ext::MessageExt, proto, ErrorReport, Result}; -use prost_types::Any; +use crate::{prost_ext::MessageExt, proto, ErrorReport, Result, Any}; use tendermint::block; /// [`Body`] of a transaction that all signers sign over. @@ -67,6 +66,12 @@ impl Body { } } +impl Default for Body { + fn default() -> Body { + Self::new([], "", 0u8) + } +} + impl From for proto::cosmos::tx::v1beta1::TxBody { fn from(body: Body) -> proto::cosmos::tx::v1beta1::TxBody { proto::cosmos::tx::v1beta1::TxBody { diff --git a/cosmrs/src/tx/builder.rs b/cosmrs/src/tx/builder.rs new file mode 100644 index 00000000..2422cd8c --- /dev/null +++ b/cosmrs/src/tx/builder.rs @@ -0,0 +1,70 @@ +//! Transaction builder. + +use super::Body; +use crate::Any; +use tendermint::block; + +/// Transaction [`Body`] builder which simplifies incrementally assembling and +/// signing a transaction. +#[derive(Clone, Debug, Default)] +pub struct Builder { + /// Transaction body in-progress. + body: Body, +} + +impl Builder { + /// Create a new transaction builder in the default state. + pub fn new() -> Self { + Self::default() + } + + /// Add a message to the transaction. + pub fn msg(&mut self, msg: impl Into) -> &mut Self { + self.body.messages.push(msg.into()); + self + } + + /// Add multiple messages to the transaction. + pub fn msgs(&mut self, msgs: impl IntoIterator) -> &mut Self { + self.body.messages.extend(msgs); + self + } + + /// Set the transaction memo. + // TODO(tarcieri): error if the memo is already set? + pub fn memo(&mut self, memo: impl Into) -> &mut Self { + self.body.memo = memo.into(); + self + } + + /// Set the timeout height. + // TODO(tarcieri): error if the timeout height is already set? + pub fn timeout_height(&mut self, height: impl Into) -> &mut Self { + self.body.timeout_height = height.into(); + self + } + + /// Add an extension option. + pub fn extension_option(&mut self, option: impl Into) -> &mut Self { + self.body.extension_options.push(option.into()); + self + } + + /// Add a non-critical extension option. + pub fn non_critical_extension_option(&mut self, option: impl Into) -> &mut Self { + self.body.extension_options.push(option.into()); + self + } +} + +impl From for Body { + fn from(builder: Builder) -> Body { + builder.body + } +} + +impl From<&Builder> for Body { + fn from(builder: &Builder) -> Body { + builder.body.clone() + } +}