Skip to content

Commit

Permalink
feat(tck): add AccountCreateTransaction
Browse files Browse the repository at this point in the history
Signed-off-by: Ricky Saechao <[email protected]>
  • Loading branch information
RickyLB committed Oct 29, 2024
1 parent fe5f90b commit 16b50f8
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 3 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions tck/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ tower-http = { version = "0.5.2", features = ["full"] }
hedera = { path = "../." }
once_cell = "1.19.0"
futures-util = "0.3.30"
serde_json = "1.0.1"
serde = { version = "1.0.181", features = ["derive"] }
time = "0.3.9"


[dependencies.jsonrpsee]
version = "0.23.2"
Expand Down
47 changes: 47 additions & 0 deletions tck/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use std::str::FromStr;

#[derive(Debug, Clone)]
#[derive(Serialize, Deserialize)]
pub enum TransactionParamValue {
String(String),
I64(i64),
Bool(bool),
Array(Vec<String>),
Map(HashMap<String, String>)
}

impl FromStr for TransactionParamValue {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// Try parsing as i64
if let Ok(i) = s.parse::<i64>() {
return Ok(TransactionParamValue::I64(i));
}

// Try parsing as bool
if let Ok(b) = s.parse::<bool>() {
return Ok(TransactionParamValue::Bool(b));
}

// Try parsing as JSON array
if s.starts_with('[') && s.ends_with(']') {
if let Ok(array) = serde_json::from_str::<Vec<String>>(s) {
return Ok(TransactionParamValue::Array(array));
}
}

// Try parsing as JSON map
if s.starts_with('{') && s.ends_with('}') {
if let Ok(map) = serde_json::from_str::<HashMap<String, String>>(s) {
return Ok(TransactionParamValue::Map(map));
}
}

// Default to String
Ok(TransactionParamValue::String(s.to_string()))
}
}
1 change: 1 addition & 0 deletions tck/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use sdk_client::{
use tokio::signal;

pub(crate) mod sdk_client;
mod helpers;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
Expand Down
164 changes: 161 additions & 3 deletions tck/src/sdk_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ use std::sync::{
};

use hedera::{
AccountId,
Client,
PrivateKey,
AccountCreateTransaction, AccountId, EntityId, Client, EvmAddress, Hbar, PrivateKey, Transaction, TransactionId
};

use jsonrpsee::core::async_trait;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::types::error::PARSE_ERROR_CODE;
use jsonrpsee::types::{
ErrorObject,
ErrorObjectOwned,
};
use once_cell::sync::Lazy;
use time::Duration;

use crate::helpers::TransactionParamValue;

static GLOBAL_SDK_CLIENT: Lazy<Arc<Mutex<Option<Client>>>> =
Lazy::new(|| Arc::new(Mutex::new(None)));
Expand All @@ -41,6 +44,22 @@ pub trait Rpc {

#[method(name = "reset")]
fn reset(&self) -> Result<HashMap<String, String>, ErrorObjectOwned>;

#[method(name = "createAccount")]
fn create_account(
&self,
key: Option<String>,
initial_balance: Option<i64>,
receiver_signature_required: Option<bool>,
auto_renew_period: Option<i64>,
memo: Option<String>,
max_automatic_token_associations: Option<i64>,
staked_account_id: Option<String>,
alias: Option<String>,
staked_node_id: Option<i64>,
declining_staking_reward: Option<bool>,
common_transaction_params: Option<HashMap<String, TransactionParamValue>>,
) -> Result<String, ErrorObjectOwned>;
}

pub struct RpcServerImpl;
Expand Down Expand Up @@ -134,4 +153,143 @@ impl RpcServer for RpcServerImpl {
*global_client = None;
Ok(HashMap::from([("status".to_string(), "SUCCESS".to_string())].to_owned()))
}

fn create_account(
&self,
key: Option<String>,
initial_balance: Option<i64>,
receiver_signature_required: Option<bool>,
auto_renew_period: Option<i64>,
memo: Option<String>,
max_automatic_token_associations: Option<i64>,
staked_account_id: Option<String>,
alias: Option<String>,
staked_node_id: Option<i64>,
decline_staking_reward: Option<bool>,
common_transaction_params: Option<HashMap<String, TransactionParamValue>>,
) -> Result<String, ErrorObjectOwned> {
let client = GLOBAL_SDK_CLIENT.lock().unwrap();
let client = client.as_ref().ok_or_else(|| {
ErrorObject::owned(-32603, "Client not initialized".to_string(), None::<()>)
})?;

let mut account_create_tx = AccountCreateTransaction::new();

if let Some(key) = key {
let private_key = PrivateKey::from_str(&key)
.map_err(|e| ErrorObject::owned(-32603, e.to_string(), None::<()>))?;
let public_key = private_key.public_key();
account_create_tx.key(public_key);
}

if let Some(initial_balance) = initial_balance {
account_create_tx.initial_balance(Hbar::new(initial_balance));
}

if let Some(receiver_signature_required) = receiver_signature_required {
account_create_tx.receiver_signature_required(receiver_signature_required);
}

if let Some(auto_renew_period) = auto_renew_period {
account_create_tx.auto_renew_period(Duration::seconds(auto_renew_period));
}
if let Some(memo) = memo {
account_create_tx.account_memo(memo);
}

if let Some(max_automatic_token_associations) = max_automatic_token_associations {
account_create_tx.max_automatic_token_associations(max_automatic_token_associations as i32);
}

if let Some(staked_account_id) = staked_account_id {
account_create_tx.staked_account_id(AccountId::from_str(&staked_account_id).unwrap());
}

if let Some(alias) = alias {
account_create_tx.alias(EvmAddress::from_str(&alias).map_err(|e| ErrorObject::owned(PARSE_ERROR_CODE, e.to_string(), None::<()>))?);
}

if let Some(staked_node_id) = staked_node_id {
account_create_tx.staked_node_id(staked_node_id as u64);
}

if let Some(decline_staking_reward) = decline_staking_reward {
account_create_tx.decline_staking_reward(decline_staking_reward);
}

if let Some(common_transaction_params) = common_transaction_params {
fill_common_transaction_params(client, &mut account_create_tx, &common_transaction_params);

account_create_tx.freeze_with(client).unwrap();

if let Some(signers) = common_transaction_params.get("signers") {
match signers {
TransactionParamValue::Array(signers) => {
for signer in signers {
account_create_tx.sign(PrivateKey::from_str_der(signer).unwrap());
}
},
_ => {}
}
}
}




Ok("SUCCESS".to_owned())
}

}

fn fill_common_transaction_params<D>(
client: &Client,
transaction: &mut Transaction<D>,
common_transaction_params: &HashMap<String, TransactionParamValue>,
) -> Result<String, ErrorObjectOwned>
{
if let Some(transaction_id) = common_transaction_params.get("transactionId") {
match transaction_id {
TransactionParamValue::String(transaction_id) => {
transaction.transaction_id(TransactionId::from_str(transaction_id.as_str()).unwrap());
}
_ => {}
}
}

if let Some(node_id) = common_transaction_params.get("nodeId") {
match node_id {
TransactionParamValue::String(node_id) => {
transaction.node_account_ids([AccountId::from_str(&node_id.as_str()).unwrap()]);
}
_ => {}
}
}

if let Some(max_fee) = common_transaction_params.get("maxTransactionFee") {
match max_fee {
TransactionParamValue::String(max_fee) => {
transaction.max_transaction_fee(Hbar::from_tinybars(max_fee.as_str().parse::<i64>().unwrap()));
}
_ => {}
}
}

if let Some(transaction_valid_duration) = common_transaction_params.get("transactionValidDuration") {
match transaction_valid_duration {
TransactionParamValue::String(transaction_valid_duration) => {
transaction.transaction_valid_duration(Duration::seconds(transaction_valid_duration.as_str().parse::<i64>().unwrap()));
}
_ => {}
}
}

if let Some(memo) = common_transaction_params.get("memo") {
match memo {
TransactionParamValue::String(memo) => {
transaction.transaction_memo(memo.as_str());
}
_ => {}
}
}
}

0 comments on commit 16b50f8

Please sign in to comment.