Skip to content

Commit

Permalink
feat(rust): add TopicCreate, TopicUpdate, TopicDelete, and TopicMessa…
Browse files Browse the repository at this point in the history
…geSubmit transactions
  • Loading branch information
mehcode committed May 30, 2022
1 parent 5644ce0 commit f7fd9b0
Show file tree
Hide file tree
Showing 11 changed files with 518 additions and 8 deletions.
10 changes: 8 additions & 2 deletions sdk/rust/src/account/account_update_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub struct AccountUpdateTransactionData {
pub auto_renew_period: Option<Duration>,

/// The new expiration time to extend to (ignored if equal to or before the current one).
pub expire_at: Option<OffsetDateTime>,
pub expires_at: Option<OffsetDateTime>,

/// The memo associated with the account.
pub memo: Option<String>,
Expand All @@ -63,6 +63,12 @@ impl AccountUpdateTransaction {
self
}

/// Sets the new expiration time to extend to (ignored if equal to or before the current one).
pub fn expires_at(&mut self, at: OffsetDateTime) -> &mut Self {
self.body.data.expires_at = Some(at);
self
}

/// Set the key for this account.
pub fn key(&mut self, key: impl Into<Key>) -> &mut Self {
self.body.data.key = Some(key.into());
Expand Down Expand Up @@ -126,7 +132,7 @@ impl ToTransactionDataProtobuf for AccountUpdateTransactionData {
let account_id = self.account_id.as_ref().map(AccountIdOrAlias::to_protobuf);
let key = self.key.as_ref().map(Key::to_protobuf);
let auto_renew_period = self.auto_renew_period.as_ref().map(Duration::to_protobuf);
let expiration_time = self.expire_at.as_ref().map(OffsetDateTime::to_protobuf);
let expiration_time = self.expires_at.as_ref().map(OffsetDateTime::to_protobuf);

let receiver_signature_required = self.receiver_signature_required.map(|required| {
services::crypto_update_transaction_body::ReceiverSigRequiredField::ReceiverSigRequiredWrapper(required)
Expand Down
4 changes: 3 additions & 1 deletion sdk/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ pub use schedule::ScheduleId;
pub use signature::{Signature, SignaturePair};
pub use signer::Signer;
pub use token::TokenId;
pub use topic::TopicId;
pub use topic::{
TopicCreateTransaction, TopicDeleteTransaction, TopicId, TopicMessageSubmitTransaction, TopicUpdateTransaction
};
pub use transaction::Transaction;
pub use transaction_hash::TransactionHash;
pub use transaction_id::TransactionId;
Expand Down
6 changes: 5 additions & 1 deletion sdk/rust/src/schedule/schedule_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ impl FromProtobuf for ScheduleId {
type Protobuf = services::ScheduleId;

fn from_protobuf(pb: Self::Protobuf) -> crate::Result<Self> {
Ok(Self { num: pb.schedule_num as u64, shard: pb.shard_num as u64, realm: pb.realm_num as u64 })
Ok(Self {
num: pb.schedule_num as u64,
shard: pb.shard_num as u64,
realm: pb.realm_num as u64,
})
}
}
6 changes: 5 additions & 1 deletion sdk/rust/src/token/token_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ impl FromProtobuf for TokenId {
type Protobuf = services::TokenId;

fn from_protobuf(pb: Self::Protobuf) -> crate::Result<Self> {
Ok(Self { num: pb.token_num as u64, shard: pb.shard_num as u64, realm: pb.realm_num as u64 })
Ok(Self {
num: pb.token_num as u64,
shard: pb.shard_num as u64,
realm: pb.realm_num as u64,
})
}
}
12 changes: 12 additions & 0 deletions sdk/rust/src/topic/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
mod topic_create_transaction;
mod topic_delete_transaction;
mod topic_id;
mod topic_message_submit_transaction;
mod topic_update_transaction;

pub use topic_create_transaction::TopicCreateTransaction;
pub(crate) use topic_create_transaction::TopicCreateTransactionData;
pub use topic_delete_transaction::TopicDeleteTransaction;
pub(crate) use topic_delete_transaction::TopicDeleteTransactionData;
pub use topic_id::TopicId;
pub use topic_message_submit_transaction::TopicMessageSubmitTransaction;
pub(crate) use topic_message_submit_transaction::TopicMessageSubmitTransactionData;
pub use topic_update_transaction::TopicUpdateTransaction;
pub(crate) use topic_update_transaction::TopicUpdateTransactionData;
119 changes: 119 additions & 0 deletions sdk/rust/src/topic/topic_create_transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use async_trait::async_trait;
use hedera_proto::services;
use hedera_proto::services::consensus_service_client::ConsensusServiceClient;
use serde_with::skip_serializing_none;
use time::Duration;
use tonic::transport::Channel;

use crate::protobuf::ToProtobuf;
use crate::transaction::{AnyTransactionData, ToTransactionDataProtobuf, TransactionExecute};
use crate::{AccountId, Key, Transaction, TransactionId};

/// Create a topic to be used for consensus.
///
/// If an `auto_renew_account` is specified, that account must also sign this transaction.
///
/// If an `admin_key` is specified, the adminKey must sign the transaction.
///
/// On success, the resulting `TransactionReceipt` contains the newly created `TopicId`.
///
pub type TopicCreateTransaction = Transaction<TopicCreateTransactionData>;

#[skip_serializing_none]
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TopicCreateTransactionData {
/// Short publicly visible memo about the topic. No guarantee of uniqueness.
#[serde(skip_serializing_if = "String::is_empty")]
topic_memo: String,

/// Access control for `TopicUpdateTransaction` and `TopicDeleteTransaction`.
admin_key: Option<Key>,

/// Access control for `TopicMessageSubmitTransaction`.
submit_key: Option<Key>,

/// The initial lifetime of the topic and the amount of time to attempt to
/// extend the topic's lifetime by automatically at the topic's expiration time, if
/// the `auto_renew_account_id` is configured.
auto_renew_period: Option<Duration>,

/// Optional account to be used at the topic's expiration time to extend the life of the topic.
auto_renew_account_id: Option<AccountId>,
}

impl TopicCreateTransaction {
/// Sets the short publicly visible memo about the topic.
///
/// No guarantee of uniqueness.
///
pub fn topic_memo(&mut self, memo: impl Into<String>) -> &mut Self {
self.body.data.topic_memo = memo.into();
self
}

/// Sets the access control for `TopicUpdateTransaction` and `TopicDeleteTransaction`.
pub fn admin_key(&mut self, key: impl Into<Key>) -> &mut Self {
self.body.data.admin_key = Some(key.into());
self
}

/// Sets the access control for `TopicMessageSubmitTransaction`.
pub fn submit_key(&mut self, key: impl Into<Key>) -> &mut Self {
self.body.data.submit_key = Some(key.into());
self
}

/// Sets the initial lifetime of the topic and the amount of time to attempt to
/// extend the topic's lifetime by automatically at the topic's expiration time.
pub fn auto_renew_period(&mut self, period: Duration) -> &mut Self {
self.body.data.auto_renew_period = Some(period);
self
}

/// Sets the account to be used at the topic's expiration time to extend the life of the topic.
pub fn auto_renew_account_id(&mut self, id: impl Into<AccountId>) -> &mut Self {
self.body.data.auto_renew_account_id = Some(id.into());
self
}
}

#[async_trait]
impl TransactionExecute for TopicCreateTransactionData {
async fn execute(
&self,
channel: Channel,
request: services::Transaction,
) -> Result<tonic::Response<services::TransactionResponse>, tonic::Status> {
ConsensusServiceClient::new(channel).create_topic(request).await
}
}

impl ToTransactionDataProtobuf for TopicCreateTransactionData {
fn to_transaction_data_protobuf(
&self,
_node_account_id: AccountId,
_transaction_id: &TransactionId,
) -> services::transaction_body::Data {
let admin_key = self.admin_key.as_ref().map(Key::to_protobuf);
let submit_key = self.submit_key.as_ref().map(Key::to_protobuf);
let auto_renew_period = self.auto_renew_period.as_ref().map(Duration::to_protobuf);
let auto_renew_account_id = self.auto_renew_account_id.as_ref().map(AccountId::to_protobuf);

services::transaction_body::Data::ConsensusCreateTopic(
services::ConsensusCreateTopicTransactionBody {
auto_renew_account: auto_renew_account_id,
memo: self.topic_memo.clone(),
admin_key,
submit_key,
auto_renew_period,
},
)
}
}

impl From<TopicCreateTransactionData> for AnyTransactionData {
fn from(transaction: TopicCreateTransactionData) -> Self {
Self::TopicCreate(transaction)
}
}
65 changes: 65 additions & 0 deletions sdk/rust/src/topic/topic_delete_transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use async_trait::async_trait;
use hedera_proto::services;
use hedera_proto::services::consensus_service_client::ConsensusServiceClient;
use serde_with::skip_serializing_none;
use tonic::transport::Channel;

use crate::protobuf::ToProtobuf;
use crate::transaction::{AnyTransactionData, ToTransactionDataProtobuf, TransactionExecute};
use crate::{AccountId, TopicId, Transaction, TransactionId};

/// Delete a topic.
///
/// No more transactions or queries on the topic will succeed.
///
/// If an `admin_key` is set, this transaction must be signed by that key.
/// If there is no `admin_key`, this transaction will fail `UNAUTHORIZED`.
///
pub type TopicDeleteTransaction = Transaction<TopicDeleteTransactionData>;

#[skip_serializing_none]
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TopicDeleteTransactionData {
/// The topic ID which is being deleted in this transaction.
topic_id: Option<TopicId>,
}

impl TopicDeleteTransaction {
/// Set the account ID which is being deleted.
pub fn topic_id(&mut self, id: impl Into<TopicId>) -> &mut Self {
self.body.data.topic_id = Some(id.into());
self
}
}

#[async_trait]
impl TransactionExecute for TopicDeleteTransactionData {
async fn execute(
&self,
channel: Channel,
request: services::Transaction,
) -> Result<tonic::Response<services::TransactionResponse>, tonic::Status> {
ConsensusServiceClient::new(channel).delete_topic(request).await
}
}

impl ToTransactionDataProtobuf for TopicDeleteTransactionData {
fn to_transaction_data_protobuf(
&self,
_node_account_id: AccountId,
_transaction_id: &TransactionId,
) -> services::transaction_body::Data {
let topic_id = self.topic_id.as_ref().map(TopicId::to_protobuf);

services::transaction_body::Data::ConsensusDeleteTopic(
services::ConsensusDeleteTopicTransactionBody { topic_id },
)
}
}

impl From<TopicDeleteTransactionData> for AnyTransactionData {
fn from(transaction: TopicDeleteTransactionData) -> Self {
Self::TopicDelete(transaction)
}
}
20 changes: 18 additions & 2 deletions sdk/rust/src/topic/topic_id.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use hedera_proto::services;

use crate::FromProtobuf;
use crate::{FromProtobuf, ToProtobuf};

/// The unique identifier for a topic on Hedera.
#[derive(Debug, serde::Serialize, serde::Deserialize, Hash, PartialEq, Eq, Clone, Copy)]
Expand All @@ -15,6 +15,22 @@ impl FromProtobuf for TopicId {
type Protobuf = services::TopicId;

fn from_protobuf(pb: Self::Protobuf) -> crate::Result<Self> {
Ok(Self { num: pb.topic_num as u64, shard: pb.shard_num as u64, realm: pb.realm_num as u64 })
Ok(Self {
num: pb.topic_num as u64,
shard: pb.shard_num as u64,
realm: pb.realm_num as u64,
})
}
}

impl ToProtobuf for TopicId {
type Protobuf = services::TopicId;

fn to_protobuf(&self) -> Self::Protobuf {
services::TopicId {
topic_num: self.num as i64,
realm_num: self.realm as i64,
shard_num: self.shard as i64,
}
}
}
Loading

0 comments on commit f7fd9b0

Please sign in to comment.